はじめに
以前、AdWords APIを使ってキーワードプランナーのデータを取得する、というシステムを作ったのですが、
最近AdWords APIが終了する(?)という噂を耳にし、慌てて新しいGoogle Ads APIを試してみることになりました。
Google Ads APIの公式サイトはこちら
Google Ads API Beta
※ 執筆時点(2020年8月3日時点)でまだBetaは取れていないようです。
前回記事はこちら
AdWords APIでキーワードプランナーの検索ボリューム・CPC・競合性を取得する
キーワードプランナーのデータを取得するまで
前回と同様、以下の流れで説明します。
- Google Ads APIを利用するための準備
- Google Ads API Client Library for Python のインストール
- OAuth2 認証の設定
- 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ライブラリを広告に絞ると表示されます。
4. APIで検索ボリューム・CPC・競合性の取得
処理の流れをざっくり説明します。
公式の説明はここにあります。
https://developers.google.com/google-ads/api/docs/keyword-planning/generate-historical-metrics
キーワードプランナーのデータを取得するためにはKeywordPlanService.GenerateHistoricalMetrics
を使う必要があります。
このAPIでは、流れとして
- キーワードプラン(
KeywordPlan
,KeywordPlanCampaigns
,KeywordPlanAdGroups
,KeywordPlanKeywords
, andKeywordPlanNegativeKeywords
.)の作成 - 過去の指標データ(
KeywordPlanService.GenerateHistoricalMetrics
)を取得
となるので、
まずは公式を参考にキーワードプランの作成部を起こし、
※ ここは公式のサンプルを参考にしました。KeywordPlanNegativeKeywords
については今回は不要だと考えて省いてます。
その後過去の指標データを取得する部分を作ります。
※ 過去の指標データ(Historical Metrics)を取得するサンプルがないため、予測データ(Forecast Metrics)を取得するサンプルを参考にして過去の指標データ取得に書き換えます。
以下が完成したサンプルコードです(Python3.7)
#!/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を使うか。
時間ができればそのあたりも調べてみようと思っています。