自分のポートフォリオサイトにGA4(Google Analytics 4)を入れたのに、公開してから42日間、ダッシュボードを一度も開いていなかった。開かなかった理由は単純で、AI秘書に「アクセスどう?」と聞かれるたびに、画面を開いてスクショを撮って貼るのが地味に面倒だったからだ。それなら、AIに直接読ませればいい——80行のPythonスクリプト1本で、この面倒を消した話を書く。
この記事で分かること
- GA4のダッシュボードを毎回開かずに、数字をAIへ直接届ける方法
- 常駐MCPサーバーでなく80行のスクリプトを選んだ理由
- AIに数字を読ませた瞬間に言語化された、見過ごしていた2つの異常
背景:42日間、ダッシュボードを開かなかった
ポートフォリオサイトを公開したとき、GA4のタグは最初から入れておいた。だが公開後42日間、一度もダッシュボードを開かなかった。
理由は明確だ。AI秘書との日々のやり取りの中で「アクセス増えた?」と聞かれるたびに、ブラウザでGA4を開いて、必要な画面を探して、スクショを撮って、チャットに貼る——この一連の作業がひと手間だった。数字は見たい。でも見に行くのは面倒。この矛盾を放置していた。
ある日、素朴な疑問が浮かんだ。AIが直接数字を読めば、この往復はまるごと要らないのでは。
結論:常駐サーバーでなく、80行のスクリプトを選んだ
GA4の数字をAIに読ませる手段としては、GA4専用のMCPサーバーを常駐させる選択肢もある。今回はそれを選ばず、GA4 Data APIを直叩きする80行のPythonスクリプト(scripts/ga4-report.py)を書いた。
理由は3つ。
- 常駐プロセスを増やさない。MCPサーバーは便利だが、常時起動しておく管理コストが増える。スクリプトなら実行した瞬間だけ動く
- 週次レビューの手順に1コマンドで配線できる。「このコマンドを実行して」の1行を足すだけで、毎週の定例作業に組み込める
- 依存が
google-authとrequestsだけ。軽い依存で、環境が壊れる余地が少ない
しくみ:人間の作業は準備の10分だけ
スクリプトが叩くのはGoogleの認証とAPIだけなので、事前準備が要る。ただし、この準備は最初の1回・10分程度で終わる。
| 手順 | やること |
|---|---|
| 1 | GCPプロジェクトを作成 |
| 2 | Google Analytics Data APIを有効化 |
| 3 | サービスアカウントを作成 |
| 4 | JSONキーをダウンロードして手元の秘密フォルダへ配置 |
| 5 | GA4の「プロパティのアクセス管理」にサービスアカウントのメールアドレスを閲覧者で追加 |
| 6 | プロパティIDを控える |
ここで押さえておきたいポイントが2つある。
- キーはAIとのチャットに貼らない。ファイル配置は人間が手を動かす。AIに渡すのは「このパスに置いた」という事実だけでいい
- 権限は閲覧者で足りる。書き込み権限を渡す必要はない。AIに読ませたいのは数字であって、GA4の設定をAIに変更させたいわけではない
手順:スクリプトがやっているのはrunReportを3回叩くだけ
スクリプトの中身はシンプルで、GA4 Data APIのrunReportエンドポイントを3種類のリクエストで叩いているだけだ。
# 1. 概況(アクティブユーザー・セッション・キーイベント等)
overview_body = {
"dateRanges": date_range,
"metrics": [
{"name": "activeUsers"},
{"name": "newUsers"},
{"name": "sessions"},
{"name": "averageSessionDuration"},
{"name": "keyEvents"},
],
}
# 2. 流入元(チャネル別・セッション降順)
channel_body = {
"dateRanges": date_range,
"dimensions": [{"name": "sessionDefaultChannelGroup"}],
"metrics": [{"name": "sessions"}, {"name": "activeUsers"}],
"orderBys": [{"metric": {"metricName": "sessions"}, "desc": True}],
}
# 3. 人気ページ(PV上位10)
page_body = {
"dateRanges": date_range,
"dimensions": [{"name": "pagePath"}],
"metrics": [{"name": "screenPageViews"}],
"orderBys": [{"metric": {"metricName": "screenPageViews"}, "desc": True}],
"limit": 10,
}
認証まわりも短い。サービスアカウントのcredentialsをrefreshしてトークンを取るだけで、OAuthの同意画面のような対話は要らない。
def _get_access_token(service_account, Request, key_path):
credentials = service_account.Credentials.from_service_account_file(
str(key_path), scopes=SCOPES
)
credentials.refresh(Request())
return credentials.token
エラー処理も1点だけ工夫した。キーが見つからない・API側がエラーを返す、どちらの場合もPythonのトレースバックをそのまま見せず、1行の案内文だけを出して終わるようにしている。
def _fail(message: str) -> None:
print(f"エラー: {message}", file=sys.stderr)
sys.exit(1)
実行はこの1行。
python3 scripts/ga4-report.py --property <プロパティID> --days 28
ハマり/気づき:AIに数字を読ませた瞬間、見過ごしていた異常が言語化された
初回実行はあっさり成功した。GA4の画面に表示されている数字と突き合わせて検算したところ、セッション9・Direct8/Organic1で一致した。ここまでは想定通り。
面白かったのはここから先だ。AIに読ませた途端、ダッシュボードを眺めていても素通りしていた異常が2つ、言語化された。
- 人気ページのランキングに、存在しないWordPressの管理画面パスへのアクセスが混ざっていた。このサイトは静的サイトで、そのパスは実在しない。つまりボットの探索アクセスが空振りしているだけなのだが、GA4にはそのままカウントされて乗ってくる。裏を返すと、生身の訪問者数はダッシュボードの数字よりさらに少ないということだ
- キーイベントが未設定だった。つまり、問い合わせフォームから連絡が来ても、その成果がGA4上に一切記録として残らない状態だった
どちらも、ダッシュボードを開いて眺めているだけでは気づきにくい種類の異常だ。人気ページのランキングを見て「へえ、このページが人気なんだ」で終わっていたら、ボットのアクセスを本物の訪問だと錯覚したままだったし、キーイベント未設定は「問い合わせ経路が計測できていない」という欠陥そのものに気づかないまま放置していた。
AIに数字を渡すと、人間が読み飛ばしていた前提を素直に指摘してくる。これは狙っていた副産物ではなかったが、一番の収穫だった。
コスト感・反映
- 実装:スクリプト1本・約80行、依存パッケージ2つ
- 事前準備:GCP・GA4側の設定作業で人間の手が動くのは10分程度(初回のみ)
- 実行コスト:
runReportを3回叩くだけなので、実行から結果表示まで数秒 - 反映先:週次レビューの手順に1コマンドとして配線済み
まとめ
- GA4のダッシュボードは、公開してから42日間、一度も開いていなかった。「見に行く」設計は続かない
- 常駐MCPサーバーでなく、GA4 Data APIを直叩きする80行のPythonスクリプトを選んだ。理由はプロセスを増やさないこと・週次レビューに1コマンドで配線できること・依存が軽いこと
- 人間の作業は準備の10分だけ。キーはAIに貼らせず人間がファイル配置、権限は閲覧者で足りる
- 数字をAIに直接読ませた途端、ダッシュボードを眺めていても気づかなかった異常(存在しないパスへのボットアクセス・キーイベント未設定)が言語化された
- 「勝手に届く」設計に変えたことが、ダッシュボードを開く習慣を作ろうとするより効いた
計測ツールとAIをつないだ運用設計のご相談は、お問い合わせからどうぞ。