まえがき
やること
Google Analyticsで集計したデータ(ここでは1昨日の投稿ごとのページビュー)をPythonで取得してレポートを作成し、Slackに投稿してみたいと思います。
PythonはLambdaで動かします。
書くきっかけ
毎日、Google Analyticsで投稿ごとのページビューを確認しています。
スマホアプリで開いて確認したり、WEBで確認したりしています。
これをプログラムで行うことができないかと考え始め、Google Analytics Data APIというものがあることを知り、挑戦してみることにしました。
構成図
今回作成するものを構成図にすると、以下のようになると思います。
作業環境
作業環境にはAmazon Linux 2のEC2インスタンスを使用します。バージョンなどは以下のようになっています。また、Google AnalyticsはGA4を使用しています。
$ cat /etc/os-release
NAME="Amazon Linux"
VERSION="2"
ID="amzn"
ID_LIKE="centos rhel fedora"
VERSION_ID="2"
PRETTY_NAME="Amazon Linux 2"
ANSI_COLOR="0;33"
CPE_NAME="cpe:2.3:o:amazon:amazon_linux:2"
HOME_URL="https://amazonlinux.com/"
$ cat /etc/image-id
image_name="amzn2-ami-kernel-5.10-hvm"
image_version="2"
image_arch="x86_64"
image_file="amzn2-ami-kernel-5.10-hvm-2.0.20221103.3-x86_64.xfs.gpt"
image_stamp="b928-dd59"
image_date="20221112010958"
recipe_name="amzn2 ami"
recipe_id="5711a1a3-4075-cb3e-5910-2700-f037-ba87-de68b995"
$ python3 --version
Python 3.7.10
$ pip3 --version
pip 20.2.2 from /usr/lib/python3.7/site-packages/pip (python 3.7)
Google Analyticsの利用開始はされており、サイト(ブログやQiita)にGoogleタグを追加してイベントデータを収集は開始されている前提とします。
手順
Google Analytics Data APIを有効化する
こちらは手元の作業PCで行います。
API Quickstartにアクセスして、[Enable the Google Analytics Data API v1]のボタンをクリックします。
プロジェクトの名前を適当に入力して(ここでは"Quickstart")、[NEXT]をクリックします。
[DOWNLOAD PRIVATE KEY AS JSON]のボタンをクリックして、Google認証情報が書かれたJSONファイルをダウンロードします。
このファイルは後ほどEC2にアップロードします。
Google AnalyticsへAPI用のユーザーを追加する
先ほどダウンロードしたJSONファイルに記載されたユーザー名で、Google Analyticsに新規ユーザーを追加します。
Google Analyticsにアクセスして、[管理]の歯車をクリックします。
[アカウントのアクセス管理]をクリックします。
右上の+ボタンから[ユーザーを追加]をクリックします。
メールアドレスを入力する欄に、先ほどダウンロードしたJSONファイルの中の、"client_email"のメールアドレスをコピペします。役割は「アナリスト」を選択して、[追加]ボタンをクリックします。
EC2にJSONファイルをアップロード
Google認証情報が記載されたJSONファイルをEC2にアップロードします。
ここではFileZillaを使用してec2-userのホームディレクトリにアップロードしました。
SlackのWebhookのURL作成
Slackでチャンネルを作成し、WebhookのURLを取得します。
Slack での Incoming Webhook の利用
パッケージダウンロード
ここからEC2インスタンスでの作業です。
Lambdaレイヤー作成のため、必要なパッケージをpipで集めます。
### Python仮想環境作成
$ python3 -m venv .venv
### Python仮想環境起動
$ source .venv/bin/activate
### pythonディレクトリ作成(Lambdaレイヤー作成のためのもの)
(.venv)$ mkdir python
### google-analytics-dataパッケージをpythonディレクトリにダウンロード
(.venv)$ pip3 install google-analytics-data -t python
Collecting google-analytics-data
Using cached google_analytics_data-0.14.2-py2.py3-none-any.whl (108 kB)
(中略)
Collecting pyasn1>=0.1.3
Using cached pyasn1-0.4.8-py2.py3-none-any.whl (77 kB)
Installing collected packages: protobuf, proto-plus, cachetools, pyasn1, rsa, pyasn1-modules, six, google-auth, googleapis-common-protos, urllib3, charset-normalizer, idna, certifi, requests, grpcio, grpcio-status, google-api-core, google-analytics-data
Successfully installed cachetools-5.2.0 certifi-2022.9.24 charset-normalizer-2.1.1 google-analytics-data-0.14.2 google-api-core-2.11.0 google-auth-2.15.0 googleapis-common-protos-1.57.0 grpcio-1.51.1 grpcio-status-1.51.1 idna-3.4 proto-plus-1.22.1 protobuf-4.21.10 pyasn1-0.4.8 pyasn1-modules-0.2.8 requests-2.28.1 rsa-4.9 six-1.16.0 urllib3-1.26.13
WARNING: Target directory /home/ec2-user/python/google already exists. Specify --upgrade to force replacement.
### slackwebパッケージをpythonディレクトリにダウンロード
(.venv)$ pip3 install slackweb -t python
Collecting slackweb
Downloading slackweb-1.0.5.tar.gz (1.3 kB)
Using legacy setup.py install for slackweb, since package 'wheel' is not installed.
Installing collected packages: slackweb
Running setup.py install for slackweb ... done
Successfully installed slackweb-1.0.5
これで十分だと思ったのですが、実際にLambdaで動かしてみるとprotobuf
パッケージが無いとのエラーが出ました。
pip3 install protobuf -t python
ではダウンロードできず、pip3 install protobuf -t python --upgrade
ではgoogle
フォルダが上書きされてしまうので、別ディレクトリにprotobuf
をダウンロードしてコピーしました。
### tmpディレクトリ作成
(.venv)$ mkdir tmp
### protobufパッケージをtmpディレクトリにダウンロード
(.venv)$ pip3 install protobuf -t tmp
Collecting protobuf
Using cached protobuf-4.21.10-cp37-abi3-manylinux2014_x86_64.whl (408 kB)
Installing collected packages: protobuf
Successfully installed protobuf-4.21.10
### tmpディレクトリの中身をpythonディレクトリにコピー
(.venv)$ cp -rp tmp/* python/
### zipに固める
(.venv)$ zip -r layer.zip python
adding: python/ (stored 0%)
adding: python/idna/ (stored 0%)
adding: python/idna/__init__.py (deflated 67%)
(中略)
adding: python/slackweb-1.0.5-py3.7.egg-info/SOURCES.txt (deflated 46%)
adding: python/slackweb-1.0.5-py3.7.egg-info/top_level.txt (stored 0%)
adding: python/slackweb-1.0.5-py3.7.egg-info/installed-files.txt (deflated 44%)
Lambdaレイヤー作成
zipに固めたパッケージでLambdaレイヤーを作成します。
### AWS認証情報作成
(.venv)$ aws configure
AWS Access Key ID [None]: XXXXXXXXXXXXXXXXXXXX
AWS Secret Access Key [None]: ****************************************
Default region name [None]: us-east-1
Default output format [None]:
## AWS認証情報設定
(.venv)$ export AWS_PROFILE=default
### Lambdaレイヤー作成
(.venv)$ aws lambda publish-layer-version \
--layer-name analytics-data-slackweb \
--zip-file fileb://layer.zip \
--compatible-runtimes python3.7
Lambdaにアタッチするロールを作成します。
### Lambdaにアタッチするロール作成
(.venv)$ aws iam create-role \
--role-name lambda-ex \
--assume-role-policy-document '{"Version": "2012-10-17","Statement": [{ "Effect": "Allow", "Principal": {"Service": "lambda.amazonaws.com"}, "Action": "sts:AssumeRole"}]}'
### ロールにポリシーをアタッチ
(.venv)$ aws iam attach-role-policy \
--role-name lambda-ex \
--policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
プログラム作成
Google Analyticsのレポートを作成するプログラムのサンプルが公開されています。
Creating a Reportのサンプルプログラムを少し修正して、EC2のec2-userのホームディレクトリにlambda_function.pyとして保存しました。
from google.analytics.data_v1beta import BetaAnalyticsDataClient
from google.analytics.data_v1beta.types import (
DateRange,
Dimension,
Metric,
MetricType,
RunReportRequest,
)
import slackweb
from datetime import datetime
from datetime import timedelta
def lambda_handler(event, context):
"""Runs the sample."""
# TODO(developer): Replace this variable with your Google Analytics 4
# property ID before running the sample.
property_id = "XXXXXXXXX" # ←Google AnalyticsのプロパティIDを記載
report = run_report(property_id)
check_day = (datetime.today() - timedelta(days=1)).strftime('%Y-%m-%d')
start_char = ("#############################" + "\n"
"#### {0} ###############".format(check_day) + "\n"
+ "#############################"
)
end_char = "#############################"
slack = slackweb.Slack(url="https://hooks.slack.com/services/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")
slack.notify(text=start_char)
slack.notify(text=report)
slack.notify(text=end_char)
def run_report(property_id="YOUR-GA4-PROPERTY-ID"):
check_day = ((datetime.today())- timedelta(days=1)).strftime('%Y-%m-%d') # 昨日の日付取得
"""Runs a report of active users grouped by country."""
client = BetaAnalyticsDataClient()
request = RunReportRequest(
property=f"properties/{property_id}",
dimensions=[Dimension(name="pageTitle")], # ページごとのタイトルを取得する
metrics=[Metric(name="screenPageViews")], # ページごとのビュー数を取得する
date_ranges=[DateRange(start_date=str(check_day), end_date=str(check_day))],
)
response = client.run_report(request)
return print_run_report_response(response)
def print_run_report_response(response):
"""Prints results of a runReport call."""
print(f"{response.row_count} rows received")
for dimensionHeader in response.dimension_headers:
print(f"Dimension header name: {dimensionHeader.name}")
for metricHeader in response.metric_headers:
metric_type = MetricType(metricHeader.type_).name
print(f"Metric header name: {metricHeader.name} ({metric_type})")
print("Report result:")
report = ""
for rowIdx, row in enumerate(response.rows):
if rowIdx < 30:
for i, dimension_value in enumerate(row.dimension_values):
dimension_name = response.dimension_headers[i].name
dimension_result = f"タイトル: {dimension_value.value}".strip(" | Atsushi Notes")
print(dimension_result)
for i, metric_value in enumerate(row.metric_values):
metric_name = response.metric_headers[i].name
metric_result = f"ビュー数: {metric_value.value}"
print(metric_result)
else:
break
report = report + dimension_result + "\n" + metric_result + "\n" + "\n"
return report
Google AnalyticsのIDは、プロパティを選択して、[プロパティ設定]から確認できます。
Lambda関数作成
作成したlambda_function.py
とGoogle認証情報が記載されたJSONファイルをzipに固めます。
(.venv)$ zip CheckGoogleAnalytics.zip lambda_function.py Quickstart-XXXXXXXXXXXX.json
adding: lambda_function.py (deflated 60%)
adding: Quickstart-XXXXXXXXXXXX.json (deflated 31%)
AWS CLIでLambda関数を作成します。
(.venv)$ aws lambda create-function \
--function-name CheckGoogleAnalytics \
--zip-file fileb://CheckGoogleAnalytics.zip \
--handler lambda_function.lambda_handler \
--runtime python3.7 \
--role arn:aws:iam::XXXXXXXXXXXX:role/lambda-ex \
--timeout 900 \
--layers "arn:aws:lambda:us-east-1:XXXXXXXXXXXX:layer:analytics-data-slackweb:1" \
--environment Variables='{GOOGLE_APPLICATION_CREDENTIALS="Quickstart-XXXXXXXXXXXX.json", TZ="Asia/Tokyo"}'
- 関数名は「CheckGoogleAnalytics」としました。
- 先ほど作成したロールをアタッチします。
- タイムアウトは最大の15分にしました。
- 先ほど作成したレイヤーを指定します。
- 環境変数にキーが
GOOGLE_APPLICATION_CREDENTIALS
で値がQuickstart-XXXXXXXXXXXX.json
(Googleの認証情報が記載されたJSONファイル名)を指定します。
※lambda_function.py
と同じディレクトリにQuickstart-XXXXXXXXXXXX.json
を保存しているので参照できます。
実行
Lambda関数を実行します。
(.venv)$ aws lambda invoke --function-name CheckGoogleAnalytics out --log-type Tail
{
"LogResult": "(省略)",
"ExecutedVersion": "$LATEST",
"StatusCode": 200
}
以上です。
最後までお読みいただきありがとうございました。
なにかの参考になれば幸いです。
参考サイト
API Quickstart
Creating a Report
API Dimensions & Metrics
Python ModuleNotFoundError: No module named 'google.analytics'
AWS LambdaでAWS CLIから関数にLayerを追加・削除する方法
AWS CLI での Lambda の使用
【Python】日付 datetimeの足し算・引き算
[解決!Python]日付や時刻をYYMMDDhhmmssなどの形式に書式化するには
Pythonからslackに通知する方法【サンプルコードあり】