Next.js、Gatsby、静的サイト向けCookie同意管理:開発者のための実装ガイド

静的サイトにおける同意管理の課題

Next.js、Gatsby、Nuxt.js のようなモダンなJavaScriptフレームワークは、Webページの構築と配信方法にパラダイムシフトをもたらしました。ページはビルド時またはサーバー側でプリレンダリングされ、その後クライアント側でハイドレーションされます。これによりCookie同意には特有の課題が生じます。すなわち、同意バナーはあらゆるトラッキングスクリプトが実行される前に準備されていなければならない一方で、ページ自体はすでにレンダリングされ、エッジでキャッシュされている可能性があるという点です。

従来のCMPは、サーバーレンダリングされたPHPや、上から下へ直線的に読み込まれるシンプルなHTMLページ向けに設計されていました。コード分割、遅延読み���み、ストリーミングSSRといった仕組みを持つフレームワークの世界では、こうした前提が崩れます。これらの環境で正しく同意を扱うには、レンダリングパイプラインを理解する必要があります。

タイミングが想像以上に重要な理由

通常のHTMLページでは、<head>内で他のスクリプトより前にCMPスクリプトを配置するのは単純です。しかし Next.js App Router や Gatsby では状況がより複雑になります。

ここでの核心原則は次の通りです。同意はコンポーネントレベルではなく、スクリプトレベルで確立されていなければならないということです。ハイドレーション後に初めてインタラクティブになるReactコンポーネントとして同意バナーをレンダリングしても、それでは遅すぎます。

Next.js App Router での統合

App Router を備えた Next.js 13+ では、スクリプトの扱い方が新しくなりました。ここでは同意統合の推奨アプローチを説明します。

ステップ1: ルートレイアウトでCMPスクリプトを読み込む

ルートの layout.tsx で、Next.js の Script コンポーネントに beforeInteractive ストラテジーを指定して使用します。これにより、ハイドレーションが始まる前に初期HTMLドキュメントへスクリプトが挿入されます。

beforeInteractive ストラテジーは極めて重要です。デフォルトの afterInteractive ストラテジーでは、ス��リプトはハイドレーション後に読み込まれるため、同意には遅すぎます。beforeInteractive を使うことで、CMPスクリプトはサーバーレンダリングされたHTMLに含まれ、ページの読み込みと同時に実行されます。

ステップ2: Googleタグの前にデフォルト同意を設定する

Google Tag Manager や gtag.js のスニペットより前に、デフォルトの同意状態を設定するインラインスクリプトを挿入します。これにより、たとえCMPバナーが表示される前にGTMが読み込まれたとしても、拒否をデフォルトとする設定が尊重されます。

このインラインスクリプトは、ルートレイアウトの <head> 内で、CMPおよびGTMスクリプトより前に配置する必要があります。Next.js では、この目的のために <head> 要素内に通常の <script> タグを記述できます。

ステップ3: ルート変更への対応

シングルページアプリケーションとしてのナビゲーションでは、CMPスクリプトは一度だけ読み込まれ、ルート変更時にページ全体のリロードは発生しません。CMPはクライアントサイドのナビゲーション��またいで持続する必要があります。FlexyConsent はこれを自動的に処理します。一度読み込まれれば、再初期化なしであらゆるルート変更にわたって有効なままです。

Next.js Pages Router での統合

Pages Router をまだ利用しているプロジェクトでは、アプローチはほぼ同じですが、ルートレイアウトの代わりに _document.tsx を使用します。カスタムDocumentクラスの <Head> コンポーネント内にCMPスクリプトを配置します。beforeInteractive ストラテジーは Pages Router でも同様に機能します。

重要な違いは、_document.tsx はサーバーでのみレンダリングされるため、ここに記述した同意ロジックは必ず初期HTMLペイロードに含まれるという点です。

Gatsby 静的サイトでの統合

Gatsby はビルド時に完全な静的HTMLを生成します。リクエスト時のサーバーサイドレンダリングは行われません。これは一部を単純化する一方で、別の点を複雑にします。

Gatsby のビルド時生成というアプローチにより、CDN上のすべてのHTMLファイルに同意スクリプトが含まれます。これは実際には理想的であり、失敗したりキャッシュを誤るサーバーロジックが存在しないという利点があります。

Nuxt.js における考慮点

Nuxt.js(Vueベース)は独自のパターンを持っています。Nuxt 3 では、useHead コンポーザブルや nuxt.config.ts の app head 設定を使って、CMPスクリプト��グローバルに追加します。Nuxt は body: false オプション(スクリプトをheadに配置)や、ノンブロッキング読み込みのための async 属性をサポートしています。

Nuxt のサーバーサイドレンダリングモードでも、同じ原則が適用されます。CMPスクリプトは、マウント後にVueコンポーネントから動的に注入されるのではなく、初期HTMLレスポンスに含まれていなければなりません。

レイアウトシフトを避ける

同意バナーは、SEOランキングに影響するCore Web Vitalsの一つであるCumulative Layout Shift(CLS)の原因として悪名高い存在です。ページがレンダリングされた後にバナーがポップインすると、コンテンツを押し下げたり、予期せずオーバーレイしたりします。

同意バナーによるCLSを最小限に抑えるための戦略:

FlexyConsent のフレームワーク非依存アプローチ

FlexyConsent はコンポーネントレベルではなくスクリプトレベルで動作することで、どのフレームワークにも、あるいはフレームワークがなくても動作するように設計されています。これが重要である理由は次の通りです。

開発者向けヒント: CMPが正しく統合されているかを確認する最も簡単なテストは、ブラウザのNetworkタブを開き、ドメインをGoogleでフィルタしてからページをリロードすることです。同意デフォルトコマンドがコンソールに表示される前に、Googleへのリクエストが発生してはなりません。もし発生している場合、CMPの���み込みが遅すぎます。

FlexyConsent の無料プランはページビュー数無制限で、Next.js、Gatsby、Nuxt、Astro、SvelteKit、Remix、プレーンHTMLで動作します。どの環境でも統合方法は同じで、適切に配置された1つのスクリプトタグだけです。

← ブログ すべて読む →