21
23

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

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

Posted at

はじめに

以前、AdWords APIを使ってキーワードプランナーのデータを取得する、というシステムを作ったのですが、
最近AdWords APIが終了する(?)という噂を耳にし、慌てて新しいGoogle Ads APIを試してみることになりました。

Google Ads APIの公式サイトはこちら
Google Ads API Beta
※ 執筆時点(2020年8月3日時点)でまだBetaは取れていないようです。

前回記事はこちら
AdWords APIでキーワードプランナーの検索ボリューム・CPC・競合性を取得する

キーワードプランナーのデータを取得するまで

前回と同様、以下の流れで説明します。

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

1. Google Ads APIを利用するための準備

Google Ads APIは無料で利用できますが、利用にあたってはMCCアカウントと開発者トークンの申請/承認手続きが必要です。
前回記事で取得しているため、ここでは省略します。
Google Ads API 公式(クイックスタート)
前回記事はこちら

2. Google Ads API Client Library for Python のインストール

※ 既にインストール済みであればこの項は不要です。

今回はGoogleが提供しているAPIクライアントライブラリ(Python)を使って取得してみます。
こちらを参考にインストールしておきます。
Google Ads API Beta > クライアントライブラリを取得する
具体的には下記コマンドで入ります(pip)

$ pip install google-ads

※ 本記事で検証しているgoogle-adsのバージョンは6.0.0です。
※ Pythonのバージョンは3.7以上

3. OAuth2 認証の設定

前回記事で設定しているため、ここでは省略します。
Google Ads API(クイックスタート)
前回記事はこちら
※ 前回のAdWords APIとは変わって、今回の設定ファイルはgoogle-ads.yamlです。
google-ads.yamlはこちらを参考にしました。
  https://github.com/googleads/google-ads-python/blob/master/google-ads.yaml
※ Google Ads APIを有効にする必要があります。
  Google Ads APIは、Google APIコンソールでAPIライブラリを広告に絞ると表示されます。
図1.png
図2.png

4. APIで検索ボリューム・CPC・競合性の取得

処理の流れをざっくり説明します。
公式の説明はここにあります。
https://developers.google.com/google-ads/api/docs/keyword-planning/generate-historical-metrics
キーワードプランナーのデータを取得するためにはKeywordPlanService.GenerateHistoricalMetricsを使う必要があります。
このAPIでは、流れとして

  1. キーワードプラン(KeywordPlan, KeywordPlanCampaigns, KeywordPlanAdGroups, KeywordPlanKeywords, and KeywordPlanNegativeKeywords.)の作成
  2. 過去の指標データ(KeywordPlanService.GenerateHistoricalMetrics)を取得
    となるので、
    まずは公式を参考にキーワードプランの作成部を起こし、
    ※ ここは公式のサンプルを参考にしました。KeywordPlanNegativeKeywordsについては今回は不要だと考えて省いてます。
    その後過去の指標データを取得する部分を作ります。
    ※ 過去の指標データ(Historical Metrics)を取得するサンプルがないため、予測データ(Forecast Metrics)を取得するサンプルを参考にして過去の指標データ取得に書き換えます。

以下が完成したサンプルコードです(Python3.7)

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

import argparse
import sys
import uuid

from google.ads.google_ads.client import GoogleAdsClient
from google.ads.google_ads.errors import GoogleAdsException

ONE_MILLION = 1.0e6

def main(client, customer_id, target_keywords):
    # キーワードプランの作成
    try:
        resource_name = add_keyword_plan(client, customer_id, target_keywords)
    except GoogleAdsException as ex:
        print(f'Request with ID "{ex.request_id}" failed with status '
              f'"{ex.error.code().name}" and includes the following errors:')
        for error in ex.failure.errors:
            print(f'\tError with message "{error.message}".')
            if error.location:
                for field_path_element in error.location.field_path_elements:
                    print(f'\t\tOn field: {field_path_element.field_name}')
        sys.exit(1)

    # 過去の指標データを取得
    keyword_plan_service = client.get_service('KeywordPlanService')
    keyword_competition_level_enum = client.get_type('KeywordPlanCompetitionLevelEnum', version='v4').KeywordPlanCompetitionLevel

    try:
        response = keyword_plan_service.generate_historical_metrics(resource_name)
    except GoogleAdsException as ex:
        print('Request with ID "{}" failed with status "%s" and includes the '
              'following errors:'.format(ex.request_id, ex.error.code().name))
        for error in ex.failure.errors:
            print('\tError with message "{}".'.format(error.message))
            if error.location:
                for field_path_element in error.location.field_path_elements:
                    print('\t\tOn field: {}'.format(field_path_element.field_name))
        sys.exit(1)

    results = []
    for i, historical in enumerate(response.metrics):
        metrics = historical.keyword_metrics
        results.append({
            'keyword':              historical.search_query.value,
            'avg_monthly_searches': metrics.avg_monthly_searches.value,
            'competition':          keyword_competition_level_enum.Name(metrics.competition),
            'competition_index':    metrics.competition_index.value,
            'low_top_of_page_bid':  metrics.low_top_of_page_bid_micros.value / ONE_MILLION,
            'high_top_of_page_bid': metrics.high_top_of_page_bid_micros.value / ONE_MILLION
        })

    print(results)


def add_keyword_plan(client, customer_id, target_keywords):
    keyword_plan = create_keyword_plan(client, customer_id)
    keyword_plan_campaign = create_keyword_plan_campaign(client, customer_id, keyword_plan)
    keyword_plan_ad_group = create_keyword_plan_ad_group(client, customer_id, keyword_plan_campaign)
    create_keyword_plan_ad_group_keywords(client, customer_id, keyword_plan_ad_group, target_keywords)

    return keyword_plan

def create_keyword_plan(client, customer_id):
    operation = client.get_type('KeywordPlanOperation', version='v4')
    keyword_plan = operation.create

    keyword_plan.name.value = (f'Keyword plan for traffic estimate {uuid.uuid4()}')

    forecast_interval = client.get_type('KeywordPlanForecastIntervalEnum', version='v4').NEXT_MONTH
    keyword_plan.forecast_period.date_interval = forecast_interval

    keyword_plan_service = client.get_service('KeywordPlanService', version='v4')
    response = keyword_plan_service.mutate_keyword_plans(customer_id, [operation])
    resource_name = response.results[0].resource_name

    print(f'Created keyword plan with resource name: {resource_name}')

    return resource_name


def create_keyword_plan_campaign(client, customer_id, keyword_plan):
    operation = client.get_type('KeywordPlanCampaignOperation', version='v4')
    keyword_plan_campaign = operation.create

    keyword_plan_campaign.name.value = f'Keyword plan campaign {uuid.uuid4()}'
    # 上限クリック単価は画面で作成した時のデフォルト値(260円)で設定してみる
    # この設定はキャンペーンではなくて広告グループや個々のキーワード毎でも設定できる
    keyword_plan_campaign.cpc_bid_micros.value = 260000000
    keyword_plan_campaign.keyword_plan.value = keyword_plan

    keyword_plan_network = client.get_type('KeywordPlanNetworkEnum', version='v4')
    network = keyword_plan_network.GOOGLE_SEARCH
    keyword_plan_campaign.keyword_plan_network = network

    geo_target = client.get_type('KeywordPlanGeoTarget', version='v4')
    # 2392:日本
    geo_target.geo_target_constant.value = 'geoTargetConstants/2392'
    keyword_plan_campaign.geo_targets.extend([geo_target])

    language = client.get_type('StringValue', version='v4')
    # 1005:日本語
    language.value = 'languageConstants/1005'
    keyword_plan_campaign.language_constants.extend([language])

    keyword_plan_campaign_service = client.get_service('KeywordPlanCampaignService', version='v4')
    response = keyword_plan_campaign_service.mutate_keyword_plan_campaigns(customer_id, [operation])

    resource_name = response.results[0].resource_name

    print(f'Created keyword plan campaign with resource name: {resource_name}')

    return resource_name


def create_keyword_plan_ad_group(client, customer_id, keyword_plan_campaign):
    operation = client.get_type('KeywordPlanAdGroupOperation', version='v4')
    keyword_plan_ad_group = operation.create

    keyword_plan_ad_group.name.value = f'Keyword plan ad group {uuid.uuid4()}'
    #keyword_plan_ad_group.cpc_bid_micros.value = 2500000
    keyword_plan_ad_group.keyword_plan_campaign.value = keyword_plan_campaign

    keyword_plan_ad_group_service = client.get_service('KeywordPlanAdGroupService', version='v4')
    response = keyword_plan_ad_group_service.mutate_keyword_plan_ad_groups(customer_id, [operation])

    resource_name = response.results[0].resource_name

    print(f'Created keyword plan ad group with resource name: {resource_name}')

    return resource_name


def create_keyword_plan_ad_group_keywords(client, customer_id, plan_ad_group, target_keywords):
    match_types = client.get_type('KeywordMatchTypeEnum', version='v4')

    keywords = []
    for target_keyword in target_keywords:
        keyword_plan_ad_group_keyword = client.get_type('KeywordPlanAdGroupKeyword', version='v4')
        keyword_plan_ad_group_keyword.text.value = target_keyword
        #keyword_plan_ad_group_keyword.cpc_bid_micros.value = 2000000
        keyword_plan_ad_group_keyword.match_type = match_types.BROAD
        keyword_plan_ad_group_keyword.keyword_plan_ad_group.value = plan_ad_group
        keywords.append(keyword_plan_ad_group_keyword)

    operations = []
    for keyword in keywords:
        operation = client.get_type('KeywordPlanAdGroupKeywordOperation', version='v4')
        operation.create.CopyFrom(keyword)
        operations.append(operation)

    keyword_plan_ad_group_keyword_service = client.get_service('KeywordPlanAdGroupKeywordService', version='v4')

    response = (keyword_plan_ad_group_keyword_service.mutate_keyword_plan_ad_group_keywords(customer_id, operations))

    for result in response.results:
        print('Created keyword plan ad group keyword with resource name: '
              f'{result.resource_name}')


if __name__ == '__main__':
    # GoogleAdsClient will read the google-ads.yaml configuration file in the
    # home directory if none is specified.
    google_ads_client = GoogleAdsClient.load_from_storage()

    parser = argparse.ArgumentParser(description='Creates a keyword plan for specified customer.')
    # The following argument(s) should be provided to run the example.
    parser.add_argument('-c', '--customer_id', type=str, required=True, help='The Google Ads customer ID.')
    args = parser.parse_args()

    target_keywords = ['ダイエット', '筋トレ', 'グルテンフリー']

    main(google_ads_client, args.customer_id, target_keywords)

※ ここでは「ダイエット」「筋トレ」「グルテンフリー」というキーワードでキーワードプランナーのデータを取得しています。
google-ads.yamlはホームディレクトリに配置している想定です。場所を指定する場合はGoogleAdsClient.load_from_storage()の引数にパスを指定します。
※ 上限クリック単価は画面で作成した時のデフォルト値(260円)で設定
※ APIでは、low_top_of_page_bid(低額帯CPC)とhigh_top_of_page_bid(高額帯CPC)は単位がmicroのため、1000000で割っています。

おわりに

Google広告に関するAPIは刷新され、今後はGoogle Ads APIに統一される流れのようです。
今回 AdWords API で行っていたキーワードプランナーのデータ取得を Google Ads API 移行してみましたが、APIだけでなくデータ項目等も変わっていて少し戸惑いました。
特にCPCが今回から低額帯と高額帯の2つに分かれており(キーワードプランナーの画面もそうなっている)今まで AdWords API で取得していた平均CPCとの整合性はどうすべきか。
低額帯と高額帯を単純に2つの平均で計算するか、もしくは今回使った過去の指標データ(Historical Metrics)ではなく予測データ(Forecast Metrics)のCPCを使うか。
時間ができればそのあたりも調べてみようと思っています。

21
23
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
21
23

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?