第9回 GA4 Data APIをCloudflareビルドで使う―サービスアカウントが使えずOAuthへ切り替える

GA4 Data APIで取得した記事別PVをCloudflare Pagesのビルドでも使うため、サービスアカウント、組織ポリシー、OAuth本番化、ADC再認証、Cloudflare Secret登録までを確認した。

執筆:ゆまラボ運営者

公開:
第9回 GA4 Data APIをCloudflareビルドで使う―サービスアカウントが使えずOAuthへ切り替える

第8回では、GA4 Data APIから記事別PVを取得できるところまで進めた。

ローカルでは node scripts/ga-pageviews.mjs を実行すると、pagePathscreenPageViews を取得できる。

次は、このデータをゆまラボのTOPページへ反映したい。ただし、ゆまラボはCloudflare PagesのビルドでAstroを生成している。ローカルのgcloud認証だけでは、Cloudflareのビルド環境からGA4 Data APIへ接続できない。

Cloudflare側でもGA4を読める認証方法を作る。

最初はサービスアカウントを使う予定で進めたが、途中でGoogle Cloudの組織ポリシーに止められた。そのため、既存のOAuth認証をCloudflareビルドでも使える形へ変更した。

サービスアカウントから試す#

Cloudflareのビルドでは人がブラウザでログインできない。そこで最初に考えたのが、GA4読み取り専用のサービスアカウントを作り、JSONキーをCloudflareのSecretへ登録する方法だ。

Google Cloudで yumalabo-ga4-build というサービスアカウントを作成し、JSON形式の秘密鍵を作ろうとした。

ところが、キーの作成画面から先へ進めなかった。

サービスアカウントキーの作成が組織ポリシーでブロックされた画面

表示された制約は次のものだ。

iam.disableServiceAccountKeyCreation

画面には「サービス アカウント キーの作成が無効になっています」と表示され、組織ポリシーによってキー作成がブロックされていた。ここで最初の予定が崩れた。

Google Cloudの公式ドキュメントでも、この制約が適用されているプロジェクトではサービスアカウントキーを作成できないと説明されている。

ここでサービスアカウント方式をそのまま続けることはできなくなった。

新しい制約は未適用。ただし以前の制約が有効#

組織ポリシーを確認すると、新しいマネージド制約 iam.managed.disableServiceAccountKeyCreation 自体は未適用になっている。

ただし、画面上部には以前の制約 iam.disableServiceAccountKeyCreation が有効と表示されていた。

「以前の制約を表示」から確認すると、こちらは親ポリシーを継承し、現在のプロジェクトで「適用済み」になっていた。

以前のサービスアカウントキー作成禁止ポリシーが適用済みの画面

つまり、キーを止めていたのは新しい制約ではなく、以前からある組織ポリシーだ。

組織ポリシーの変更権限もない#

次に、現在のプロジェクトだけポリシーを変更できるか確認した。

しかし「ポリシーを管理」は使用できず、必要な権限がないと表示された。

組織ポリシーを変更する権限がないことを示す画面

表示された不足権限には、orgpolicy.policies.createorgpolicy.policies.deleteorgpolicy.policies.updateorgpolicy.policy.set が含まれていた。

Google Cloudも、iam.disableServiceAccountKeyCreation が有効な場合はキーを使わない認証方式を先に検討するよう案内している。

ここで組織ポリシーを解除する方向には進めず、サービスアカウントのJSONキー方式を中止した。

既存のOAuth認証をCloudflareでも使うことにする#

第8回では、ローカルのgcloud Application Default Credentials(ADC)を使ってGA4 Data APIへ接続している。

そこで、サービスアカウントを新しく使うのではなく、このOAuth認証をCloudflareのビルドでも利用する方向へ切り替えた。

ただし、そのまま認証情報を持ち込めば済む話でもない。

Google Auth Platformの「対象」を確認すると、公開ステータスは「テスト中」、ユーザーの種類は「外部」になっている。

Google Auth Platformで公開ステータスがテスト中になっている画面

Googleの仕様では、ExternalのOAuthアプリがTestingの状態で通常のOAuthスコープを要求する場合、テストユーザーの認可は7日で期限切れになる。refresh tokenも同様に期限切れになる。

Cloudflareの自動ビルドで使う認証が7日で切れる状態では運用できない。そのため、OAuthアプリ側の設定も変更することにした。

ブランディングとanalytics.readonlyを設定#

Google Auth Platformのブランディングには、ゆまラボの情報を登録した。

  • ホームページ:https://bringain.com/
  • プライバシーポリシー:https://bringain.com/privacy/
  • 承認済みドメイン:bringain.com
  • 利用規約:今回は未設定
  • ロゴ:今回は未設定

次に「データアクセス」で、GA4の読み取りに必要なスコープを追加した。

https://www.googleapis.com/auth/analytics.readonly

Google Analytics Data APIのanalytics.readonlyスコープを選択した画面

記事別PVを読むだけなので、書き込み権限は追加していない。

その後、「アプリを公開」から公開ステータスを本番環境へ変更した。

Google Auth Platformの公開ステータスを本番環境へ変更した画面

画面上にはアプリの検証が必要という案内が残った。ただ、自分で使う個人用途で利用者を広げる予定はないため、検証申請は行わずに進めた。Googleのヘルプでは、100ユーザー未満のPersonal Useアプリは検証完了が必須ではないとされている。

ADCを一度取り消して本番状態で認証し直す#

OAuthアプリを本番環境へ変更したため、第8回で作ったADCを一度削除して認証を取り直した。

まず既存のADCを取り消す。

gcloud auth application-default revoke

次に、OAuth Desktop ClientのJSONを指定し、GA4読み取り用スコープを含めてログインする。

最初は analytics.readonly だけを指定したところ、gcloudから次のエラーが返った。

Invalid value for [--scopes]:
https://www.googleapis.com/auth/cloud-platform scope is required but not requested.

--scopes を明示する場合、gcloud側で必要になる cloud-platform も含める必要があった。

最終的に使った形は下記。

gcloud auth application-default login `
  --client-id-file="C:\path\to\client_secret.json" `
  --scopes="https://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/analytics.readonly"

Google CloudのADCドキュメントでも、Google Cloud外のサービス向けスコープを追加する場合は、OAuth Client IDを --client-id-file で渡し、--scopes を指定する方法が案内されている。

認証フローを完了すると、gcloud側でも認証完了画面が表示された。

gcloud CLIのApplication Default Credentials認証が完了した画面

gcloud auth application-default print-access-token でもアクセストークンを取得できた。ただし、トークン自体は認証情報なのでスクリーンショットには使用しない。

GA4 Data APIをもう一度実行#

認証し直した状態で、第8回のスクリプトを再実行した。

node scripts/ga-pageviews.mjs

結果は正常。

GA4 Data APIから記事別pagePathとscreenPageViewsを取得したターミナル

この時点では83件取得でき、/blog/、各記事の pagePathscreenPageViews が出力された。

認証方式を作り直した後も、第8回で作ったGA4 Data API取得処理はそのまま利用できた。

ADCのJSONをCloudflare Secretへ登録#

最後に、WindowsのADCファイルをCloudflare側へ渡す。

ADCはWindowsでは次の場所へ保存される。

%APPDATA%\gcloud\application_default_credentials.json

このJSONには client_idclient_secretrefresh_token などが含まれるため、Gitには入れない。

Cloudflare Pagesの「Variables and Secrets」で、次のSecretとして登録した。

GA4_ADC_JSON

Cloudflare PagesへGA4_ADC_JSONをSecretとして登録した画面

値は暗号化され、画面上から内容を確認できない状態になっている。

Cloudflare Pagesでは、ビルド時に環境変数やSecretを利用できる。

Cloudflareで使う認証までの流れ#

第8回では、ローカルでGA4 Data APIを呼び出せるところまで進めている。

Cloudflareビルドへ認証情報を渡す準備を進める途中で、認証方式を変更することになった。

最終的な流れは次のようになった。

サービスアカウントを作成

JSONキー作成を試す

iam.disableServiceAccountKeyCreation でブロック

親ポリシーからの継承を確認

ポリシー変更権限もないことを確認

既存OAuth方式へ切り替え

OAuthアプリをTestingからProductionへ変更

analytics.readonlyを追加

ADCを再認証

GA4 Data APIで取得成功

GA4_ADC_JSONをCloudflare Secretへ登録

サービスアカウントのキー禁止を解除せず、既存のOAuth認証を再利用する形にした。

次は、この GA4_ADC_JSON と第8回のGA4取得処理をAstroのビルドへ接続し、TOPページへ人気記事3件を表示する。