AdWords APIでキーワードプランナーの検索ボリューム・CPC・競合性を取得する

※ 2020/08/03 Google Ads API版の記事を公開しましたので、よろしければどうぞ。
[Google Ads APIでキーワードプランナーの検索ボリューム・CPC・競合性を取得する](https://qiita.com/zak_y/items/7468a3df8d221f1b725b)

# はじめに
広告出稿の参考とするために、ターゲットキーワードとその関連キーワードの検索ボリューム・CPC・競合性を必要とする要件があり、GoogleキーワードプランナーのデータをAdwords APIを使って取得してみました。

AdWords APIの公式サイトはこちら
[Google AdWords API](https://developers.google.com/adwords/api/docs/guides/start?hl=ja)

# キーワードプランナーのデータを取得するまで
以下の流れで説明します。

1. AdWords APIを利用するための準備
2. Google Ads Client Libraries（Python）のインストール
3. OAuth2 認証の設定
4. APIで検索ボリューム・CPC・競合性の取得

## 1. AdWords APIを利用するための準備
AdWords APIは無料で利用できますが、利用にあたってはMCCアカウントと開発者トークンの申請/承認手続きが必要です。
公式サイトはこちら
[最初のAPI呼び出しを実行する | AdWords API](https://developers.google.com/adwords/api/docs/guides/first-api-call?hl=ja)

具体的な申請方法などはこちらのサイトが参考になりました。
[キーワードプランナーもログインせずに自由自在！ AdWords API の申請と使い方](https://pct.unifas.net/programming/php/2874/)

※開発者トークンの承認に1週間程度かかるので、そのまま待ちます。

## 2. Google Ads Client Libraries（Python）のインストール
※既にインストール済みであればこの項は不要です。

今回はGoogleが提供しているAPIクライアントライブラリ（Python）を使って取得してみます。
こちらを参考にインストールしておきます。
[Google API Client Libraries > Python](https://developers.google.com/api-client-library/python/start/get_started)
具体的には下記コマンドで入ります（pip）

```sh:
$ pip install googleads
```

※ 本記事で検証している`googleads`のバージョンは`13.0.0`です。

## 3. OAuth2 認証の設定
以下の流れで設定します。

a. Google Developers Console の認証情報のページでクライアントIDとクライアントシークレットを取得します。
下記ページの「OAuth2 認証を設定する」を参考に...
[最初のAPI呼び出しを実行する | AdWords API](https://developers.google.com/adwords/api/docs/guides/first-api-call?hl=ja)

b. aで取得したクライアントIDとクライアントシークレットを使ってリフレッシュトークンを取得します。
下記ページの「OAuth2 リフレッシュトークンを取得してクライアントを設定する」と
[最初のAPI呼び出しを実行する | AdWords API](https://developers.google.com/adwords/api/docs/guides/first-api-call?hl=ja)
こちらの「Step 2 - Setting up the client library」を参考に...
[API access using own credentials (installed application flow) | GitHub](https://github.com/googleads/googleads-python-lib/wiki/API-access-using-own-credentials-(installed-application-flow)#step-2---setting-up-the-client-library)

c. aで取得したクライアントIDとクライアントシークレットとbで取得したリフレッシュトークンを`googleads.yaml`に設定します。
下記ページの「OAuth2 リフレッシュトークンを取得してクライアントを設定する」を参考に...
[最初のAPI呼び出しを実行する | AdWords API](https://developers.google.com/adwords/api/docs/guides/first-api-call?hl=ja)

## 4. APIで検索ボリューム・CPC・競合性の取得
以下がサンプルコードです（Python3）

```py:get_keyword_ideas.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from googleads import adwords

PAGE_SIZE = 100

def get_ads_selector(request_type, requested_attribute_types, queries):
    ads_selector = {'ideaType': 'KEYWORD', 'requestType': request_type}
    ads_selector['requestedAttributeTypes'] = requested_attribute_types
    ads_selector['paging'] = {'startIndex': '0', 'numberResults': str(PAGE_SIZE)}
    ads_selector['searchParameters'] = [{
        'xsi_type': 'RelatedToQuerySearchParameter',
        'queries': queries
    }]
    ads_selector['searchParameters'].append({
        'xsi_type': 'LanguageSearchParameter',
        'languages': [{'id': '1005'}]
    })
    ads_selector['searchParameters'].append({
        'xsi_type': 'NetworkSearchParameter',
        'networkSetting': {
            'targetGoogleSearch': True,
            'targetSearchNetwork': False,
            'targetContentNetwork': False,
            'targetPartnerSearchNetwork': False
        }
    })
    return ads_selector

def get_ads_results(ads_selector):
    ads_list = []
    page = {}
    try:
        page = targeting_idea_service.get(ads_selector)
    except Exception as e:
        print(e)

    if 'entries' in page:
        for result in page['entries']:
            attributes = {}
            for attribute in result['data']:
                attributes[attribute['key']] = getattr(attribute['value'], 'value', '0')
            if isinstance(attributes['AVERAGE_CPC'], str):
                average_cpc = int(attributes['AVERAGE_CPC'])
            elif attributes['AVERAGE_CPC'] is None:
                average_cpc = 0
            else:
                average_cpc = int(attributes['AVERAGE_CPC']['microAmount'])//1000000
            if attributes['COMPETITION'] is None:
                competition = 0.0
            else:
                competition = attributes['COMPETITION']
            if attributes['SEARCH_VOLUME'] is not None and int(attributes['SEARCH_VOLUME']) > 0:
                record = {
                    'keyword': attributes['KEYWORD_TEXT'],
                    'search_volume': attributes['SEARCH_VOLUME'],
                    'average_cpc': average_cpc,
                    'competition': competition
                }
                ads_list.append(record)
    else:
        print('Adwords API: No related keywords were found.')
    return ads_list

def main(target_keywords):
    ads_selector = get_ads_selector('IDEAS', ['KEYWORD_TEXT', 'SEARCH_VOLUME', 'AVERAGE_CPC', 'COMPETITION'], target_keywords)
    ads_list = get_ads_results(ads_selector)

    targetidea_list = []
    cnt = 0
    for row in ads_list:
        cnt += 1
        str_search_volume = str(int(row['search_volume']))
        str_average_cpc   = str(int(row['average_cpc']))
        float_competition = float(row['competition'])
        str_competition = '%.3f' % float_competition
        if float_competition >= 0.67:
            str_competition_rank = '高'
        elif float_competition >= 0.43:
            str_competition_rank = '中'
        else:
            str_competition_rank = '低'
        record = {
            'no': cnt,
            'keyword': row['keyword'],
            'search_volume': str_search_volume,
            'average_cpc': str_average_cpc,
            'competition': str_competition,
            'competition_rank': str_competition_rank
        }
        targetidea_list.append(record)

    print(targetidea_list)

if __name__ == '__main__':
    ads_client = adwords.AdWordsClient.LoadFromStorage()
    targeting_idea_service = ads_client.GetService('TargetingIdeaService', version='v201806')

    target_keywords = ['ダイエット']
    main(target_keywords)
```

※ ここでは「ダイエット」というキーワードでキーワードプランナーのデータを取得しています。
※ `googleads.yaml`はホームディレクトリに配置している想定です。場所を指定する場合はadwords.AdWordsClient.LoadFromStorage()の引数にパスを指定します。
※ APIでは、`AVERAGE_CPC`（平均CPC）は単位がmicroのため、1000000で割っています。
※ APIでは、`COMPETITION`（競合性）は小数点表記のため、キーワードプランナーの表示に合わせてランク文字列（高|中|低）も生成しています。

# APIのバージョンアップについて
本記事で検証している`TargetingIdeaService`のバージョンは`v201806`です。
AdWords APIはリリーステンポが速く、本番運用で利用するためには数ヶ月以内に新しいバージョンに移行する必要があります。
詳しくはこちら
[サポート終了と廃止のスケジュール | AdWords API](https://developers.google.com/adwords/api/docs/sunset-dates)

※最新のバージョンを使用するためには、クライアントライブラリ（googleads）も同時にバージョンアップする必要があります。

# 参考にしたサイト
・[最初のAPI呼び出しを実行する | AdWords API](https://developers.google.com/adwords/api/docs/guides/first-api-call?hl=ja)
・[キーワードプランナーもログインせずに自由自在！ AdWords API の申請と使い方](https://pct.unifas.net/programming/php/2874/)
・[googleads/googleads-python-lib | GitHub](https://github.com/googleads/googleads-python-lib/blob/master/README.md#getting-started)
・[PythonでGoogleAdwordsAPIを使って検索ボリュームを出してみた](https://qiita.com/wc_tanaka_rin/items/1dd5091ac674d7bde959)

# おわりに
Google API群の中でもAdWords APIは比較的使うまでの手続きが複雑でかなり手間取りました...
特に実装しようとしているツールの仕様ドキュメントを提出するのが億劫になりますが、
ここを突破すればデータの取得自体は非常に簡単で、かつデータの価値も高そうなのでいろいろと試してみたいと思います。