やること
僭越ながら、Google AdSenseで広告収益を得ているのですが、毎日いくら稼げたかな〜とGoogle AdSenseにログインして確認していました。
これをプログラムで取得して、毎日Slackなどに投稿することができれば面白いなと考え、AdSense Management APIを触り始めました。
本記事では、PythonでAdSense Management APIを使用して、Google AdSenseのレポートを取得する手順を記載したいと思います。
ハマりにハマったので、備忘録として残そうと考えたのも書くきっかけです。
事前確認
手順に入る前に、まず現状を共有しておきます。
- Google AdSenseのアカウント作成は完了しています。
- Google AdSenseで収益を得ていて、レポートを作成できる状態です。
手順
Google Cloud
プロジェクトの作成
Google Cloud Platformにログインします。
新しいプロジェクトを作成します。ここでは「My Project 77498」としました。
AdSense Management APIの有効化
"Google AdSense"というワードで検索すると2件ヒットしました。「AdSense Management API」をクリックします。
OAuth同意画面の作成
「OAuth同意画面」をクリックして、OAuth同意画面を作成していきます。
「アプリ名」を入力します。ここでは「My AdSense App」としました。
「ユーザーサポートメール」をプルダウンから選びます。
「デベロッパーの連絡先情報」のメールアドレスを入力して、「保存して次へ」をクリックしました。
「スコープを追加または削除」をクリックして、スコープを追加します。
ここでは、「Google API サービスの設定の管理」の「Service Management API」を追加しました。
「保存して次へ」をクリックしました。
テストユーザーにはテストに使用するGmailのメールアドレスを入力しました。
OAuthクライアントIDの作成
「認証情報」から「認証情報の作成」をクリックし、「OAuthクライアントID」を選択します。
「アプリケーションの種類」は「ウェブアプリケーション」を選択して、いったんこのまま作成しました。
JSONの認証情報ファイルをダウンロードして、任意のディレクトリに保存しておきます。
プログラム
コードのダウンロードと認証情報ファイル配置
公式が用意しているgoogleads-adsense-examplesのコードをダウンロードします。
ダウンロードしたものの中で「python」ディレクトリをVS Codeなどで開きます。
この中に、先ほどダウンロードしたJSONの認証情報ファイルを、「client_secrets.json」という名前で保存します。デフォルトのものはバックアップを取得しました。
ディレクトリ構成は、以下のようになっているはずです。
v2--
|--python
|--adsense_util.py
|--client_secrets.json.bk
|--client_secrets.json ←先ほどダウンロードした認証情報ファイル
|--generate_report.py
|--get_account_tree.py
|--get_all_accounts.py
|--get_all_ad_clients.py
|--get_all_ad_units_for_custom_channel.py
|--get_all_ad_units.py
|--get_all_alerts.py
|--get_all_custom_channels_for_ad_unit.py
|--get_all_custom_channels.py
|--get_all_payments.py
|--get_all_saved_reports.py
|--get_all_url_channels.py
|--README.md
ライブラリのインストール
python仮想環境を用意しました。
python % python -m venv .venv
python % ll -a
total 128
drwxrwxr-x@ 19 atsushi staff 608 2 7 11:30 .
drwxrwxr-x@ 8 atsushi staff 256 2 7 11:15 ..
drwxr-xr-x 6 atsushi staff 192 2 7 11:30 .venv
-rw-rw-r--@ 1 atsushi staff 1775 5 12 2022 README.md
-rw-rw-r--@ 1 atsushi staff 3378 5 12 2022 adsense_util.py
-rw-r--r--@ 1 atsushi staff 680 2 6 14:12 client_secrets.json
-rw-rw-r--@ 1 atsushi staff 273 5 12 2022 client_secrets.json.bk
-rw-rw-r--@ 1 atsushi staff 2890 5 12 2022 generate_report.py
-rw-rw-r--@ 1 atsushi staff 2065 5 12 2022 get_account_tree.py
-rw-rw-r--@ 1 atsushi staff 1811 5 12 2022 get_all_accounts.py
-rw-rw-r--@ 1 atsushi staff 2182 5 12 2022 get_all_ad_clients.py
-rw-rw-r--@ 1 atsushi staff 2551 5 12 2022 get_all_ad_units.py
-rw-rw-r--@ 1 atsushi staff 2811 5 12 2022 get_all_ad_units_for_custom_channel.py
-rw-rw-r--@ 1 atsushi staff 1944 5 12 2022 get_all_alerts.py
-rw-rw-r--@ 1 atsushi staff 2617 5 12 2022 get_all_custom_channels.py
-rw-rw-r--@ 1 atsushi staff 2703 5 12 2022 get_all_custom_channels_for_ad_unit.py
-rw-rw-r--@ 1 atsushi staff 2169 5 12 2022 get_all_payments.py
-rw-rw-r--@ 1 atsushi staff 2121 5 12 2022 get_all_saved_reports.py
-rw-rw-r--@ 1 atsushi staff 2573 5 12 2022 get_all_url_channels.py
公式にある通り、必要ライブラリをインストールします。
python % source .venv/bin/activate
(.venv) python %
(.venv) python % pip install google-api-python-client
Collecting google-api-python-client
Using cached google_api_python_client-2.76.0-py2.py3-none-any.whl (11.0 MB)
Collecting google-auth<3.0.0dev,>=1.19.0
Using cached google_auth-2.16.0-py2.py3-none-any.whl (177 kB)
Collecting httplib2<1dev,>=0.15.0
Using cached httplib2-0.21.0-py3-none-any.whl (96 kB)
Collecting uritemplate<5,>=3.0.1
Using cached uritemplate-4.1.1-py2.py3-none-any.whl (10 kB)
Collecting google-auth-httplib2>=0.1.0
Using cached google_auth_httplib2-0.1.0-py2.py3-none-any.whl (9.3 kB)
Collecting google-api-core!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.0,<3.0.0dev,>=1.31.5
Using cached google_api_core-2.11.0-py3-none-any.whl (120 kB)
Collecting protobuf!=3.20.0,!=3.20.1,!=4.21.0,!=4.21.1,!=4.21.2,!=4.21.3,!=4.21.4,!=4.21.5,<5.0.0dev,>=3.19.5
Using cached protobuf-4.21.12-cp37-abi3-macosx_10_9_universal2.whl (486 kB)
Collecting googleapis-common-protos<2.0dev,>=1.56.2
Using cached googleapis_common_protos-1.58.0-py2.py3-none-any.whl (223 kB)
Collecting requests<3.0.0dev,>=2.18.0
Using cached requests-2.28.2-py3-none-any.whl (62 kB)
Collecting cachetools<6.0,>=2.0.0
Using cached cachetools-5.3.0-py3-none-any.whl (9.3 kB)
Collecting pyasn1-modules>=0.2.1
Using cached pyasn1_modules-0.2.8-py2.py3-none-any.whl (155 kB)
Collecting six>=1.9.0
Using cached six-1.16.0-py2.py3-none-any.whl (11 kB)
Collecting rsa<5,>=3.1.4
Using cached rsa-4.9-py3-none-any.whl (34 kB)
Collecting pyparsing!=3.0.0,!=3.0.1,!=3.0.2,!=3.0.3,<4,>=2.4.2
Using cached pyparsing-3.0.9-py3-none-any.whl (98 kB)
Collecting pyasn1<0.5.0,>=0.4.6
Using cached pyasn1-0.4.8-py2.py3-none-any.whl (77 kB)
Collecting charset-normalizer<4,>=2
Using cached charset_normalizer-3.0.1-cp39-cp39-macosx_11_0_arm64.whl (122 kB)
Collecting urllib3<1.27,>=1.21.1
Using cached urllib3-1.26.14-py2.py3-none-any.whl (140 kB)
Collecting certifi>=2017.4.17
Using cached certifi-2022.12.7-py3-none-any.whl (155 kB)
Collecting idna<4,>=2.5
Using cached idna-3.4-py3-none-any.whl (61 kB)
Installing collected packages: pyasn1, urllib3, six, rsa, pyparsing, pyasn1-modules, protobuf, idna, charset-normalizer, certifi, cachetools, requests, httplib2, googleapis-common-protos, google-auth, uritemplate, google-auth-httplib2, google-api-core, google-api-python-client
Successfully installed cachetools-5.3.0 certifi-2022.12.7 charset-normalizer-3.0.1 google-api-core-2.11.0 google-api-python-client-2.76.0 google-auth-2.16.0 google-auth-httplib2-0.1.0 googleapis-common-protos-1.58.0 httplib2-0.21.0 idna-3.4 protobuf-4.21.12 pyasn1-0.4.8 pyasn1-modules-0.2.8 pyparsing-3.0.9 requests-2.28.2 rsa-4.9 six-1.16.0 uritemplate-4.1.1 urllib3-1.26.14
(.venv) python %
(.venv) python % pip install google_auth_oauthlib
Collecting google_auth_oauthlib
Using cached google_auth_oauthlib-0.8.0-py2.py3-none-any.whl (19 kB)
Collecting requests-oauthlib>=0.7.0
Using cached requests_oauthlib-1.3.1-py2.py3-none-any.whl (23 kB)
Requirement already satisfied: google-auth>=2.15.0 in ./.venv/lib/python3.9/site-packages (from google_auth_oauthlib) (2.16.0)
Requirement already satisfied: cachetools<6.0,>=2.0.0 in ./.venv/lib/python3.9/site-packages (from google-auth>=2.15.0->google_auth_oauthlib) (5.3.0)
Requirement already satisfied: six>=1.9.0 in ./.venv/lib/python3.9/site-packages (from google-auth>=2.15.0->google_auth_oauthlib) (1.16.0)
Requirement already satisfied: rsa<5,>=3.1.4 in ./.venv/lib/python3.9/site-packages (from google-auth>=2.15.0->google_auth_oauthlib) (4.9)
Requirement already satisfied: pyasn1-modules>=0.2.1 in ./.venv/lib/python3.9/site-packages (from google-auth>=2.15.0->google_auth_oauthlib) (0.2.8)
Requirement already satisfied: pyasn1<0.5.0,>=0.4.6 in ./.venv/lib/python3.9/site-packages (from pyasn1-modules>=0.2.1->google-auth>=2.15.0->google_auth_oauthlib) (0.4.8)
Requirement already satisfied: requests>=2.0.0 in ./.venv/lib/python3.9/site-packages (from requests-oauthlib>=0.7.0->google_auth_oauthlib) (2.28.2)
Collecting oauthlib>=3.0.0
Using cached oauthlib-3.2.2-py3-none-any.whl (151 kB)
Requirement already satisfied: charset-normalizer<4,>=2 in ./.venv/lib/python3.9/site-packages (from requests>=2.0.0->requests-oauthlib>=0.7.0->google_auth_oauthlib) (3.0.1)
Requirement already satisfied: urllib3<1.27,>=1.21.1 in ./.venv/lib/python3.9/site-packages (from requests>=2.0.0->requests-oauthlib>=0.7.0->google_auth_oauthlib) (1.26.14)
Requirement already satisfied: idna<4,>=2.5 in ./.venv/lib/python3.9/site-packages (from requests>=2.0.0->requests-oauthlib>=0.7.0->google_auth_oauthlib) (3.4)
Requirement already satisfied: certifi>=2017.4.17 in ./.venv/lib/python3.9/site-packages (from requests>=2.0.0->requests-oauthlib>=0.7.0->google_auth_oauthlib) (2022.12.7)
Installing collected packages: oauthlib, requests-oauthlib, google-auth-oauthlib
Successfully installed google-auth-oauthlib-0.8.0 oauthlib-3.2.2 requests-oauthlib-1.3.1
承認済みのリダイレクトURIの追加
試しにここで、「generate_report.py」を実行してみます。
(.venv) python % python generate_report.py
redirect_uri_mismatch
のエラーが発生します。
ここで、「エラーの詳細」をクリックします。
リダイレクトURIにhttp://localhost:8080/
を入れてくれと丁寧に書いてあるので、「OAuthクライアントID」に、このURIを追記します。
先ほど作ったOAuthクライアントIDの「承認済みのリダイレクトURI」にhttp://localhost:8080/
を追加します。
レポート生成
もう一度、generate_report.py
を実行してみます。
今度は「アカウントの選択」画面が表示されました。
使用するアカウントを選択します。
「認証が完了しました。ウィンドウを閉じてもよい」という旨のメッセージが表示されるので、ブラウザのウィンドウを閉じます。
もう一度generate_report.py
を実行します。
今回はレポート結果が表示されました。
(.venv) python % python generate_report.py
{'totalMatchedRows': '4', 'headers': [{'name': 'MONTH', 'type': 'DIMENSION'}, {'name': 'PLATFORM_TYPE_NAME', 'type': 'DIMENSION'}, {'name': 'PAGE_VIEWS', 'type': 'METRIC_TALLY'}, {'name': 'AD_REQUESTS', 'type': 'METRIC_TALLY'}, {'name': 'AD_REQUESTS_COVERAGE', 'type': 'METRIC_RATIO'}, {'name': 'CLICKS', 'type': 'METRIC_TALLY'}, {'name': 'AD_REQUESTS_CTR', 'type': 'METRIC_RATIO'}, {'name': 'COST_PER_CLICK', 'type': 'METRIC_CURRENCY', 'currencyCode': 'JPY'}, {'name': 'AD_REQUESTS_RPM', 'type': 'METRIC_CURRENCY', 'currencyCode': 'JPY'}, {'name': 'ESTIMATED_EARNINGS', 'type': 'METRIC_CURRENCY', 'currencyCode': 'JPY'}], 'rows': [{'cells': [{'value': '2021-03'}, {'value': 'Other devices'}, {'value': '1'}, {'value': '2'}, {'value': '1'}, {'value': '0'}, {'value': '0'}, {'value': '0'}, {'value': '0'}, {'value': '0'}]}, {'cells': [{'value': '2021-03'}, {'value': 'Tablets'}, {'value': '142'}, {'value': '428'}, {'value': '0.9533'}, {'value': '0'}, {'value': '0'}, {'value': '0'}, {'value': '6'}, {'value': '3'}]}, {'cells': [{'value': '2021-03'}, {'value': 'High-end mobile devices'}, {'value': '4028'}, {'value': '16179'}, {'value': '0.9906'}, {'value': '35'}, {'value': '0.0022'}, {'value': '18'}, {'value': '39'}, {'value': '633'}]}, {'cells': [{'value': '2021-03'}, {'value': 'Desktop'}, {'value': '7288'}, {'value': '27379'}, {'value': '0.9938'}, {'value': '17'}, {'value': '0.0006'}, {'value': '59'}, {'value': '37'}, {'value': '1011'}]}], 'totals': {'cells': [{}, {}, {'value': '11459'}, {'value': '43988'}, {'value': '0.9922'}, {'value': '52'}, {'value': '0.0012'}, {'value': '32'}, {'value': '37'}, {'value': '1647'}]}, 'averages': {'cells': [{}, {}, {'value': '2864'}, {'value': '10997'}, {'value': '0'}, {'value': '13'}, {'value': '0'}, {'value': '0'}, {'value': '0'}, {'value': '412'}]}, 'startDate': {'year': 2021, 'month': 3, 'day': 1}, 'endDate': {'year': 2021, 'month': 3, 'day': 31}}
MONTH PLATFORM_TYPE_NAME PAGE_VIEWS AD_REQUESTS AD_REQUESTS_COVERAGE CLICKS AD_REQUESTS_CTR COST_PER_CLICK AD_REQUESTS_RPM ESTIMATED_EARNINGS
2021-03 Other devices 1 2 1 0 0 0 0 0 2021-03 Tablets 142 428 0.9533 0 0 0 6 3 2021-03 High-end mobile devices 4028 16179 0.9906 35 0.0022 18 39 633 2021-03 Desktop 7288 27379 0.9938 17 0.0006 59 37 1011
Report from {'year': 2021, 'month': 3, 'day': 1} to {'year': 2021, 'month': 3, 'day': 31}.
補足
adsense_util.py
pythonディレクトリの中の、adsense_util.py
を実行すると、次の実行からログインを求められずにレポートを生成できます。
adsense_util.py
を実行すると、実行ディレクトリにadsense.dat
ファイルが生成されます。
(.venv) python % python adsense_util.py
(.venv) python % ll -a
total 152
drwxrwxr-x@ 22 atsushi staff 704 2 7 11:54 .
drwxrwxr-x@ 8 atsushi staff 256 2 7 11:15 ..
-rw-r--r--@ 1 atsushi staff 6148 2 7 11:43 .DS_Store
drwxr-xr-x 6 atsushi staff 192 2 7 11:30 .venv
-rw-rw-r--@ 1 atsushi staff 1775 5 12 2022 README.md
drwxr-xr-x 3 atsushi staff 96 2 7 11:42 __pycache__
-rw-r--r-- 1 atsushi staff 649 2 7 11:54 adsense.dat
-rw-rw-r--@ 1 atsushi staff 3378 5 12 2022 adsense_util.py
-rw-r--r--@ 1 atsushi staff 366 2 7 11:43 client_secrets.json
-rw-rw-r--@ 1 atsushi staff 273 5 12 2022 client_secrets.json.bk
-rw-rw-r--@ 1 atsushi staff 2890 5 12 2022 generate_report.py
-rw-rw-r--@ 1 atsushi staff 2065 5 12 2022 get_account_tree.py
-rw-rw-r--@ 1 atsushi staff 1811 5 12 2022 get_all_accounts.py
-rw-rw-r--@ 1 atsushi staff 2182 5 12 2022 get_all_ad_clients.py
-rw-rw-r--@ 1 atsushi staff 2551 5 12 2022 get_all_ad_units.py
-rw-rw-r--@ 1 atsushi staff 2811 5 12 2022 get_all_ad_units_for_custom_channel.py
-rw-rw-r--@ 1 atsushi staff 1944 5 12 2022 get_all_alerts.py
-rw-rw-r--@ 1 atsushi staff 2617 5 12 2022 get_all_custom_channels.py
-rw-rw-r--@ 1 atsushi staff 2703 5 12 2022 get_all_custom_channels_for_ad_unit.py
-rw-rw-r--@ 1 atsushi staff 2169 5 12 2022 get_all_payments.py
-rw-rw-r--@ 1 atsushi staff 2121 5 12 2022 get_all_saved_reports.py
-rw-rw-r--@ 1 atsushi staff 2573 5 12 2022 get_all_url_channels.py
デフォルトでは2021年3月のレポート
デフォルトのプログラムでは2021年3月のレポート(2021年3月1日〜2021年3月31日)を取得するものとなっています。
startDate_year
、startDate_month
、startDate_day
、endDate_year
、endDate_month
、endDate_day
に代入する数値を適宜修正してください。
また、metrics
やdimensions
も適宜修正して、好みのレポートを生成してください。
昨日の収益のレポートを生成する
自分が修正したコードを共有させていただきます。
昨日の収益を取得するように、generate_report.py
を少し修正しました。オリジナルのものはgitの公式のものを見てください。
-
datetime
からdatetime
とtimedelta
をインポート。 - 昨日の年月日を取得する
get_yesterday()
関数を作成。 -
main()
関数の中でget_yesterday()
を呼び出す。 - 取得した昨日の年月日を、
startDate_year
、startDate_month
、startDate_day
、endDate_year
、endDate_month
、endDate_day
に代入するように修正。 -
dimensions
をDATE
に修正。 -
orderBy
を+DATE
に修正。
#!/usr/bin/python
#
# Copyright 2021 Google LLC.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Retrieves a saved report or generates a new one.
To get saved reports, run get_all_saved_reports.py.
Tags: accounts.reports.generate
"""
import adsense_util
import argparse
import sys
import google.auth.exceptions
from googleapiclient import discovery
from datetime import datetime, timedelta # 追記
# Declare command-line flags.
argparser = argparse.ArgumentParser(add_help=True)
argparser.add_argument(
'--report_id',
help='The ID of the saved report to generate.')
args = argparser.parse_args()
saved_report_id = args.report_id
### 追記(ここから) ###
def get_yesterday():
yesterday = datetime.now() - timedelta(1)
year = yesterday.year
month = yesterday.month
day = yesterday.day
return year, month, day
### 追記(ここまで) ###
def main(argv):
# Authenticate and construct service.
credentials = adsense_util.get_adsense_credentials()
with discovery.build('adsense', 'v2', credentials = credentials) as service:
try:
# Let the user pick account if more than one.
account_id = adsense_util.get_account_id(service)
# 昨日の年月日を取得する
year, month, day = get_yesterday() # 追記
# Retrieve report.
if saved_report_id:
result = service.accounts().reports().saved().generate(
name=saved_report_id, dateRange='LAST_7_DAYS').execute()
else:
result = service.accounts().reports().generate(
account=account_id, dateRange='CUSTOM',
startDate_year=year, startDate_month=month, startDate_day=day, # year, month, dayに修正
endDate_year=year, endDate_month=month, endDate_day=day, # year, month, dayに修正
metrics=['PAGE_VIEWS', 'AD_REQUESTS', 'AD_REQUESTS_COVERAGE',
'CLICKS', 'AD_REQUESTS_CTR', 'COST_PER_CLICK',
'AD_REQUESTS_RPM', 'ESTIMATED_EARNINGS'],
dimensions=['DATE'], # DATEに修正
orderBy=['+DATE']).execute() # DATEに修正
print(result)
# Display headers.
for header in result['headers']:
print('%25s' % header['name'], end=''),
print()
# Display results.
if 'rows' in result:
for row in result['rows']:
for cell in row['cells']:
print('%25s' % cell['value'], end='')
print()
# Display date range.
print('Report from %s to %s.' % (result['startDate'], result['endDate']))
print()
except google.auth.exceptions.RefreshError:
print('The credentials have been revoked or expired, please delete the '
'"%s" file and re-run the application to re-authorize.' %
adsense_util.CREDENTIALS_FILE)
if __name__ == '__main__':
main(sys.argv)
実行します。
(.venv) python % python generate_report.py
{'totalMatchedRows': '1', 'headers': [{'name': 'DATE', 'type': 'DIMENSION'}, {'name': 'PAGE_VIEWS', 'type': 'METRIC_TALLY'}, {'name': 'AD_REQUESTS', 'type': 'METRIC_TALLY'}, {'name': 'AD_REQUESTS_COVERAGE', 'type': 'METRIC_RATIO'}, {'name': 'CLICKS', 'type': 'METRIC_TALLY'}, {'name': 'AD_REQUESTS_CTR', 'type': 'METRIC_RATIO'}, {'name': 'COST_PER_CLICK', 'type': 'METRIC_CURRENCY', 'currencyCode': 'JPY'}, {'name': 'AD_REQUESTS_RPM', 'type': 'METRIC_CURRENCY', 'currencyCode': 'JPY'}, {'name': 'ESTIMATED_EARNINGS', 'type': 'METRIC_CURRENCY', 'currencyCode': 'JPY'}], 'rows': [{'cells': [{'value': '2023-02-06'}, {'value': '594'}, {'value': '2182'}, {'value': '0.9973'}, {'value': '2'}, {'value': '0.0009'}, {'value': '6'}, {'value': '5'}, {'value': '12'}]}], 'totals': {'cells': [{}, {'value': '594'}, {'value': '2182'}, {'value': '0.9973'}, {'value': '2'}, {'value': '0.0009'}, {'value': '6'}, {'value': '5'}, {'value': '12'}]}, 'averages': {'cells': [{}, {'value': '594'}, {'value': '2182'}, {'value': '0'}, {'value': '2'}, {'value': '0'}, {'value': '0'}, {'value': '0'}, {'value': '12'}]}, 'startDate': {'year': 2023, 'month': 2, 'day': 6}, 'endDate': {'year': 2023, 'month': 2, 'day': 6}}
DATE PAGE_VIEWS AD_REQUESTS AD_REQUESTS_COVERAGE CLICKS AD_REQUESTS_CTR COST_PER_CLICK AD_REQUESTS_RPM ESTIMATED_EARNINGS
2023-02-06 594 2182 0.9973 2 0.0009 6 5 12
Report from {'year': 2023, 'month': 2, 'day': 6} to {'year': 2023, 'month': 2, 'day': 6}.
参考サイト