tech.sinayaka.com

PythonからGA4 Data APIにアクセスするまでが長かった

2026-06-03
2026-06-06
4分
657語
Web技術 PythonGA4Firebase

iOSアプリのFirebase Analyticsデータを定期的にPythonで取得したかった。GA4 Data APIを叩けばいいだけの話なのに、認証で半日溶かした。

何がダメだったか

GA4 Data APIには analytics.readonly スコープが必要。これが曲者で、手元の認証情報のどれも持っていなかった。

Firebase CLI トークン → ❌

token = json.loads(Path.home().joinpath('.config/configstore/firebase-tools.json').read_text())['tokens']['access_token']
# → 401

Firebase CLIのトークンにはFirebase系のスコープしかない。GA4は別。

gcloud トークン → ❌

TOKEN=$(gcloud auth print-access-token)
curl -H "Authorization: Bearer $TOKEN" https://analyticsdata.googleapis.com/...
# → 403 ACCESS_TOKEN_SCOPE_INSUFFICIENT

gcloudのトークンは cloud-platform スコープのみ。

gcloud auth application-default login --scopes=... → ❌

gcloud auth application-default login \
  --scopes=https://www.googleapis.com/auth/analytics.readonly,...
# → Googleにブロックされる

gcloudのOAuthクライアントに analytics.readonly が登録されていないのでそもそもリクエストできない。

サービスアカウント → ほぼ❌

サービスアカウントは作れるし、キーも生成できる。でもGA4プロパティへのアクセス権を付与するには、GAのUIかAnalytics Admin APIが必要。

UIからサービスアカウントのメールアドレスを追加しようとしたら「Googleアカウントと一致しません」と弾かれた。サービスアカウントのメールはGoogleアカウントではないのでGAのUIから直接追加できない。Analytics Admin APIで追加しようとしたら、それにも analytics.manage.users スコープが必要で…という無限ループ。

解決策: OAuth 2.0 Playground

一番手軽だったのが Google OAuth 2.0 Playground

  1. 左のリストから Google Analytics Data API v1analytics.readonly を選択
  2. Authorize → Googleアカウントでログイン
  3. Exchange authorization code for tokens
  4. access_tokenrefresh_token を取得

ただしPlaygroundのOAuthクライアントは独自のものなので、refresh_token を使い回すには同じクライアントが必要。別のクライアントでは使えない。

永続化: 自前OAuthクライアントを作る

GCP Console で OAuth 2.0クライアントID(デスクトップアプリ)を作成して client_secret.json をダウンロード。その後ローカルでブラウザ認証フローを走らせる。

from google_auth_oauthlib.flow import InstalledAppFlow

SCOPES = ["https://www.googleapis.com/auth/analytics.readonly"]
flow = InstalledAppFlow.from_client_secrets_file("client_secret.json", SCOPES)
creds = flow.run_local_server(port=8080, prompt='consent')

# refresh_tokenを保存しておけば次回以降はブラウザ不要
import json
json.dump({
    "refresh_token": creds.refresh_token,
    "client_id": creds.client_id,
    "client_secret": creds.client_secret,
    "token_uri": creds.token_uri,
    "scopes": list(creds.scopes)
}, open("~/.ga4-credentials.json", "w"))

ただし、GCPプロジェクトで Google Analytics Data API を有効化していないと動かない。

gcloud services enable analyticsdata.googleapis.com --project=YOUR_PROJECT

毎回使う時のコード

from google.analytics.data_v1beta import BetaAnalyticsDataClient
from google.analytics.data_v1beta.types import RunReportRequest, DateRange, Metric
from google.oauth2.credentials import Credentials
from google.auth.transport.requests import Request
import json, pathlib

c = json.loads(pathlib.Path.home().joinpath('.ga4-credentials.json').read_text())
creds = Credentials(
    token=None,
    refresh_token=c['refresh_token'],
    token_uri=c['token_uri'],
    client_id=c['client_id'],
    client_secret=c['client_secret'],
    scopes=c['scopes']
)
creds.refresh(Request())  # access_tokenを自動更新
client = BetaAnalyticsDataClient(credentials=creds)

req = RunReportRequest(
    property="properties/YOUR_PROPERTY_ID",
    date_ranges=[DateRange(start_date="30daysAgo", end_date="today")],
    metrics=[Metric(name="activeUsers")]
)
resp = client.run_report(req)
print(resp.rows[0].metric_values[0].value)

まとめ

方法結果理由
Firebase CLIトークンanalyticsスコープなし
gcloudトークンanalyticsスコープなし
gcloud —scopesGoogleにブロックされる
サービスアカウントGAのUI/APIから権限付与が別途必要
OAuth Playground一時的なアクセスに使える
自前OAuthクライアントrefresh_tokenで永続化できる

最終的には ~/.ga4-credentials.json に認証情報を保存して、毎回 creds.refresh(Request()) で自動更新する運用に落ち着いた。




Copyright 2026
サイトマップ