Google Ads API: การตั้งค่า การยืนยันตัวตน การอ่านและเขียนข้อมูล
คู่มือทางเทคนิคสำหรับการตั้งค่าการเข้าถึง Google Ads ผ่านโปรแกรม — ตั้งแต่สถาปัตยกรรมไปจนถึงการเรียก API ครั้งแรก ครอบคลุมการกำหนดค่า MCC, OAuth 2.0, ระดับ Developer Token, ไลบรารี google-ads สำหรับ Python, การอ่านข้อมูลด้วย GAQL และรูปแบบการเขียนแบบ validate_only
อัปเดต (ตุลาคม 2026): Google ยกเลิกโทเคนนักพัฒนาซอฟต์แวร์เมื่อวันที่ 9 กันยายน 2026 ปัจจุบันระดับการเข้าถึง API กำหนดแยกตามโครงการ Google Cloud และจัดการในหน้า Overview ของ Google Ads API ใน Cloud Console ส่วนหัว developer-token เป็นตัวเลือกและจะถูกละเว้น ส่วน API Center ไม่รับลงทะเบียนหรือเปลี่ยนระดับการเข้าถึงแล้ว Google ระบุว่าโค้ดเดิมยังทำงานได้ ขั้นตอนเกี่ยวกับโทเคนนักพัฒนาซอฟต์แวร์และ API Center ด้านล่างอธิบายการตั้งค่า ณ วันที่เผยแพร่ในเดือนมิถุนายน 2026 การตั้งค่าในปัจจุบันอธิบายไว้ในบทความต่อเนื่อง การเข้าถึง Google Ads API ในปี 2026: โปรเจกต์ Cloud มาแทนที่ Developer Token
สถาปัตยกรรม
ต้องมีองค์ประกอบสามอย่างแยกกันก่อนที่จะเรียก API ได้:
| องค์ประกอบ | วัตถุประสงค์ | ตัวอย่าง |
|---|---|---|
| Manager Account (MCC) | ออก Developer Token | login_customer_id |
| Google Cloud Project | ไคลเอนต์ OAuth 2.0 สำหรับการยืนยันตัวตน | Client ID + Secret |
| Google Ads Account | เป้าหมายของการดำเนินการ API ทั้งหมด | customer_id |
องค์ประกอบเหล่านี้ไม่ใช่บัญชีเดียวกัน MCC เป็นเจ้าของ Developer Token ได้โดยไม่ต้องเป็นเจ้าของบัญชีเป้าหมาย เพียงเชื่อมโยงเป็นบัญชีผู้จัดการ Google Cloud Project อาจใช้บัญชี Google คนละบัญชีกับ MCC ส่วนบัญชีเป้าหมายคือบัญชีผู้โฆษณาที่มีแคมเปญอยู่
การแยกส่วนนี้มีความสำคัญเนื่องจาก API Center (ที่ออก Developer Token) มีให้ใช้งานเฉพาะภายใน Manager Accounts เท่านั้น บัญชี Google Ads แบบเดี่ยวไม่สามารถเข้าถึง API Center ได้ แม้ว่าจะมีผู้ใช้ระดับผู้ดูแลระบบก็ตาม
ส่วนหัวของคำขอ API ประกอบด้วยข้อมูลระบุตัวตนทั้งสามส่วนนี้และโทเคน OAuth Bearer:
developer-token: <from MCC API Center>
login-customer-id: <MCC numeric ID, no dashes>
customer-id: <target account numeric ID>
Authorization: Bearer <OAuth 2.0 access token>
ข้อกำหนดเบื้องต้น
- Google Ads Manager Account ที่ตั้งค่าเสร็จสมบูรณ์แล้ว
- บัญชีโฆษณาเป้าหมายที่เชื่อมโยงกับ Manager Account และยอมรับการเชื่อมโยงแล้ว
- Google Cloud Project ที่เปิดใช้งาน Google Ads API แล้ว
- Python 3.9+ พร้อมไลบรารี
google-ads(pip install google-ads) - เบราว์เซอร์สำหรับขั้นตอนการให้ความยินยอมผ่าน OAuth เพียงครั้งเดียว
ขั้นตอนที่ 1: Manager Account และ Developer Token
API Center อยู่ภายใต้ Tools & Settings → Setup → API Center ภายใน Manager Account หากไม่พบ API Center แสดงว่าบัญชีนั้นไม่ใช่ Manager Account หรือการตั้งค่ายังไม่สมบูรณ์
ขอ Developer Token จาก API Center หากใช้โทเคนกับบัญชีของคุณเอง ให้ตั้งประเภทบัญชีเป็น Advertiser ไม่ใช่ Agency หรือ Third-Party ระบบจะออกโทเคนให้ทันทีในระดับ Test Access
Test Access อนุญาตให้:
- อ่านข้อมูลจากบัญชีทดสอบเท่านั้น
- เขียนข้อมูลใน บัญชีทดสอบเท่านั้น
- ไม่อนุญาตให้อ่านหรือเขียนข้อมูลในบัญชีใช้งานจริง
คำขอที่ส่งไปยังบัญชีใช้งานจริงด้วย Test Access จะล้มเหลวด้วย DEVELOPER_TOKEN_NOT_APPROVED (“The developer token is only approved for use with test accounts”) หลังการยกเลิกในเดือนกันยายน 2026 API เวอร์ชันปัจจุบันจะส่งคืน CLOUD_PROJECT_NOT_APPROVED_FOR_PRODUCTION แทน (ACTION_NOT_PERMITTED ใน v24 และเวอร์ชันก่อนหน้า)
การสมัคร Basic Access
หากต้องการเข้าถึงบัญชีใช้งานจริง ให้สมัคร Basic Access จากหน้า API Center เดียวกัน แบบฟอร์มการสมัครประกอบด้วยคำถาม 12 ข้อ สำหรับการใช้งานภายในกับบัญชีของคุณเอง คำตอบที่เกี่ยวข้องคือ:
| คำถาม | คำตอบ |
|---|---|
| Q4: ความสัมพันธ์กับ ตัวแทน Google | ไม่ |
| Q6: รูปแบบธุรกิจ | อธิบายกรณีใช้งานของคุณเอง (อีคอมเมิร์ซ การหาผู้มีโอกาสเป็นลูกค้า การรายงานภายใน) |
| Q8: ใครจะมีสิทธิ์เข้าถึง | ผู้ใช้ภายใน — เฉพาะพนักงาน |
| Q9: เครื่องมือที่พัฒนาโดยบุคคลที่สาม | ไม่ (ใช้สคริปต์หรือเอเจนต์ของตัวเอง) |
| Q10: Conversion Tracking & Remarketing API | ไม่ (เว้นแต่คุณใช้งานจริง) |
| Q11: ประเภทแคมเปญ | Search, Performance Max, Shopping (ตามที่เกี่ยวข้อง) |
| Q12: ขีดความสามารถ | การสร้างแคมเปญ การจัดการแคมเปญ การรายงาน |
Q7 ต้องใช้เอกสารออกแบบในรูปแบบ PDF โดยอธิบายสถาปัตยกรรม API ขั้นตอนการยืนยันตัวตน กลยุทธ์การจำกัดอัตราการเรียกใช้ การจัดการข้อผิดพลาด และกรณีการใช้งานภายในเท่านั้น ให้เขียนตามข้อเท็จจริง เพราะทีมตรวจสอบการปฏิบัติตามกฎระเบียบจะประเมินความสอดคล้องกับกรณีการใช้งานที่แจ้งไว้
ระยะเวลาดำเนินการ ณ เดือนมิถุนายน 2026: ประมาณ 3 วันทำการ พร้อมหมายเหตุเกี่ยวกับปริมาณการสมัครที่สูงกว่าปกติ
ขั้นตอนที่ 2: OAuth 2.0
การตั้งค่า Google Cloud Project
ใน Google Cloud Console ภายใต้โครงการที่เกี่ยวข้อง:
- เปิดใช้งาน Google Ads API (APIs & Services → Library)
- กำหนดค่า OAuth consent screen:
- User Type: Internal (เฉพาะผู้ใช้ใน Google Workspace ของคุณเท่านั้นที่ให้สิทธิ์ได้ โดยไม่ต้องผ่านการตรวจสอบแอปสำหรับผู้ใช้ภายนอก)
- ชื่อแอป อีเมลฝ่ายช่วยเหลือ และอีเมลติดต่อนักพัฒนา
- เพิ่มขอบเขตสิทธิ์ใน Data Access:
https://www.googleapis.com/auth/adwords - สร้าง OAuth Client ID:
- Application type: Desktop app
- ดาวน์โหลดไฟล์ JSON ที่มี client secret
แอปประเภท Desktop app ใช้ http://localhost เป็น URI สำหรับเปลี่ยนเส้นทาง ซึ่งเป็นค่าที่ถูกต้อง ขั้นตอน OAuth จะเปิดเบราว์เซอร์ จากนั้น Google จะเปลี่ยนเส้นทางไปยัง localhost พร้อมรหัสอนุญาต และเซิร์ฟเวอร์ HTTP ในเครื่องจะรับรหัสนั้น
การสร้างโทเคนรีเฟรช
สคริปต์ Python ขั้นพื้นฐานนี้รันเซิร์ฟเวอร์ HTTP ในเครื่องบน 127.0.0.1:0 (พอร์ตสุ่ม) แสดง URL สำหรับขออนุญาต รอคำขอหนึ่งรายการ ดึงพารามิเตอร์ code และแลกเป็นโทเคน โดยยังไม่ตรวจสอบพารามิเตอร์ state ที่ส่งกลับหรือกำหนดสิทธิ์ของไฟล์โทเคน ต้องเพิ่มทั้งสองส่วนก่อนนำไปใช้นอกเหนือจากการรันในเครื่องเพียงครั้งเดียว:
from pathlib import Path
from http.server import HTTPServer, BaseHTTPRequestHandler
from urllib.parse import urlparse, parse_qs
from google_auth_oauthlib.flow import Flow
class CallbackHandler(BaseHTTPRequestHandler):
code_value = None
def do_GET(self):
qs = parse_qs(urlparse(self.path).query)
CallbackHandler.code_value = (qs.get('code') or [None])[0]
self.send_response(200)
self.end_headers()
self.wfile.write(b'OAuth complete.')
def log_message(self, format, *args):
return
server = HTTPServer(('127.0.0.1', 0), CallbackHandler)
redirect_uri = f'http://127.0.0.1:{server.server_port}/'
flow = Flow.from_client_secrets_file(
'client_secret.json',
scopes=['https://www.googleapis.com/auth/adwords'],
redirect_uri=redirect_uri
)
auth_url, _ = flow.authorization_url(
access_type='offline',
prompt='consent'
)
print(auth_url)
server.handle_request()
flow.fetch_token(code=CallbackHandler.code_value)
Path('google_ads_token.json').write_text(flow.credentials.to_json())
พารามิเตอร์สองตัวที่มีความสำคัญ:
access_type='offline'— ส่งคืนโทเคนรีเฟรช ไม่ใช่เพียงโทเคนสำหรับเข้าถึงprompt='consent'— บังคับให้แสดงหน้าจอขอความยินยอมใหม่ แม้ผู้ใช้เคยให้สิทธิ์แล้ว จำเป็นเมื่อต้องการโทเคนรีเฟรชใหม่หลังเปลี่ยนขอบเขตสิทธิ์
โทเคนรีเฟรชไม่มีอายุใช้งานตายตัว แต่จะใช้ไม่ได้หากผู้ใช้เพิกถอนสิทธิ์การเข้าถึง ไม่ได้ใช้โทเคนเป็นเวลา 6 เดือน ผู้ใช้เปลี่ยนรหัสผ่าน (สำหรับโทเคนที่มีขอบเขตสิทธิ์ Gmail) บัญชีมีโทเคนรีเฟรชที่ยังใช้งานได้เกินขีดจำกัดของ Google หรือผู้ดูแล Workspace จำกัดขอบเขตสิทธิ์หรือกำหนดระยะเวลาเซสชัน ควรเตรียมพร้อมสำหรับการขออนุญาตใหม่
ปัญหาขอบเขตสิทธิ์กับไคลเอนต์ที่มีอยู่เดิม
หาก URL สำหรับขออนุญาตกำหนด include_granted_scopes=true และผู้ใช้เคยให้สิทธิ์ไคลเอนต์ OAuth นี้สำหรับขอบเขตอื่น เช่น Gmail, Drive หรือ Calendar มาก่อน Google จะส่งคืนขอบเขตสิทธิ์เดิมรวมกับขอบเขตใหม่ โดยค่าเริ่มต้น ไลบรารี google-auth-oauthlib จะปฏิเสธขอบเขตสิทธิ์ที่ไม่ตรงกันนี้ ให้ตั้งค่าตัวแปรสภาพแวดล้อมก่อนโหลดขั้นตอน OAuth:
import os
os.environ['OAUTHLIB_RELAX_TOKEN_SCOPE'] = '1'
อีกทางเลือกคือไม่ใส่ include_granted_scopes=true ใน URL สำหรับขออนุญาต (สคริปต์ด้านบนไม่ได้กำหนดค่านี้) เพื่อให้โทเคนครอบคลุมเฉพาะขอบเขตสิทธิ์ที่ร้องขออย่างชัดเจน
ขั้นตอนที่ 3: google-ads.yaml
ไลบรารีอ่านการกำหนดค่าจากไฟล์ YAML:
developer_token: <value>
client_id: <value>
client_secret: <value>
refresh_token: <value>
login_customer_id: 1911599764
use_proto_plus: true
กฎความปลอดภัย:
- สิทธิ์ของไฟล์:
0600(เจ้าของอ่าน/เขียนเท่านั้น) - ห้ามบันทึกไฟล์เข้าระบบควบคุมเวอร์ชัน
- เก็บไฟล์ไว้นอกรีโพซิทอรี Git ทุกแห่ง
- เมื่อใช้งานเป็นทีม ให้แจกจ่ายผ่านระบบจัดการข้อมูลลับ แทนการใช้ไฟล์ร่วมกัน
login_customer_id คือรหัส MCC ที่เป็นตัวเลขโดยไม่มีขีดคั่น ใช้บอก API ว่าผู้ใช้ที่ยืนยันตัวตนแล้วเข้าถึงบัญชีเป้าหมายผ่านบัญชีผู้จัดการใด และจำเป็นทุกครั้งที่เข้าถึงผ่านบัญชีผู้จัดการ ส่วน customer_id ของบัญชีเป้าหมายจะส่งเมื่อเรียก API ไม่ได้ระบุในไฟล์กำหนดค่า
use_proto_plus เป็นคีย์กำหนดค่าที่จำเป็น: true เลือกอินเทอร์เฟซข้อความ proto-plus ที่ใช้ในคู่มือนี้ ส่วน false เลือกข้อความ protobuf แบบปกติ ซึ่ง Google แนะนำสำหรับงานที่ต้องการประสิทธิภาพสูง
ขั้นตอนที่ 4: การเริ่มต้นไคลเอนต์ Python
from google.ads.googleads.client import GoogleAdsClient
client = GoogleAdsClient.load_from_storage(
'/path/to/google-ads.yaml',
version='v22'
)
gs = client.get_service('GoogleAdsService')
พารามิเตอร์ version เลือกเวอร์ชัน API อย่างชัดเจน ไลบรารี google-ads มาพร้อมกับหลายเวอร์ชันที่ติดตั้งแบบขนาน ตัวอย่างในบทความนี้ใช้ v22 ณ เดือนตุลาคม 2026 ไลบรารีรุ่นปัจจุบันไม่รวม v22 แล้ว (นำออกใน 33.0.0) และ 34.0.0 เพิ่ม v26 จึงควรเปลี่ยนไปใช้เวอร์ชันปัจจุบัน ควรระบุเวอร์ชันเสมอ — ค่าเริ่มต้นอาจล้าหลังหรือไม่รองรับฟิลด์ใหม่กว่า
ตรวจสอบการเชื่อมต่อ:
cs = client.get_service('CustomerService')
customers = cs.list_accessible_customers()
ids = [r.split('/')[-1] for r in customers.resource_names]
# Example output: ['1305475941', '3977581086', '1911599764']
ขั้นตอนที่ 5: การดำเนินการอ่าน (GAQL)
Google Ads ใช้ GAQL (Google Ads Query Language) ซึ่งมีไวยากรณ์คล้าย SQL การอ่านข้อมูลทั้งหมดใช้ GoogleAdsService.search_stream() ซึ่งไม่ต้องจัดการการแบ่งหน้าและเหมาะกว่า search() สำหรับคำสั่งสืบค้นส่วนใหญ่
แคมเปญพร้อมตัวชี้วัดผลการดำเนินงาน
SELECT
campaign.id,
campaign.name,
campaign.status,
campaign.advertising_channel_type,
campaign.serving_status,
campaign.bidding_strategy_type,
metrics.impressions,
metrics.clicks,
metrics.cost_micros,
metrics.conversions,
metrics.conversions_value,
metrics.ctr,
metrics.average_cpc
FROM campaign
ORDER BY campaign.id
งบประมาณแคมเปญ
SELECT
campaign_budget.id,
campaign_budget.name,
campaign_budget.amount_micros,
campaign_budget.delivery_method,
campaign_budget.status,
campaign.id,
campaign.name
FROM campaign_budget
กลุ่มโฆษณา
SELECT
ad_group.id,
ad_group.name,
ad_group.status,
ad_group.cpc_bid_micros,
campaign.id,
campaign.name
FROM ad_group
ORDER BY campaign.id, ad_group.id
คีย์เวิร์ด (เรียงตามจำนวนการแสดงผล)
SELECT
ad_group_criterion.keyword.text,
ad_group_criterion.keyword.match_type,
ad_group_criterion.status,
ad_group_criterion.criterion_id,
ad_group.id,
ad_group.name,
campaign.id,
campaign.name,
metrics.impressions,
metrics.clicks,
metrics.cost_micros,
metrics.conversions
FROM keyword_view
WHERE ad_group_criterion.type = 'KEYWORD'
ORDER BY metrics.impressions DESC
LIMIT 100
โฆษณาพร้อมสถานะการปฏิบัติตามนโยบาย
SELECT
ad_group_ad.ad.id,
ad_group_ad.ad.name,
ad_group_ad.ad.type,
ad_group_ad.status,
ad_group_ad.policy_summary.approval_status,
ad_group.id,
ad_group.name,
campaign.id,
campaign.name
FROM ad_group_ad
การกระทำที่นับเป็นคอนเวอร์ชัน
SELECT
conversion_action.id,
conversion_action.name,
conversion_action.status,
conversion_action.type,
conversion_action.category,
conversion_action.include_in_conversions_metric,
conversion_action.counting_type
FROM conversion_action
รูปแบบการเรียกใช้ใน Python
def gaql_query(client, customer_id, query):
gs = client.get_service('GoogleAdsService')
results = []
for batch in gs.search_stream(customer_id=customer_id, query=query):
for row in batch.results:
results.append(row)
return results
ขั้นตอนที่ 6: การดำเนินการเขียนด้วย validate_only
ตัวอย่างด้านล่างใช้ออบเจ็กต์คำขอแทนอาร์กิวเมนต์แบบระบุชื่อ เพราะออบเจ็กต์คำขอใช้ส่งค่า validate_only บริการเปลี่ยนแปลงข้อมูลทุกบริการ (CampaignService, AdGroupService, AdGroupCriterionService, CampaignBudgetService) ใช้รูปแบบเดียวกัน:
from google.protobuf import field_mask_pb2
req = client.get_type('MutateCampaignsRequest')
req.customer_id = '1305475941'
req.validate_only = True
op = client.get_type('CampaignOperation')
op.create.name = 'Campaign Name'
op.create.status = client.enums.CampaignStatusEnum.PAUSED
op.create.advertising_channel_type = client.enums.AdvertisingChannelTypeEnum.SEARCH
op.create.campaign_budget = 'customers/1305475941/campaignBudgets/123456789'
op.create.manual_cpc.enhanced_cpc_enabled = False
req.operations.append(op) # .append(), not .add()
client.get_service('CampaignService').mutate_campaigns(request=req)
ประเด็นสำคัญของรูปแบบนี้ (เมื่อใช้ use_proto_plus: true):
validate_onlyเป็นฟิลด์ในออบเจ็กต์คำขอ ไม่ใช่อาร์กิวเมนต์แบบระบุชื่อที่ส่งให้เมธอด mutate- เพิ่มรายการดำเนินการผ่าน
req.operations.append(op)ส่วน.add()ใช้กับอินเทอร์เฟซ protobuf แบบปกติ (use_proto_plus: false) - ในตัวอย่างนี้ระบุพาธทรัพยากรเป็นสตริงโดยตรง (
'customers/1305475941/campaigns/22479990461') แต่บริการยังมีตัวช่วยสร้างพาธ เช่นcampaign_service.campaign_path(customer_id, campaign_id)ซึ่ง Google แนะนำให้ใช้แทนการประกอบชื่อเอง
ด่านตรวจการเปลี่ยนแปลงข้อมูลสามขั้นตอน
เพื่อความปลอดภัยในสภาพแวดล้อมใช้งานจริง การเปลี่ยนแปลงข้อมูลต้องผ่านด่านตรวจสามขั้นตอน:
ด่านที่ 1 — validate_only=True: API ตรวจโครงสร้างคำขอ ฟิลด์ที่จำเป็น และการอ้างอิงทรัพยากร โดยยังไม่สร้างออบเจ็กต์ ต้องทำขั้นตอนนี้ก่อนการเปลี่ยนแปลงข้อมูลทุกครั้ง
ด่านที่ 2 — สร้างในสถานะพัก: ตั้ง validate_only=False และสร้างออบเจ็กต์ด้วย status=PAUSED ตรวจสอบผลด้วยคำสั่งอ่านข้อมูลก่อนดำเนินการต่อ
ด่านที่ 3 — เปิดใช้งานจริง: เรียก API แยกต่างหากเพื่ออัปเดตเฉพาะฟิลด์ status เป็น ENABLED ขั้นตอนนี้ควรต้องได้รับอนุมัติอย่างชัดเจน และไม่ควรรวมไว้กับการสร้าง
# Gate 3: enable a previously created paused campaign
req = client.get_type('MutateCampaignsRequest')
req.customer_id = '1305475941'
req.validate_only = False
op = client.get_type('CampaignOperation')
op.update.resource_name = 'customers/1305475941/campaigns/22479990461'
op.update.status = client.enums.CampaignStatusEnum.ENABLED
op.update_mask.CopyFrom(field_mask_pb2.FieldMask(paths=['status']))
req.operations.append(op)
client.get_service('CampaignService').mutate_campaigns(request=req)
การอัปเดตงบประมาณ
req = client.get_type('MutateCampaignBudgetsRequest')
req.customer_id = '1305475941'
req.validate_only = True
op = client.get_type('CampaignBudgetOperation')
op.update.resource_name = 'customers/1305475941/campaignBudgets/123456789'
op.update.amount_micros = 1_000_000 # $1.00 per day
op.update_mask.CopyFrom(field_mask_pb2.FieldMask(paths=['amount_micros']))
req.operations.append(op)
client.get_service('CampaignBudgetService').mutate_campaign_budgets(request=req)
การอัปเดตราคาเสนอของกลุ่มโฆษณา
req = client.get_type('MutateAdGroupsRequest')
req.customer_id = '1305475941'
req.validate_only = True
op = client.get_type('AdGroupOperation')
op.update.resource_name = 'customers/1305475941/adGroups/165827073530'
op.update.cpc_bid_micros = 250_000 # $0.25
op.update_mask.CopyFrom(field_mask_pb2.FieldMask(paths=['cpc_bid_micros']))
req.operations.append(op)
client.get_service('AdGroupService').mutate_ad_groups(request=req)
การสร้างคีย์เวิร์ด
req = client.get_type('MutateAdGroupCriteriaRequest')
req.customer_id = '1305475941'
req.validate_only = True
op = client.get_type('AdGroupCriterionOperation')
op.create.ad_group = 'customers/1305475941/adGroups/165827073530'
op.create.status = client.enums.AdGroupCriterionStatusEnum.PAUSED
op.create.keyword.text = 'example keyword'
op.create.keyword.match_type = client.enums.KeywordMatchTypeEnum.EXACT
req.operations.append(op)
client.get_service('AdGroupCriterionService').mutate_ad_group_criteria(request=req)
การจัดการข้อผิดพลาด
from google.ads.googleads.errors import GoogleAdsException
try:
response = service.mutate_campaigns(request=req)
except GoogleAdsException as ex:
for error in ex.failure.errors:
print(f'{error.error_code}: {error.message}')
รหัสข้อผิดพลาดที่พบบ่อยและความหมาย:
| รหัสข้อผิดพลาด | สาเหตุ |
|---|---|
RESOURCE_NOT_FOUND | ทรัพยากรที่อ้างอิงไม่มีอยู่ ถูกลบ หรือชื่อทรัพยากรมีรูปแบบไม่ถูกต้อง |
DEVELOPER_TOKEN_NOT_APPROVED | ใช้โทเคน Test Access กับบัญชีใช้งานจริง (CLOUD_PROJECT_NOT_APPROVED_FOR_PRODUCTION หลังการยกเลิกในเดือนกันยายน 2026) |
REQUIRED | ขาดฟิลด์บังคับ (เช่น กลยุทธ์การเสนอราคาในการสร้างแคมเปญ) |
UNRECOGNIZED_FIELD | ฟิลด์จาก API เวอร์ชันอื่นหรือชื่อฟิลด์ไม่ถูกต้อง |
INVALID_ARGUMENT | ค่าฟิลด์ไม่ผ่านการตรวจสอบ (เช่น งบประมาณติดลบ) |
PERMISSION_DENIED | ผู้ใช้ OAuth ไม่มีสิทธิ์เข้าถึงบัญชีเป้าหมาย |
ระดับการเข้าถึง API
การเข้าถึง Google Ads API เป็นแบบลำดับชั้น ไม่ใช่แบบมีหรือไม่มี:
| ระดับ | การออกให้ | อ่าน (บัญชีใช้งานจริง) | เขียน (บัญชีใช้งานจริง) | เขียน (บัญชีทดสอบ) | ขีดจำกัดจำนวนการดำเนินการต่อวัน |
|---|---|---|---|---|---|
| Test Access | ทันที (จาก MCC API Center จนถึงเดือนกันยายน 2026 ปัจจุบันได้รับโดยอัตโนมัติเมื่อเปิดใช้ API ในโครงการ Cloud) | ❌ | ❌ | ✅ | 15,000 |
| Explorer Access (มีระบุไว้ ณ เดือนตุลาคม 2026) | ยื่นคำขอในหน้า Overview ของ Cloud Console | ✅ | ✅ (บางบริการมีข้อจำกัด) | ✅ | บัญชีใช้งานจริง 2,880 / บัญชีทดสอบ 15,000 |
| Basic Access | ยื่นคำขอและผ่านการตรวจสอบการปฏิบัติตามกฎระเบียบ | ✅ | ✅ | ✅ | 15,000 |
| Standard Access | ยื่นคำขอหลังได้รับ Basic Access + ตรวจสอบโดยเจ้าหน้าที่ | ✅ | ✅ | ✅ | ไม่จำกัด |
Test Access เพียงพอสำหรับการพัฒนากับบัญชีทดสอบ Google Ads ทั้งการยืนยันตัวตน การสืบค้นด้วย GAQL การทดสอบ validate_only และการอ่านและเขียนข้อมูลได้เต็มรูปแบบ การเปลี่ยนเป็น Basic Access ต้องผ่านการตรวจสอบการปฏิบัติตามกฎระเบียบ ไม่ได้ขึ้นอยู่กับยอดใช้จ่าย
Standard Access ยกเลิกขีดจำกัดจำนวนการดำเนินการต่อวัน (แต่ยังมีขีดจำกัดอัตราการเรียกใช้ของแต่ละฟีเจอร์) ต้องยื่นคำขอแยกต่างหากหลังได้รับ Basic Access แล้วเท่านั้น และผ่านการตรวจสอบโดยเจ้าหน้าที่ เอกสารระดับการเข้าถึงของ Google ไม่ได้ระบุเกณฑ์ยอดใช้จ่าย
บัญชีทดสอบ
บัญชีทดสอบคือบัญชี Google Ads ฟรีที่ไม่มีการเรียกเก็บเงินและไม่แสดงโฆษณา บัญชีทดสอบกับบัญชีใช้งานจริงไม่สามารถทำงานร่วมกันได้ จึงสร้างบัญชีทดสอบภายใต้ MCC ที่ใช้งานจริงไม่ได้ ให้ลงชื่อเข้าใช้ด้วยบัญชี Google ที่ไม่ได้เชื่อมโยงกับ MCC ที่ใช้งานจริง แล้วสร้างบัญชีผู้จัดการทดสอบแยกต่างหาก สร้างบัญชีลูกค้าทดสอบภายใต้บัญชีผู้จัดการนั้น และใช้บัญชีลูกค้าทดสอบหนึ่งบัญชีเป็น customer_id เป้าหมาย (โดยใช้บัญชีผู้จัดการทดสอบเป็น login_customer_id) ระหว่างการพัฒนาด้วย Test Access
validate_only ในแต่ละระดับการเข้าถึง
validate_only=True ใช้ได้ในทุกระดับการเข้าถึง แต่ Test Access ยังปฏิเสธคำขอเปลี่ยนแปลงข้อมูลแบบ validate_only ที่ส่งไปยังบัญชีใช้งานจริงด้วยข้อผิดพลาดด้านสิทธิ์การเข้าถึงเดียวกับคำขออื่น นี่ไม่ใช่ข้อจำกัดของ validate_only แต่เป็นการควบคุมการเข้าถึงเดียวกับที่ใช้กับการเขียนข้อมูลทั้งหมด ไม่ว่าค่า validate_only จะเป็นอย่างไร
การติดตามคอนเวอร์ชัน: การอ่านผ่าน API กับสถานะการทำงานจริง
ส่วนติดต่อผู้ใช้ของ Google Ads อาจแนะนำ “Set up conversion tracking” แม้จะมีการกระทำที่นับเป็นคอนเวอร์ชันและเปิดใช้งานอยู่แล้ว API ยืนยันได้ว่ามีการกระทำนั้นอยู่ (ประเภท WEBPAGE หมวดหมู่ PURCHASE สถานะ ENABLED และ include_in_conversions_metric: true) แต่ยืนยันได้เพียงว่าออบเจ็กต์มีอยู่ ไม่ได้ยืนยันว่าเว็บไซต์ส่งเหตุการณ์ AW-.../label ที่ตรงกัน โหลดแท็ก Google แล้ว หรือระบบได้รับสัญญาณคอนเวอร์ชันแล้ว
เมื่อตรวจสอบการติดตามคอนเวอร์ชัน ให้แยกการตรวจผ่าน API (ข้อมูลเมตาของการกระทำที่นับเป็นคอนเวอร์ชัน) ออกจากการตรวจในเบราว์เซอร์ (แท็บเครือข่าย การโหลดแท็ก และการส่งเหตุการณ์) API เป็นแหล่งข้อมูลหลักสำหรับการกำหนดค่า ส่วนเบราว์เซอร์เป็นแหล่งข้อมูลหลักสำหรับการทำงานจริง
รูปแบบการระบุที่มาของรายได้ฝั่ง backend ใช้กับกรณีนี้ได้ หากเหตุการณ์คอนเวอร์ชันฝั่งไคลเอนต์ไม่น่าเชื่อถือ ให้วางแผนอัปโหลดคอนเวอร์ชันจากฝั่งเซิร์ฟเวอร์หรือแบบออฟไลน์ผ่าน ConversionUploadService ของ Google Ads API เป็นทางสำรอง
การกำหนดเวอร์ชัน API
ไลบรารี google-ads สำหรับ Python มาพร้อม API หลายเวอร์ชัน ณ เดือนตุลาคม 2026 รุ่นล่าสุด (34.0.0) เพิ่ม v26 และนำ v22 กับเวอร์ชันก่อนหน้าออกจากไลบรารีแล้ว แต่ละเวอร์ชันจะเพิ่ม ประกาศเลิกใช้ หรือลบฟิลด์ GAQL และเมธอดของบริการ
กฎสำหรับการเลือกเวอร์ชัน:
- ระบุเวอร์ชันอย่างชัดเจนใน
load_from_storage(version='v22')ค่าเริ่มต้นอาจล้าสมัย - ตรวจสอบ บันทึกการออกรุ่น Google Ads API สำหรับการเลิกใช้งานฟิลด์ก่อนอัปเกรด
- เมธอด
search_streamมีให้ใช้งานในทุกเวอร์ชันปัจจุบัน และเป็นเส้นทางการอ่านที่แนะนำ - ต้องกำหนด
use_proto_plusอย่างชัดเจน (trueหรือfalse) โดยค่านี้เลือกอินเทอร์เฟซข้อความของ Python ไม่ใช่เวอร์ชัน API - รูปแบบออบเจ็กต์คำขอสำหรับการเปลี่ยนแปลงข้อมูล (
mutate_campaigns(request=req)) ใช้ส่งฟิลด์ระดับคำขอ เช่นvalidate_onlyตัวอย่างปัจจุบันของ Google ยังส่งcustomer_idและoperationsเป็นอาร์กิวเมนต์แบบระบุชื่อสำหรับการเปลี่ยนแปลงข้อมูลทั่วไป
ความปลอดภัยในเครื่อง
ไฟล์ข้อมูลรับรองทั้งหมดต้องอยู่นอกระบบควบคุมเวอร์ชัน:
~/.hermes/
google-ads.yaml # 0600 — dev token, OAuth client, refresh token
google_ads_token.json # 0600 — OAuth tokens, adwords scope
google_client_secret.json # 0600 — OAuth client ID + secret
เพิ่ม .gitignore ในรีโพซิทอรีที่ใช้ทำงาน:
google-ads.yaml
*_token*.json
*_secret*.json
บันทึกไฟล์เทมเพลตที่ใช้ค่าตัวแทนเข้าระบบควบคุมเวอร์ชันได้ เพื่อแสดงโครงสร้างที่ต้องใช้:
# google-ads.yaml.template — commit this, fill locally
developer_token: INSERT_DEV_TOKEN
client_id: INSERT_CLIENT_ID
client_secret: INSERT_CLIENT_SECRET
refresh_token: INSERT_REFRESH_TOKEN
login_customer_id: INSERT_MCC_ID
use_proto_plus: true
ฟิลด์ที่จำเป็นสำหรับการดำเนินการทั่วไป
| การดำเนินการ | ฟิลด์ที่จำเป็น |
|---|---|
| สร้างแคมเปญ (Search) | name, status, advertising_channel_type, campaign_budget, manual_cpc หรือกลยุทธ์การเสนอราคา, contains_eu_political_advertising |
| สร้างกลุ่มโฆษณา (Search) | name, status, type_, cpc_bid_micros, campaign |
| สร้างคีย์เวิร์ด | ad_group, status, keyword.text, keyword.match_type |
| อัปเดตสถานะแคมเปญ | resource_name, status, update_mask (พาธ: ['status']) |
| อัปเดตงบประมาณ | resource_name, amount_micros, update_mask (พาธ: ['amount_micros']) |
การขาดฟิลด์ที่จำเป็นจะส่งคืน REQUIRED พร้อมชื่อฟิลด์ การขาด update_mask ในการดำเนินการอัปเดตจะถูกปฏิเสธด้วย FieldMaskError.FIELD_MASK_MISSING
สคริปต์ทดสอบฉบับย่อ
สคริปต์ฉบับย่อที่อ่านประเภทองค์ประกอบทั้งหมดและทำการทดสอบการเขียนแบบ validate_only (รายการฟิลด์และตัวกรอง GAQL ถูกย่อด้วย ... และรหัสเป็นค่าตัวอย่าง จึงต้องเติมให้ครบก่อนรัน):
# google_ads_api_test.py — read all entities + validate_only write tests
import warnings
warnings.filterwarnings('ignore')
from google.ads.googleads.client import GoogleAdsClient
from google.ads.googleads.errors import GoogleAdsException
from google.protobuf import field_mask_pb2
CFG = '/path/to/google-ads.yaml'
CID = '1305475941'
c = GoogleAdsClient.load_from_storage(CFG, version='v22')
gs = c.get_service('GoogleAdsService')
def gaql(query, label):
print(f'\n=== {label} ===')
n = 0
for batch in gs.search_stream(customer_id=CID, query=query):
for row in batch.results:
n += 1
print(f'{n} rows')
# Read all entities
gaql("SELECT customer.id, customer.descriptive_name FROM customer WHERE customer.id = ...", "CUSTOMER")
gaql("SELECT campaign.id, campaign.name, campaign.status, ... FROM campaign", "CAMPAIGNS")
gaql("SELECT campaign_budget.id, campaign_budget.name, ... FROM campaign_budget", "BUDGETS")
gaql("SELECT ad_group.id, ad_group.name, ... FROM ad_group", "AD GROUPS")
gaql("SELECT ad_group_criterion.keyword.text, ... FROM keyword_view WHERE ...", "KEYWORDS")
gaql("SELECT ad_group_ad.ad.id, ... FROM ad_group_ad", "ADS")
gaql("SELECT conversion_action.id, ... FROM conversion_action", "CONVERSIONS")
# Write tests
def test_write(name, fn):
print(f'\n--- {name} ---')
try:
fn()
print('PASS')
except GoogleAdsException as e:
for err in e.failure.errors:
print(f'{err.error_code}: {err.message}')
def test_create_campaign():
req = c.get_type('MutateCampaignsRequest')
req.customer_id = CID
req.validate_only = True
op = c.get_type('CampaignOperation')
op.create.name = 'TEST_CAMPAIGN'
op.create.status = c.enums.CampaignStatusEnum.PAUSED
op.create.advertising_channel_type = c.enums.AdvertisingChannelTypeEnum.SEARCH
op.create.campaign_budget = f'customers/{CID}/campaignBudgets/123456789'
op.create.manual_cpc.enhanced_cpc_enabled = False
req.operations.append(op)
c.get_service('CampaignService').mutate_campaigns(request=req)
test_write('Create Campaign (validate_only)', test_create_campaign)
print('\nDone.')
เอกสารอ้างอิง
- เอกสาร Google Ads API
- ไลบรารี google-ads สำหรับ Python
- เอกสารอ้างอิง GAQL
- OAuth 2.0 สำหรับแอปเดสก์ท็อป
- สร้างผู้ช่วย AI เฉพาะโครงการผ่าน Telegram — ใช้รูปแบบ OAuth เดียวกันกับขอบเขตสิทธิ์ของ Google อีกประเภทหนึ่ง
- สถาปัตยกรรมอ้างอิงสำหรับชั้นปฏิบัติการ AI แบบเธรด — รูปแบบการดำเนินงานที่เชื่อมต่อกับการทำงานอัตโนมัติผ่าน API
- ดำเนินงานหลายสิบโครงการด้วยทีมขนาดเล็ก — เหตุผลที่การทำงานอัตโนมัติผ่าน API ใช้แทนการทำงานด้วยตนเองผ่านส่วนติดต่อผู้ใช้เมื่อขยายขนาดงาน