業務でGoogle Ads APIを使うことになったのだけど、クライアントライブラリが訳あって使えずRESTでAPIを叩く羽目ことになったのでメモ。
Google Ads API とは
Google広告のAPI。
クライアントライブラリが用意されており、実運用ではこちらの使用が強く推奨されている。
6言語に対応しておりRubyのライブラリもあったのだけど、自分が使用するRubyのバージョンが非対応だった。
これに合わせてRubyのバージョンアップをした方が良いか?とも考えたけど、毎年のRubyメジャーバージョンアップに合わせてAPIライブラリのサポート範囲もどんどん絞って(新しく)していくようで、ここでかなりの工数をかけてバージョンアップをしたところで鼬ごっこになることが予想できたため、泣く泣くRESTでAPIリクエストを一から書くことにした。
ちなみに、Google Ads API を使用する上で必須知識である
- Google広告自体の使い方やアカウントの構成
- OAuthによる認証方式
については以前記事にしたのでこちらも合わせてご覧ください。
Google Ads API を使いたい【基礎編】 - 箱のプログラミング日記。
【Google APIs】OAuth2.0を使って認証を通す - 箱のプログラミング日記。
やること
広告キャンペーンをAPI経由で作成する際にやることを例にとると、
- 作成したい広告キャンペーンのデータを作成
- APIクライアント情報を用意
- リクエストヘッダに上記項目を含めて送信
だいたいこんな感じになる。
クライアントライブラリを使えばこの辺のめんどくさい工程を簡単に実現させてくれるのだけど、今回は使えないので一個ずつ自分でやっていかなければならない。。
で、広告キャンペーンを例にとりたいところだけど、キャンペーンデータは複数の入れ子が発生しかなり複雑になってしまうので、以下の例では広告予算の作成に切り替えて話を進めていきます。
作成したい広告予算のデータを作成
こちらを参考に、デモの広告予算データをjsonファイルで作成しておきます。
$ cat create_budget.json { operations: [ { create: { name: "new budget 234", amount_micros: "60000000" } } ] }
APIクライアント情報を用意
APIクライアント情報に必要な項目は以下の3つ。
- OAuthアクセストークン
- MCC開発者トークン
- MCCログインID
OAuthアクセストークン
Google Ads APIは認証にOAuth2.0を使用しており、アクセストークンを取得するためには下記の手順を踏む必要がある。
- API Consoleでプロジェクトの作成
- 同意画面の作成
- OAuthクライアント情報作成
- ↑のクライアント情報を元にリフレッシュトークンを取得
- リフレッシュトークンを元にアクセストークンを取得
細かい部分は以前の記事に書いたので今回は割愛。
このあたりの構造、OAuthを初めて使う身としてはかなり難易度が高く理解できるまで時間をかけてしまったので、この辺に慣れていない人はまずGoogle API云々の前にOAuth2.0の基本を抑えることを強くお勧めします。
MCC開発者トークン
Google広告でAPIを使用するためには、Google広告アカウントを束ねるmanagerアカウント(MCC)が必要になる。
MCCを作成したら開発者トークンを発行する。詳しい手順は以下の記事がわかりやすいです。
Google Ads API のサンプルを動かすまで - Qiita
MCCログインID
ここでだいぶ詰まった。リファレンスに大々的に書いていないのでわかりづらいのだけど、MCCアカウントのログインIDが必要になります。
ログインIDは「123-456-7890」のような10桁の数値。こちらのハイフンを覗いて使用します。
リクエストヘッダに上記項目を含めて送信
では実際にこれまでに用意したものをヘッダに含めてcurlでリクエストを走らせてみます。
$ curl --request POST \ --header "Content-Type: application/json" \ --header "Authorization: Bearer アクセストークン" \ --header "developer-token: MCC開発者トークン" \ --header 'login-customer-id: MCCアカウントID' \ --data @create_budget.json https://googleads.googleapis.com/v6/customers/Google広告アカウントID/campaignBudgets:mutate
レスポンス
{ "results": [ { "resourceName": "customers/Google広告アカウントID/campaignBudgets/作成された広告予算ID" } ] }
エンドポイントは以下。
https://googleads.googleapis.com/v6/customers/Google広告アカウントID/campaignBudgets:mutate
v6
...APIのバージョンGoogle広告アカウントID
...Google広告管理画面のヘッダで参照できるアカウントIDcampaignBudgets
...作成したい対象のリソース名mutate
...データの作成や更新はmutateアクションを使用する
ここの「Google広告アカウントID」はMCCではなく個々の広告アカウントIDなので注意。
MCCのアカウントIDはリクエストヘッダにlogin-customer-id
として含める(鬼詰まりポイント)。
よく遭遇したエラー
リクエスト送信の検証でよく遭遇したエラーをいくつかまとめます。
トークン有効期限エラー
{ "error": { "code": 401, "message": "Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.", "status": "UNAUTHENTICATED" } }
アクセストークンの有効期限が切れているので再度取得が必要。
権限エラー(OAuth情報が誤っている)
{ "error": { "code": 403, "message": "The caller does not have permission", "status": "PERMISSION_DENIED", "details": [ { "@type": "type.googleapis.com/google.ads.googleads.v6.errors.GoogleAdsFailure", "errors": [ { "errorCode": { "authorizationError": "USER_PERMISSION_DENIED" }, "message": "User doesn't have permission to access customer. Note: If you're accessing a client customer, the manager's customer id must be set in the 'login-customer-id' header. See https://developers.google.com/google-ads/api/docs/concepts/call-structure#cid" } ] } ] } }
トークン自体は正しく、認証の通過はできるが権限がない場合。Google広告のアカウントと紐づくGoogleアカウントで取得したアクセストークンではない場合に発生する。
アクセストークン(orリフレッシュトークン)を取得するアカウントが間違っていないか・Google広告に紐づいているアカウントと同意画面で「許可」したアカウントが一致しているかを確認する必要がある。
もしくは、「If you're accessing a client customer, the manager's customer id must be set in the 'login-customer-id' header.」とあるように、MCCアカウントIDはリクエストヘッダに含めエンドポイントにはMCC管理下のGoogle広告IDを設定する必要があるため、ここが逆になっていないかどうか確認する。
空のオブジェクトが返ってくる
[]
こちらはmutate(データの作成・更新)ではなくserch(データの取得)で発生した現象。認証も通過し、エンドポイントも合っているのに情報が見つからない場合。
自分の場合はリクエストヘッダにMCCアカウントIDを含めていなかったため実際は存在するはずのデータが取得できず空のオブジェクトが返ってくるみたいでした。
参考
Mutate | Google Ads API | Google Developers
真・Google Ads API 徹底入門 その3 Mutate 編 - Feedforce Developer Blog
↑こちらの記事以外にもシリーズ全般お世話になりました。
resource_name
についての説明やmutate
とserch
の違いなどがわかりやすく纏まっていました。