← ブログに戻る

Astroサイトにプライバシーファーストのアナリティクスを追加する

AstroのView Transitionsは標準のアナリティクススクリプトを静かに壊します。クッキーや同意バナーなしで、すべてのルート変更を計測する正しいパターンをご紹介します。

AstroのView Transitionsは、ブラウザの完全リロードなしにページコンテンツをその場で入れ替えます。つまりDOMContentLoadedやloadに依存するアナリティクススクリプトは、最初の訪問時に一度だけ発火することになります。その後のクライアントサイドナビゲーションはすべて見えません。これは設定ミスではなく、ClientRouterの動作仕様による根本的な帰結です。

同じサイレントトラッキングの問題はSvelteKit 2やRemixにも存在しますが、各フレームワークでの修正方法は異なります。Astroでの答えはastro:page-loadライフサイクルイベントです。

通常のscriptタグが失敗する理由

<ClientRouter />が有効な場合(Astro 4ではastro:transitionsからのオプトイン、Astro 5ではデフォルト有効)、ナビゲーションはページをアンロードしません。Astroは次のページをバックグラウンドでフェッチし、DOMを入れ替え、URLを更新します。現在のJavaScriptコンテキストを破壊することなくすべてを行います。

素の<script>タグで読み込まれたトラッカースクリプトは、Astroのビルドパイプラインではバンドルされたモジュールスクリプトとして扱われます。バンドルされたモジュールスクリプトは、ページセッションごとに正確に一度だけ実行されます。トラッカーは初期化し、ランディングページのページビューを発火し、その後ユーザーがナビゲートしても二度と実行されません。

ナビゲーションごとに発火させるには、初期化ロジックをAstroのナビゲーションライフサイクルに接続する必要があります。正しいフックはastro:page-loadで、新しいページが表示され、すべてのブロッキングスクリプトが読み込まれた後に発火します。最初のロードでも、その後のすべての遷移でも発火します。

正しい統合方法

ルートレイアウト(src/layouts/Layout.astroまたは同等のもの)にトラッカースクリプトを一度追加し、astro:page-loadのリスナーをアタッチします。

---
// Layout.astro
---
<html lang="en">
  <head>
    <!-- your head content -->
  </head>
  <body>
    <slot />

    <script
      is:inline
      src="https://api.monoid.website/tracker.min.js"
      data-site-id="YOUR_SITE_ID"
      async
    ></script>
  </body>
</html>

is:inlineディレクティブは、Astroのバンドラーにこのスクリプトをそのまま残すよう指示します。これがないとAstroはスクリプトをモジュールとして処理し、重複排除し、再実行を抑制します。is:inlineがあれば、scriptタグはすべてのページのHTML出力にそのまま埋め込まれます。

View Transitionsを使用しないサイトでは、これだけで十分です。トラッカーはロード時に一度発火し、それで完了です。

View Transitionsナビゲーションの取り扱い

サイトが<ClientRouter />を使用している場合、追加の設定は不要です。ただし、その理由を正確に理解しておく価値があります。一般に語られている説明は誤りだからです。

トラッカーはastro:page-loadをはじめとするAstroのライフサイクルイベントをリッスンしていません。読み込み時にhistory.pushStateにパッチを当てます。AstroのルーターはまさにそのHistory API呼び出しを通じてURLを更新するため、パッチされた関数が遷移のたびに実行され、ページビューを送信します。このフックはAstroのイベント層をリッスンするのではなく、その下位に位置しています。

確認するには、DevToolsのNetworkタブを開き、collectでフィルターしてください。2つのページ間をナビゲートします。最初のロードを含め、ナビゲーションごとに1つのPOSTリクエストが見えるはずです。

知っておくべき注意点が1つあります。このフックはpushStateを対象としており、popstateは対象外です。ブラウザの「戻る」「進む」操作はpushStateを呼び出さずにルートを変更するため、現時点では新しいページビューにはなりません。

トラッカーは手動でページビューを送るメソッドを公開していません。グローバルが受け付けるのはカスタムイベントのみです。

<script>
  // カスタムイベントのみ — trackPageview() という呼び出しは存在しません。
  // 名前は [a-z0-9_][a-z0-9_-]{0,63} に一致する必要があります。
  window.monoid('event', 'signup_started');
</script>

環境の分離

Astroプロジェクトは通常、ローカル開発、プレビュー、本番の各環境を持ちます。環境変数でsite_idを保持し、開発時はトラッキングを抑制します。

---
const siteId = import.meta.env.PUBLIC_MONOID_SITE_ID
---

{siteId && (
  <script
    is:inline
    src="https://api.monoid.website/tracker.min.js"
    data-site-id={siteId}
    async
  ></script>
)}

本番では.envにPUBLIC_MONOID_SITE_IDを設定し、ローカルでは未設定のままにします。AstroはPUBLIC_接頭辞を持つ変数をクライアントに公開します。接頭辞のないサーバー専用変数はブラウザで実行されるコードからは見えません。

不要なもの

クッキー同意バナーは不要。CMP統合も不要。コレクションエンドポイントは、IPアドレス、User-Agent、サーバー側のシークレット、そして現在の日付から日次の訪問者ハッシュを計算します。

visitor_hash = SHA-256(IP + UA + SALT_SECRET + YYYY-MM-DD)

ハッシュは24時間ごとにリセットされます。訪問者の端末には何も保存されません。大まかなブラウザファミリーと端末タイプは、集計レポート用にリクエストのUser-Agentからサーバー側で導出されます。完全なUser-Agent文字列、ブラウザバージョン、永続識別子が保存されることはありません。

Astroサイトは多くの場合、完全に静的またはエッジレンダリングで、JavaScriptは最小限です。クッキーも同意要件もない2 KB未満のアナリティクススクリプトを追加することは、その哲学に自然になじみます。メンテナンスするnpmパッケージも、更新するSDKも、アナリティクス処理のためにGDPRの法的根拠を文書化する必要もありません。

出典

Comments

Loading comments…