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。
- 左のリストから
Google Analytics Data API v1→analytics.readonlyを選択 - Authorize → Googleアカウントでログイン
- Exchange authorization code for tokens
access_tokenとrefresh_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 —scopes | ❌ | Googleにブロックされる |
| サービスアカウント | △ | GAのUI/APIから権限付与が別途必要 |
| OAuth Playground | ✅ | 一時的なアクセスに使える |
| 自前OAuthクライアント | ✅ | refresh_tokenで永続化できる |
最終的には ~/.ga4-credentials.json に認証情報を保存して、毎回 creds.refresh(Request()) で自動更新する運用に落ち着いた。