tva
← コラム

Google Ads API:設定・認証・読み取りと書き込み操作

Google Adsをプログラムから利用するための設定手順を、アーキテクチャから最初のAPI呼び出しまで解説します。MCCの設定、OAuth 2.0、デベロッパートークンのアクセスレベル、Pythonのgoogle-adsライブラリ、GAQLによる読み取りクエリ、validate_onlyを使った書き込み方法を扱います。

更新(2026年10月):Googleは2026年9月9日にデベロッパートークンを廃止しました。APIのアクセスレベルは現在、Google Cloudプロジェクトごとに割り当てられ、Cloud ConsoleのGoogle Ads APIの概要ページで管理します。developer-tokenヘッダーは任意となり、指定しても無視されます。APIセンターでは登録やアクセス権の変更を扱わなくなりました。Googleによると、既存のコードは引き続き動作します。以下のデベロッパートークンとAPIセンターの手順は、2026年6月の公開時点の設定を説明したものです。現在の設定方法は、続編の2026年のGoogle Ads APIアクセス:Cloudプロジェクトがデベロッパートークンに代わるで解説しています。

アーキテクチャ

API呼び出しを動作させるには、三つの独立したエンティティが必要です。

エンティティ目的例
マネージャーアカウント(MCC)デベロッパートークンを発行するlogin_customer_id
Google Cloudプロジェクト認証用のOAuth 2.0クライアントクライアントID + シークレット
Google AdsアカウントすべてのAPI操作の対象customer_id

これらは同一のアカウントではありません。MCCは対象アカウントを所有していなくてもデベロッパートークンを保有でき、マネージャーとしてリンクされていれば十分です。Google Cloudプロジェクトは、MCCとは別のGoogle IDで管理しても構いません。対象アカウントは、キャンペーンがある広告主アカウントです。

この分離が重要なのは、デベロッパートークンが発行されるAPIセンターを、マネージャーアカウント内でしか利用できないためです。単独のGoogle Adsアカウントは、管理者ユーザーがいてもAPIセンターにアクセスできません。

API呼び出しのヘッダーは、これら三つの識別情報とOAuthのBearerトークンを組み合わせます。

developer-token: <MCC APIセンターから取得>
login-customer-id: <MCC の数値 ID、ダッシュなし>
customer-id: <対象アカウントの数値 ID>
Authorization: Bearer <OAuth 2.0 アクセストークン>

前提条件

  • セットアップが完了したGoogle Adsマネージャーアカウント
  • 対象の広告アカウントがマネージャーアカウントにリンクされ、リンクが承認されていること
  • Google Ads APIが有効化されたGoogle Cloudプロジェクト
  • Python 3.9以上とgoogle-adsライブラリ(pip install google-ads)
  • 一度だけ実行するOAuth同意フロー用のブラウザー

ステップ1:マネージャーアカウントとデベロッパートークン

APIセンターは、マネージャーアカウント内のツールと設定 → 設定 → APIセンターにあります。APIセンターが表示されない場合、そのアカウントはマネージャーアカウントでないか、セットアップが不完全です。

APIセンターからデベロッパートークンをリクエストします。自身のアカウント用のトークンである場合は、アカウントタイプをAdvertiser(代理店やサードパーティではありません)に設定してください。トークンはすぐにテストアクセスレベルで発行されます。

テストアクセスで許可される操作:

  • テストアカウントのみに対する読み取り操作
  • テストアカウントのみに対する書き込み操作
  • 本番アカウントに対する読み取り・書き込み操作は不可

テストアクセスで本番アカウントにリクエストを送ると、DEVELOPER_TOKEN_NOT_APPROVED(“The developer token is only approved for use with test accounts”)で失敗します。2026年9月の廃止以降、現在のAPIバージョンでは代わりにCLOUD_PROJECT_NOT_APPROVED_FOR_PRODUCTIONが返されます(v24以前ではACTION_NOT_PERMITTED)。

ベーシックアクセスの申請

本番アカウントにアクセスするには、同じAPIセンターのページからベーシックアクセスを申請します。申請フォームには12の質問があります。自社アカウントでの社内利用の場合、関連する回答は次のとおりです。

質問回答
Q4:Google担当者との関係なし(No)
Q6:ビジネスモデル自社のユースケースを説明(EC、リード獲得、内部レポートなど)
Q8:アクセス権限を持つユーザー社内ユーザー — 従業員のみ
Q9:サードパーティ開発ツールいいえ(自社スクリプト/エージェント)
Q10:コンバージョントラッキングとリマーケティングAPIいいえ(実際に使用する場合を除く)
Q11:キャンペーンタイプ検索、Performance Max、ショッピング(該当するもの)
Q12:機能キャンペーン作成、キャンペーン管理、レポート

Q7では設計文書(PDF)が必要です。APIのアーキテクチャ、認証フロー、レート制限の方針、エラー処理、社内利用に限った用途を記載します。事実に基づいて記述してください。コンプライアンスチームが申告した用途との整合性を審査します。

2026年6月時点の処理期間:約3営業日。ただし申請量が通常より多いとの注記があります。

ステップ2:OAuth 2.0

Google Cloudプロジェクトのセットアップ

該当プロジェクトのGoogle Cloudコンソールで以下を実施します。

  1. Google Ads APIを有効化(APIとサービス → ライブラリ)
  2. OAuth同意画面を設定:
  • ユーザータイプ:Internal(Google Workspace内のユーザーのみが認証可能 — 外部アプリ検証をスキップできます)
  • アプリ名、サポートメール、デベロッパー連絡先メール
  1. データアクセスでスコープを追加:https://www.googleapis.com/auth/adwords
  2. OAuthクライアントIDを作成:
  • アプリケーションタイプ:Desktop app
  • クライアントシークレットJSONをダウンロード

Desktop appタイプは、リダイレクトURIとしてhttp://localhostを使います。これは正しい設定です。OAuthフローでブラウザーが開き、Googleが認証コードを付けてlocalhostへリダイレクトし、ローカルHTTPサーバーが受け取ります。

リフレッシュトークンの生成

次の最小限のPythonスクリプトは、127.0.0.1:0(ランダムなポート)でローカルHTTPサーバーを起動し、認証URLを表示します。リクエストを1件待ち、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())

2つのパラメーターが重要です。

  • access_type='offline'— アクセストークンだけでなくリフレッシュトークンも返します
  • prompt='consent'— 以前に認証済みでも新しい同意画面を強制します。スコープが変更された場合に新しいリフレッシュトークンを取得するために必要です

リフレッシュトークンに固定の有効期間はありません。ただし、ユーザーがアクセス権を取り消した場合、6か月間使われなかった場合、ユーザーがパスワードを変更した場合(Gmailスコープを含むトークン)、アカウントがGoogleの有効なリフレッシュトークン数の上限を超えた場合、Workspace管理者がスコープを制限するかセッションの有効期間を設定した場合は使えなくなります。再認可が必要になることを想定してください。

既存クライアントでのスコープの落とし穴

認可URLにinclude_granted_scopes=trueが設定され、ユーザーが以前にこのOAuthクライアントに別のスコープ(Gmail、Drive、Calendar)を許可していた場合、Googleは新旧のスコープの和集合を返します。google-auth-oauthlibは、このスコープの不一致を初期設定では拒否します。フローを読み込む前に環境変数を設定してください。

import os
os.environ['OAUTHLIB_RELAX_TOKEN_SCOPE'] = '1'

または、認可URLにinclude_granted_scopes=trueを含めないことで(上のスクリプトでも設定していません)、トークンの対象を明示的にリクエストしたスコープのみにします。

ステップ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の数値IDです。認証済みユーザーがどのマネージャーアカウントを経由して対象アカウントにアクセスするかをAPIに示し、マネージャーアカウント経由のアクセスでは必須です。対象のcustomer_idは設定ファイルではなく、呼び出し時に渡します。

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年10月時点のライブラリには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]
# 出力例: ['1305475941', '3977581086', '1911599764']

ステップ5:読み取り操作(GAQL)

Google Adsは、SQLに似た構文のGAQL(Google Ads Query Language)を使います。すべての読み取り操作には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() を使用。.add() ではない
client.get_service('CampaignService').mutate_campaigns(request=req)

このパターンの要点(use_proto_plus: trueの場合):

  • validate_onlyは変更操作メソッドのキーワード引数ではなく、リクエストオブジェクトのフィールドです
  • 操作は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へ更新します。この操作には明示的な承認を求め、作成とまとめて実行するべきではありません。

# ゲート 3: 作成済みの一時停止キャンペーンを有効化
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 / 日
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本番アカウントに対するテストアクセストークン(2026年9月の廃止以降はCLOUD_PROJECT_NOT_APPROVED_FOR_PRODUCTION)
REQUIRED必須フィールドの欠落(例:キャンペーン作成時の入札戦略)
UNRECOGNIZED_FIELD異なるAPIバージョンのフィールドまたは誤ったフィールド名
INVALID_ARGUMENTフィールド値の検証に失敗(例:負の予算)
PERMISSION_DENIEDOAuthユーザーが対象アカウントへのアクセス権を持っていない

APIアクセスレベル

Google Ads APIのアクセス権は、許可か拒否かの二択ではなく、段階別に設定されています。

レベル発行・付与の条件読み取り(本番)書き込み(本番)書き込み(テストアカウント)1日あたりの操作上限
テストアクセス即時(2026年9月まではMCC APIセンターから発行。現在はCloudプロジェクトでAPIを有効にすると自動付与)❌❌✅15,000
エクスプローラーアクセス(2026年10月時点で掲載)Cloud Consoleの概要ページから申請✅✅(一部のサービスに制限あり)✅本番2,880/テスト15,000
ベーシックアクセス申請 + コンプライアンス審査✅✅✅15,000
スタンダードアクセスベーシックアクセス取得後の申請と手動監査✅✅✅無制限

テストアクセスは、Google Adsテストアカウントを対象とする開発に十分です。認証、GAQLクエリ、validate_onlyテスト、完全な読み取り・書き込みが可能です。ベーシックアクセスへの移行は、支出額ではなくコンプライアンス審査によって制限されます。

スタンダードアクセスでは1日の操作上限が撤廃されます(機能ごとのレート制限は引き続き適用されます)。ベーシックアクセスの取得後にのみ可能な別途の申請と、手動監査が必要です。Googleのアクセスレベルのドキュメントには支出の基準額は記載されていません。

テストアカウント

テストアカウントは、請求が発生せず、広告を配信しない無料のGoogle Adsアカウントです。テストアカウントと本番アカウントは相互に操作できないため、本番用MCCの配下には置けません。本番用MCCにリンクされていないGoogleアカウントでログインして、別のテスト用マネージャーアカウントを作成し、その配下にテスト用クライアントアカウントを作成します。テストアクセスでの開発では、その1つを対象のcustomer_idとし、テスト用マネージャーをlogin_customer_idに指定します。

アクセスレベルごとのvalidate_only

validate_only=Trueはすべてのアクセスレベルで使えますが、テストアクセスでは、本番アカウントに対するvalidate_onlyの変更操作も、他のリクエストと同じ認可エラーで拒否されます。これはvalidate_only自体の制限ではありません。フラグの有無にかかわらず、すべての書き込み操作に適用されるアクセス制御です。

コンバージョントラッキング:APIでの読み取りと実際の動作

Google AdsのUIでは、コンバージョンアクションが存在して有効であっても、「コンバージョントラッキングを設定してください」という推奨が表示される場合があります。APIはコンバージョンアクションの存在を確認できますが(タイプWEBPAGE、カテゴリPURCHASE、ステータスENABLED、include_in_conversions_metric: true)、これはアクションオブジェクトが存在することを証明するに過ぎません。ウェブサイトが対応するAW-.../labelイベントを発行していること、Googleタグが読み込まれていること、コンバージョンシグナルが受信されていることは証明されません。

コンバージョントラッキングを監査する際は、APIでの確認(コンバージョンアクションのメタデータ)と、ブラウザーでの確認(ネットワークタブ、タグの読み込み、イベントの発火)を分けてください。設定についてはAPIが、実行についてはブラウザーが、事実を確認する基準になります。

バックエンドでの収益のアトリビューションの手法が、ここでも当てはまります。クライアント側のコンバージョンイベントが不安定な場合は、代替手段としてGoogle Ads APIのConversionUploadServiceを使い、サーバー側またはオフラインでのコンバージョンアップロードを計画してください。

APIバージョニング

Pythonのgoogle-adsライブラリには、複数のAPIバージョンが同梱されています。2026年10月時点の最新リリース(34.0.0)ではv26が追加され、v22以前はライブラリから削除されています。各バージョンで、GAQLフィールドやサービスメソッドが追加、非推奨化、削除されます。

バージョン選択のルール:

  • load_from_storage(version='v22')でバージョンを明示的に指定してください。デフォルトは古い可能性があります。
  • アップグレード前にGoogle Ads APIリリースノートでフィールドの非推奨化を確認してください。
  • search_streamメソッドは現在のすべてのバージョンで利用可能で、推奨される読み取りパスです。
  • use_proto_plusは明示的に設定する必要があります(trueまたはfalse)。APIバージョンではなく、Pythonのメッセージインターフェースを選択します。
  • 変更操作のリクエストオブジェクトを使うパターン(mutate_campaigns(request=req))では、validate_onlyなどのリクエスト単位のフィールドを設定できます。Googleの現在の例でも、通常の変更操作にはcustomer_idとoperationsをキーワード引数で渡しています。

ローカルセキュリティ

すべての認証情報ファイルはバージョン管理の対象外にする必要があります。

~/.hermes/
  google-ads.yaml          # 0600 — 開発トークン、OAuth クライアント、リフレッシュトークン
  google_ads_token.json    # 0600 — OAuth トークン、adwords スコープ
  google_client_secret.json # 0600 — OAuth クライアント ID + シークレット

作業リポジトリには.gitignoreを追加してください。

google-ads.yaml
*_token*.json
*_secret*.json

期待される構造を文書化するために、プレースホルダー値を持つテンプレートファイルはコミットできます。

# google-ads.yaml.template — これをコミットし、ローカルで値を入力
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

一般的な操作の必須フィールド

操作必須フィールド
キャンペーン作成(検索)name、status、advertising_channel_type、campaign_budget、manual_cpcまたは入札戦略、contains_eu_political_advertising
広告グループ作成(検索)name、status、type_、cpc_bid_micros、campaign
キーワード作成ad_group、status、keyword.text、keyword.match_type
キャンペーンステータス更新resource_name、status、update_mask(paths:['status'])
予算更新resource_name、amount_micros、update_mask(paths:['amount_micros'])

必須フィールドが欠けると、フィールド名とともにREQUIREDが返されます。更新操作でupdate_maskが欠けている場合は、FieldMaskError.FIELD_MASK_MISSINGで拒否されます。

簡略版テストスクリプト

すべてのエンティティタイプを読み取り、validate_only書き込みテストを実行する簡略版スクリプトです。GAQLのフィールド一覧とフィルターは...で省略され、IDは仮の値なので、実行前に補ってください。

# google_ads_api_test.py — 全エンティティ読み取り + validate_only 書き込みテスト
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.')

参考資料

関連記事