SvelteKitアプリにプライバシーファーストのアナリティクスを追加する
SvelteKit 2は他のフレームワークとは異なる方法でクライアントサイドナビゲーションをインターセプトします。クッキーや同意バナーなしでルート変更を追跡する正しいパターンをご紹介します。
SvelteKit 2は既存のアナリティクス統合のほとんどを静かに壊しました。SvelteKit 1で問題なく動作していた素の<script>タグは、SvelteKit 2ではハードリロード時にのみ発火し、すべてのクライアントサイドナビゲーションを見逃します。標準的な修正であるhistory.pushStateのフックも機能しません。SvelteKitはpushStateが呼び出される前にルーターレベルでナビゲーションをインターセプトするためです。Monoidトラッカーはこれを最初から正しく扱います。
通常のアプローチが失敗する理由
従来のアナリティクススクリプトは、history.pushStateとhistory.replaceStateをモンキーパッチすることでルート変更を検出します。SvelteKitのルーターは独自の内部ナビゲーションプリミティブを呼び出し、ルート遷移が既に進行中の副作用としてのみpushStateを呼び出します。パッチされたpushStateが発火する頃には、新しいルートはまだ完全にレンダリングされていない可能性があり、一部のナビゲーションタイプ(プログラム的なgoto()呼び出し、プリローディング付きの<a>クリック)では、タイミングが重複または見逃しを生み出します。
これはSvelteKit 2アプリケーションでGoogle Analytics GA4が初回ロードでのみ最初のページビューを記録するという広く報告された問題の根本原因です。
正しいアプローチ
<svelte:head>を使用してルートの+layout.svelteにMonoidトラッカースクリプトを一度追加します。
<svelte:head>
<script
async
src="https://api.monoid.website/tracker.min.js"
data-site-id="YOUR_SITE_ID"
></script>
</svelte:head>
トラッカーの組み込みDOMContentLoadedリスナーは初回ページロードで発火します。その後のクライアントサイドナビゲーションについては、トラッカーのhistory.pushStateフックがSvelteKitの内部ナビゲーションが解決した後に発火します。つまり、最初のルートを含むすべてのルートが、重複や見逃しなく正確に一度追跡されます。
確認するには、DevToolsのNetworkタブを開き、/collectへのPOSTリクエストを監視してください。ルート変更ごとに1つ表示されるはずです。
ステージングトラフィックの分離
SvelteKitプロジェクトは開発中に通常localhostで実行されます。別のサイトを登録し、そのsite_idを環境変数にバインドして、開発トラフィックが本番メトリクスを汚染しないようにします。
<script>
const siteId = import.meta.env.VITE_MONOID_SITE_ID
</script>
<svelte:head>
{#if siteId}
<script
async
src="https://api.monoid.website/tracker.min.js"
data-site-id={siteId}
></script>
{/if}
</svelte:head>
開発時は.env.localにVITE_MONOID_SITE_IDを設定し(またはトラッキングを抑制するために未設定のままにし)、本番ではデプロイ環境に設定します。{#if siteId}ブロックは、変数が設定されていないときにトラッカーが決して注入されないことを保証します。
不要なもの
クッキー同意バナーは不要。クッキーポリシーの更新も不要。navigator.cookieEnabledチェックも不要。コレクションエンドポイントは、IPアドレス、User-Agent、サーバー側のシークレット、そして現在の日付から日次の訪問者ハッシュを導出します。
visitor_hash = SHA-256(IP + UA + SALT_SECRET + YYYY-MM-DD)
ハッシュは24時間ごとにリセットされ、IPやUser-Agentを復元するために逆算することはできません。訪問者の端末には何も保存されません。これは統合がePrivacyやPECRの同意要件をトリガーしないことを意味します。同意するものが何もないからです。
ダッシュボードでの確認
デプロイ後、アナリティクスダッシュボードを開き、ライブサイト上で複数のルート間をナビゲートします。各ナビゲーションは正しいパスで新しいページビューエントリを生成するはずです。ナビゲーションに関係なくエントリが1つしか表示されない場合は、スクリプトがルートレイアウトに読み込まれていること、そして本番環境でVITE_MONOID_SITE_IDが設定されていることを確認してください。
使用するSvelteKitアダプター(Cloudflare、Vercel、Node、static)はアナリティクス収集に影響しません。トラッキングはハイドレーション後にブラウザで完全に行われるためです。