tva
← บทความเชิงลึก

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 Tokenlogin_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 ภายใต้โครงการที่เกี่ยวข้อง:

  1. เปิดใช้งาน Google Ads API (APIs & Services → Library)
  2. กำหนดค่า OAuth consent screen:
  • User Type: Internal (เฉพาะผู้ใช้ใน Google Workspace ของคุณเท่านั้นที่ให้สิทธิ์ได้ โดยไม่ต้องผ่านการตรวจสอบแอปสำหรับผู้ใช้ภายนอก)
  • ชื่อแอป อีเมลฝ่ายช่วยเหลือ และอีเมลติดต่อนักพัฒนา
  1. เพิ่มขอบเขตสิทธิ์ใน Data Access: https://www.googleapis.com/auth/adwords
  2. สร้าง 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.')

เอกสารอ้างอิง

บทความที่เกี่ยวข้อง