Google Ads API のサンプルを動かすまで

## 概要

Google Ads APIのサンプルコードを動かすまで。
このAPIは、Google広告(Google AdWords)のアカウントや広告を管理するために利用するものです。
以前から提供されていたAdWords APIの次世代版として、2018年に発表されました。

[QuickStart](https://developers.google.com/google-ads/api/docs/first-call/overview)ガイドはありますが、 ライブラリのインストールに手間取ったり、いろんなページを行ったり来たり、迷子になったのでメモ。

## 環境

- Google Ads API Beta v0.6.0
- gRPC 1.17.0
- MacOS Mojave 10.14.2
- PHP 7.1.25
- PEAR 1.10.5

## 手順

[QuickStart](https://developers.google.com/google-ads/api/docs/first-call/overview) に沿って進めていきます。

1. [開発者トークンを取得](https://qiita.com/akaaariiiiin/items/7db3d40ca5b92610d448#1-%E9%96%8B%E7%99%BA%E8%80%85%E3%83%88%E3%83%BC%E3%82%AF%E3%83%B3%E3%82%92%E5%8F%96%E5%BE%97)
2. [クライアントライブラリを取得](https://qiita.com/akaaariiiiin/items/7db3d40ca5b92610d448#2-%E3%82%AF%E3%83%A9%E3%82%A4%E3%82%A2%E3%83%B3%E3%83%88%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AA%E3%82%92%E5%8F%96%E5%BE%97)
3. [OAuth2 クライアントIDとクライアントシークレットを取得](https://qiita.com/akaaariiiiin/items/7db3d40ca5b92610d448#3-oauth2-%E3%82%AF%E3%83%A9%E3%82%A4%E3%82%A2%E3%83%B3%E3%83%88id%E3%81%A8%E3%82%AF%E3%83%A9%E3%82%A4%E3%82%A2%E3%83%B3%E3%83%88%E3%82%B7%E3%83%BC%E3%82%AF%E3%83%AC%E3%83%83%E3%83%88%E3%82%92%E5%8F%96%E5%BE%97)
4. [リフレッシュトークンを取得](https://qiita.com/akaaariiiiin/items/7db3d40ca5b92610d448#4-%E3%83%AA%E3%83%95%E3%83%AC%E3%83%83%E3%82%B7%E3%83%A5%E3%83%88%E3%83%BC%E3%82%AF%E3%83%B3%E3%82%92%E5%8F%96%E5%BE%97)
5. [キャンペーンを取得する](https://qiita.com/akaaariiiiin/items/7db3d40ca5b92610d448#5-%E3%82%AD%E3%83%A3%E3%83%B3%E3%83%9A%E3%83%BC%E3%83%B3%E3%82%92%E5%8F%96%E5%BE%97%E3%81%99%E3%82%8B)

## 1. 開発者トークンを取得

1. [ここ](https://ads.google.com/home/tools/manager-accounts/)からMCCアカウントを作成する
  * Developer tokenを取得するにはMCCアカウントが必要です。
2. MCCアカウントにログインする
3. `ツール` > `設定` > `APIセンター`から必要事項を記入して申し込む
  * サンプルを動かすだけならアクセス権は`テストアカウント`で大丈夫です。
4. 登録できたら以下のように開発者トークンを取得できる
<img width="1276" alt="開発者トークン_s.png" src="https://qiita-image-store.s3.amazonaws.com/0/73589/4dbc138e-81a7-0899-2568-2a1ef7251891.png">

参考

- [MCCアカウントと開発者トークンの取得](https://developers.google.com/adwords/api/docs/guides/signup)
- [テストアカウント](https://developers.google.com/adwords/api/docs/guides/accounts-overview#test_accounts)

## 2. クライアントライブラリを取得

2018-12-17現在、クライアントライブラリは5言語で用意されていますが、今回はPHPを使います。

1. gRPC PHP extensionをインストールする

    ```sh
$ sudo pecl install grpc
    ```
  - 以下のようなログが出たら成功です。

    ```sh
    Build process completed successfully
    Installing '/usr/local/Cellar/php@7.1/7.1.25/pecl/20160303/grpc.so'
    install ok: channel://pecl.php.net/grpc-1.17.0
    Extension grpc enabled in php.ini
    ```
  - 以下のようなエラーが出る場合は失敗です。ここで失敗していると、3.でエラーが発生します。(PHP 7.3ではうまくいかなかったので、PHP 7.1でやり直しました。。)

    ```sh
    Build process completed successfully
    Installing '/usr/local/Cellar/php/7.3.0/pecl/20180731/grpc.so'

    Warning: mkdir(): File exists in System.php on line 294

    Warning: mkdir(): File exists in /usr/local/Cellar/php/7.3.0/share/php/pear/System.php on line 294
    ERROR: failed to mkdir /usr/local/Cellar/php/7.3.0/pecl/20180731
    ```

2. GithubからGoogle　Ads APIのクライアントライブラリをダウンロードする

    ```sh
$ git clone https://github.com/googleads/google-ads-php.git
    ```

3. `composer install` する

    ```sh
$ cd google-ads-php
$ composer install
    ```
  - 以下のようなログが出たら成功です。

    ```sh
    $ composer install
    Loading composer repositories with package information
    Updating dependencies (including require-dev)
    Package operations: 52 installs, 0 updates, 0 removals
      - Installing ralouphie/getallheaders (2.0.5): Downloading (100%)
    (省略)
      - Installing squizlabs/php_codesniffer (3.3.2): Downloading (100%)
    grpc/grpc suggests installing ext-protobuf (For better performance, install the protobuf C extension.)
    react/event-loop suggests installing ext-event (~1.0 for ExtEventLoop)
    monolog/monolog suggests installing aws/aws-sdk-php (Allow sending log messages to AWS services like DynamoDB)
    (省略)
    monolog/monolog suggests installing sentry/sentry (Allow sending log messages to a Sentry server)
    symfony/yaml suggests installing symfony/console (For validating YAML files using the lint command)
    sebastian/global-state suggests installing ext-uopz (*)
    phpunit/php-code-coverage suggests installing ext-xdebug (^2.5.1)
    phpunit/phpunit suggests installing phpunit/php-invoker (~1.1)
    phpunit/phpunit suggests installing ext-xdebug (*)
    Writing lock file
    Generating autoload files
    ```
  - 以下のようなエラーが出る場合は失敗です。1.でgRPC PHP extensionのインストールが成功しているか確認してみてください。

    ```sh
    $ composer install
    Loading composer repositories with package information
    Updating dependencies (including require-dev)
    Your requirements could not be resolved to an installable set of packages.
    
      Problem 1
        - The requested PHP extension ext-grpc * is missing from your system. Install or enable PHP's grpc extension.
    ```

参考

- [google-ads-phpのGithub README](https://github.com/googleads/google-ads-php/blob/master/README.md#getting-started)
- [gRPC PHP extensionのインストール](https://grpc.io/docs/quickstart/php.html#using-pecl)

## 3. OAuth2 クライアントIDとクライアントシークレットを取得

1. [Google API Console](https://console.developers.google.com/apis/credentials)にログインする

2. プロジェクトを作成する
  1. `作成`ボタンを押す
<img width="916" alt="google_api_console_login_s.png" src="https://qiita-image-store.s3.amazonaws.com/0/73589/17e53da0-7f03-550a-ff48-a67c9231b2c6.png">
  2. プロジェクト名を入力する
  3. 下部の`作成`ボタンを押す
<img width="915" alt="create_project_s.png" src="https://qiita-image-store.s3.amazonaws.com/0/73589/adcfe172-babb-9231-56bc-ab26958da59f.png">

3. `OAuth 同意画面`を作成する
  1. `OAuth 同意画面`タブを開く
  2. アプリケーション名を入力する
<img width="1280" alt="同意画面作成1_s.png" src="https://qiita-image-store.s3.amazonaws.com/0/73589/a3df4162-573b-7c4e-4a2a-9052407e46bb.png">

  3. `保存`ボタンを押す
<img width="1280" alt="同意画面作成2_s.png" src="https://qiita-image-store.s3.amazonaws.com/0/73589/5188a6fc-0bd8-b363-558f-7b9ed7dd33ef.png">

4. OAuth2 クライアントIDとクライアントシークレットを取得する
  1. `認証情報を作成` > `OAuth クライアント　ID`を選択する
<img width="907" alt="create_client_id_s.png" src="https://qiita-image-store.s3.amazonaws.com/0/73589/9de9cc9f-fab9-8b1e-aaa8-2fa8e9f511e6.png">

  2. アプリケーションの種類は`その他`を選択する[^1]
  3. `作成`ボタンを押すとクライアントIDとクライアントシークレットが表示される
<img width="774" alt="アプリケーションの種類_s.png" src="https://qiita-image-store.s3.amazonaws.com/0/73589/a7b57e05-9f40-bc29-4de4-c18b942c76e6.png">

[^1]: 他のアプリケーションを選ぶと、WEBサイトのURLやアプリのIDの入力が必要です。それらは自分のPCで検証する際には不要のため、今回は一番簡単な`その他`を利用します。

## 4. リフレッシュトークンを取得

1. JSONをダウンロードする
<img width="1022" alt="jsonダウンロード_s.png" src="https://qiita-image-store.s3.amazonaws.com/0/73589/9e56b192-16cb-9b4b-3850-f1319a659605.png">

    ```json
    {
      "installed": {
        "client_id": "hoge.apps.googleusercontent.com",
        "project_id": "precise-rite-999999",
        "auth_uri": "https://accounts.google.com/o/oauth2/auth",
        "token_uri": "https://www.googleapis.com/oauth2/v3/token",
        "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
        "client_secret": "fuga",
        "redirect_uris": [
          "urn:ietf:wg:oauth:2.0:oob",
          "http://localhost"
        ]
      }
    }
    ```

2. 以下のフォーマットに1.で取得したJSONの内容を当てはめ、改行を削除してブラウザからアクセスする

    ```
    # フォーマット
    {auth_uri}
    ?client_id={client_id}
    &redirect_uri={redirect_uris(httpの方)}
    &scope=https://www.googleapis.com/auth/adwords
    &access_type=offline
    &response_type=code

    # URL
    https://accounts.google.com/o/oauth2/auth?client_id=hoge.apps.googleusercontent.com&redirect_uri=http://localhost&scope=https://www.googleapis.com/auth/adwords&access_type=offline&response_type=code
    ```

3. 以下のような画面が表示されるので許可する
<img width="543" alt="アクセス許可_s.png" src="https://qiita-image-store.s3.amazonaws.com/0/73589/0b6c1458-01a6-009a-cdda-29088f7c579a.png">

4. リダイレクトされるので、リダイレクト先のURLを取得する
  - URLの取得が目的なので、リダイレクト先のページがエラーになっていてもOKです。
<img width="888" alt="URL取得_s.png" src="https://qiita-image-store.s3.amazonaws.com/0/73589/58c0f4c6-dd84-d792-b74e-3ce0ddd68436.png">

    ```
    http://localhost/?code=4/poyo&scope=https://www.googleapis.com/auth/adwords
    ```

5. 以下のコマンドでリフレッシュトークンを取得する

    ```sh
    # フォーマット
    # curl -d client_id={client_id} -d client_secret={client_secret} -d redirect_uri={redirect_uris(httpの方)} -d grant_type=authorization_code -d code={認証コード(4.で取得したURLのcodeパラメータ)} https://accounts.google.com/o/oauth2/token

    $ curl -d client_id=hoge.apps.googleusercontent.com -d client_secret=fuga -d redirect_uri=http://localhost -d grant_type=authorization_code -d code=4/poyo https://accounts.google.com/o/oauth2/token
    {
      "access_token": "nyaaa",
      "expires_in": 3600,
      "refresh_token": "1/piyo",
      "scope": "https://www.googleapis.com/auth/adwords",
      "token_type": "Bearer"
    }
    ```

参考

- [リフレッシュトークンの取得方法](https://qiita.com/iwaseasahi/items/2363dc1d246bc06baeae)

## 5. キャンペーンを取得する

やっとサンプルを動かします、、！

1. `google_ads_php.ini`に今まで取得した値を入れる

    ```sh
    $ cd google-ads-php  # ここにいる場合は不要
    $ cp examples/Authentication/google_ads_php.ini ./
    $ vim google_ads_php.ini

    # 4箇所を実際の値に変更する
    [GOOGLE_ADS]
    developerToken = "INSERT_DEVELOPER_TOKEN_HERE"     # 1-4.で取得した開発者トークン

    [OAUTH2]
    clientId = "INSERT_OAUTH2_CLIENT_ID_HERE"          # 4ｰ1.で取得したclient_id
    clientSecret = "INSERT_OAUTH2_CLIENT_SECRET_HERE"  # 4ｰ1.で取得したclient_secret
    refreshToken = "INSERT_OAUTH2_REFRESH_TOKEN_HERE"  # 4ｰ5.で取得したrefresh_token
    ```

2. `GetCampaigns.php`36行目あたりの`CUSTOMER_ID`に実際の値に変更する

    ```sh
    $ vim examples/BasicOperations/GetCampaigns.php
    ```
    ```php
    class GetCampaigns
    {
        //const CUSTOMER_ID = 'INSERT_CUSTOMER_ID_HERE';
        const CUSTOMER_ID = '9999999999';  //　ここ
        const PAGE_SIZE = 1000;
    ```

3. キャンペーンを取得できました！

    ```sh
    $ php examples/BasicOperations/GetCampaigns.php
    [2018-12-17 14:00:17] google-ads.INFO: Request made: Host: "googleads.googleapis.com", Method: "/google.ads.googleads.v0.services.GoogleAdsService/Search", ClientCustomerId: 9999999999, RequestId: "stuH5sXJeVEsb-dCAQj2Iw", IsFault: 0, FaultMessage: "None"
    [2018-12-17 14:00:17] google-ads.DEBUG: Request
    -------
    Method Name: /google.ads.googleads.v0.services.GoogleAdsService/Search
    Host: googleads.googleapis.com
    Headers: {
        "developer-token": "REDACTED",
        "x-goog-api-client": "gl-php\/7.1.25 gapic\/ gax\/0.35.0 grpc\/1.17.0"
    }
    Request: {"customerId":"9999999999","query":"SELECT campaign.id, campaign.name FROM campaign ORDER BY campaign.id","pageSize":1000}

    Response
    -------
    Headers: {
        "content-disposition": "attachment",
        "request-id": "stuH5sXJeVEsb-dCAQj2Iw",
        "date": "Mon, 17 Dec 2018 14:00:17 GMT",
        "alt-svc": "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
    }
    Response: {"results":[{"campaign":{"resourceName":"customers\/9999999999\/campaigns\/1381374713","id":"1381374713","name":"test #1"}}],"totalResultsCount":"1","fieldMask":"campaign.id,campaign.name"}
    Campaign with ID 1381374713 and name 'test #1' was found.
    ```

参考

- [google-ads-phpのGithub README](https://github.com/googleads/google-ads-php/blob/master/README.md#getting-started)