hydrogen-analytics-tracking について
Shopify Hydrogen のストアフロント向け分析トラッキングを実装・デバッグするエージェントスキルです。ブラウザーとサーバーのイベント送信、共通イベント ID による重複排除、同意管理、Oxygen のキャッシュ設定を扱います。
主な機能
- 01ブラウザーの dataLayer と GTM 追跡
- 02サーバー側イベント転送
- 03共通イベント ID による重複排除
- 04Consent Mode v2 のガイダンス
- 05CSP と Oxygen キャッシュのガイダンス
活用シーン
- 01GA4 と広告プラットフォームの追跡設定
- 02分析サービスに届かないイベントの調査
- 03ブラウザーとサーバーのコンバージョン重複排除
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ weaverse/ shopify-hydrogen-skills --skill hydrogen-analytics-trackingインストール後、Claude Code で/hydrogen-analytics-trackingを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/architecture.mdcart-attribute-stash.mdcsp-for-tracking.mdgotchas.mdgtm-meta-implementation.mdoxygen-full-page-cache.mdwebhook-forwarding-via-builder.md詳細
Hydrogen Analytics & Tracking — エージェントスキル
Shopify Hydrogen で完全なトラッキングパイプラインを構築します。クライアントの dataLayer → GTM → ブラウザピクセル、およびサーバーの
/api/track→ GA4 MP / Meta CAPI / Google Ads に対応し、共通のevent_idで両側の重複を排除します。Consent Mode v2、CSPstrict-dynamic、Oxygen のフルページキャッシュとの互換性に加え、あらゆる実装でつまずきやすい意外な落とし穴も扱います。
このスキルには、Hydrogen ストアフロントの本番環境でトラッキングを行う中で得た貴重な知見が盛り込まれています。リファレンスファイルには詳細な実装が記載されています。このトップページは全体像を示す案内図です。
このスキルを使う場面
次のような場合に必要です。
- Hydrogen で GA4 / Meta / Google Ads / TikTok のトラッキングを実装する際、標準の Hydrogen Analytics コンポーネントでは不十分な場合。
- 広告ブロッカーや ITP に対する耐性を高めるため、サーバーサイドトラッキング(Measurement Protocol、Conversions API)を追加する場合。
- 「イベント X は GTM プレビューに表示されるのに、GA4 / Meta には表示されない」問題をデバッグする場合。
- ブラウザピクセルとサーバー CAPI の間でコンバージョンの重複排除を設定する場合。
- CMS 層として Weaverse を使用する Hydrogen ストアフロントでトラッキングを設定する場合。
- 正しい
Oxygen-Cache-Controlヘッダーを設定しているのに、Oxygen のフルページキャッシュが無効化される理由を調べる場合。
page_view と Hydrogen 組み込みの <Analytics.Provider> のカートイベントを GTM 経由で GA4 に転送したいだけであれば、Shopify のドキュメントで十分です。ファネル全体が必要な場合は、こちらを参照してください。
基本的な考え方
トラッキングの 3 つのレイヤー
| レイヤー | 実行場所 | 強み | 弱み |
|---|---|---|---|
| ブラウザ(GTM → ピクセル) | dataLayer.push() → GTM タグ → GA4、Meta Pixel、Google Ads、TikTok | ユーザーコンテキストが豊富、fbp/fbc Cookie、即時のクライアントサイド ECommerce イベント | ITP、広告ブロッカー、ページ遷移時の競合 |
サーバーサイド(/api/track) | Hydrogen ワーカー → GA4 MP、Meta CAPI、Google Ads Enhanced Conversions | 広告ブロッカーの影響を受けない、クライアントのアンロード後も実行される、Webhook からもトリガー可能 | 一部のコンテキストが失われる(転送しない場合は fbp がない)、IP + UA + マッチキーが必要 |
| 制御できないベンダーの連携 | Shopify の「Google & YouTube」販売チャネルアプリ、Shopify Customer Events Pixel | Shopify のチェックアウト内で動作する(マーチャントの GTM は設定できない)、Shopify 公認 | カスタマイズに制限がある。同じベンダーを二重に設定すると、マーチャントの GTM とイベントが重複する可能性がある |
組み合わせが重要です。 完全なパイプラインでは、ストアフロントページに GTM、耐障害性と重複排除にサーバーサイド、チェックアウトページ(Shopify Plus では制限されています)にベンダーの連携機能を使用します。
二重送信と event_id による重複排除
基盤となるパターンです。トラッキング可能な各イベントで次を行います。
- クライアントで UUID の
event_idを一度だけ生成します。 - その
event_idを含めてdataLayerに送信し、GTM を経由してブラウザピクセルからevent_idを重複排除キーとしてヒットを送信します。 - 同じ
event_idを指定してnavigator.sendBeaconで/api/trackにPOSTし、サーバーから同じキーを使って GA4 MP / Meta CAPI / Google Ads に転送します。 - 各ベンダーのバックエンドが
(event_name, event_id)で重複を排除するため、カウントは 2 回ではなく 1 回になります。
function trackEvent({ event_name, custom_data, user_data }) {
const event_id = crypto.randomUUID();
// (1) Browser side
window.dataLayer.push({ event: event_name, event_id, ...custom_data });
// (2) Server side, same event_id
const payload = { event_id, event_name, custom_data, user_data, consent };
navigator.sendBeacon("/api/track", new Blob([JSON.stringify(payload)]));
return event_id;
}
なぜ fetch ではなく sendBeacon を使うのか
カートへの追加、チェックアウト開始、「今すぐ購入」は、直後にページ遷移が発生します。通常の fetch() はページのアンロード時にキャンセルされ、イベントが失われます。sendBeacon はこの用途のために設計されたブラウザー API です。リクエストはブラウザーによってキューに格納され、ページ遷移後も確実に送信されます。sendBeacon を利用できない場合は、fetch(..., {keepalive: true}) にフォールバックします。
event_id をサーバーで生成できない理由
サーバーが event_id を生成すると、ブラウザーはすでに別の ID(または ID なし)で dataLayer イベントを送信しており、後から補完する方法がありません。必ずクライアント側で生成し、同じ値を両方向に送信してください。
実験の露出(A/B テスト)
Weaverse ストアフロントの A/B テストには、決定論的なプロジェクトレベルのバリアント割り当てを行う @weaverse/experiments を使用します。露出は、ほかのすべてのイベントと同じパイプラインを通ります。
- バリアントごとに下流イベントをセグメント化します。 解決済みの割り当てを
<Analytics.Provider customData={{ experiments: { '<id>': '<variant>' } }}>に渡します。customDataはすべてのイベントにマージされるため、add_to_cart/purchaseにはすでにバリアントのタグが付いています。これにより、インプレッションだけでなくコンバージョンへの影響を測定できます。イベントごとに実験を再度添付する必要はありません。 - インプレッションイベントを発火します。 実験の
onExposeコールバックからuseAnalytics().publish('custom_experiment_viewed', { experimentId, variantId })を呼び出し、canTrack()で制御します。ほかのカスタムイベントと同様に、<CustomAnalytics>サブスクライバーでcustom_experiment_viewedを dataLayer/GA4 に橋渡しします(custom_プレフィックスが必須です。ready()を呼び出してください)。 - 重複を排除します。 露出はコンバージョンではなくインプレッションなので、通常は
event_idによる二重送信は不要です。/api/trackに転送する場合は、ストアフロントのtrackEvent()ヘルパーを再利用してください。
サーバーサイドの getExperiments() の配線は、weaverse-hydrogen スキル(Multi-Project Architecture → A/B Testing)に記載されています。
参考ファイル
最初から実装する場合は、以下を順に読んでください。デバッグ中の場合は、該当するファイルに進んでください。
| 参考資料 | 次の場合にお読みください… |
|---|---|
architecture.md | パイプライン全体を設定する場合。二重送信パターン、重複排除の契約、各ベンダーの責務、各要素の連携方法について説明しています。 |
gtm-meta-implementation.md | GTM dataLayer のプッシュ、GA4 イベントタグ、Meta CAPI フォワーダーを配線する場合。実際のコードパターンを紹介しています。 |
webhook-forwarding-via-builder.md | Weaverse ホストのストアフロントの場合: マルチテナントアプリのクライアントシークレットを漏らさずに、Shopify の Webhook をストアフロントに到達させる方法。builder の WebhookForward モデルとストアごとの署名シークレットを使用します。 |
cart-attribute-stash.md | Webhook の Cookie の欠落を橋渡しする場合: ブラウザーから Shopify の注文 Webhook に _fbp / _fbc / gclid / アフィリエイトのクリック ID を渡す方法。stash ロジックが必要な 2 つのカートエントリーパス(POST アクションと /cart/<id>:<qty> ローダー)について説明しています。 |
oxygen-full-page-cache.md | FPC の設定、Set-Cookie が FPC を無効にする理由、entry.server.tsx で除去する方法を確認する場合。 |
csp-for-tracking.md | Google/Meta/Hotjar を許可する CSP ディレクティブ、nonce と strict-dynamic の違い、GTM Custom HTML タグとインラインスクリプト違反について確認する場合。 |
gotchas.md | どの実装でも発生しやすい不具合を確認する場合。何かが動作しないときは、まずこちらを読んでください。 |
Hydrogenのトラッキング実装でよくある7つの間違い
-
add_to_cartにHydrogenのPRODUCT_ADD_TO_CART分析イベントを使う。 Hydrogenは再検証後にカートの状態を比較し、その時点でイベントを発行します。タイミングが不安定なため、イベントがGA4 DebugViewにまったく届かないこともよくあります。対処法: ボタンのonClickハンドラーからsendBeacon経由でadd_to_cartを直接発火させます(フォームの送信/ページ遷移後も送信されます)。 -
<Script waitForHydration>を使って、ハイドレーション後にGTMを読み込む。 Tag Assistantの単独スキャンでGTMが検出されなくなり、nonceベースのstrict-dynamicCSPへの移行も妨げます。対処法:<head>内でgtm.jsを通常の<script async nonce={nonce}>として読み込み、その前にインラインのgtm.startとConsent Mode v2のデフォルト拒否ブロックを配置します。 -
GA4のイベント名でイベントをプッシュしながら、GTMトリガーでは旧来のsnake_case名を設定する(またはその逆)。「Custom Event」の名称変更後に、カバーできない範囲が生じます。対処法: GTMトリガーのフィルターを、ストアフロントが現在実際にプッシュしているイベント名に合わせます。コードとGTMを同時に変更してください。
-
<Analytics.ProductView>のマウント条件にselectedVariantを使う。 統合リスティングや、ハイドレーション後にバリアントが解決される商品では、分析コンポーネントが一度もマウントされず、view_itemも発火しません。対処法: バリアントごとの安全なフォールバックを用意し、常にマウントします。 -
「同意なし」を「何も送信しない」と捉える。 Meta CAPIの緩和パターン(LDUフラグとip/ua/fbp/fbcのみを使用し、ハッシュ化されたPIIは含めない)を使うと、コンプライアンスを保ちながら最適化シグナルの多くを取り戻せます。GA4 Consent Mode v2のモデリングされたコンバージョンも同様に機能します。対処法: サーバー側のフォワーダーで、
ad_storage !== "granted"の場合はハッシュ化されたPIIを除外しつつ、data_processing_options: ["LDU"]を指定してイベントを送信します。 -
Liquidの
dataLayer.pushスニペットをHydrogenに貼り付ける。 マーチャントが既存のテーマ用スニペット({{ product.id }}、{{ collection.title }}、{{ product.price | money_without_currency }}などのLiquidタグを使用)を持ち込むことがよくあります。Hydrogenでは何も機能しません。HydrogenはReact/SSRであり、実行時にLiquidは存在しないため、中括弧は文字列としてそのまま表示されるか、エラーの原因になります。対処法: Hydrogenのデータから同じオブジェクトを再構築し、JSでプッシュします。LiquidからHydrogenへの対応関係:{{ product.id }}→product.id、{{ product.title }}→product.title、{{ product.price | money_without_currency }}→product.priceRange?.minVariantPrice?.amount(通貨記号を含まない文字列)、{{ collection.id/title }}→collection.id/title。 -
組み込みのHydrogen分析イベントで
select_item/view_item_listが発火すると期待する。 GA4のリストイベントはカートイベントには対応しません。select_itemはクリックイベントです(リスト内の商品カードをユーザーがクリックする)。商品、コレクション、インデックスをすでに持っているコレクション/PLPの商品カードのonClickから発火させます。view_item_listは表示イベントです。app/components/root/custom-analytics.tsxのCOLLECTION_VIEWEDサブスクライバーからプッシュします。GA4用にindex(リスト内の位置)を含めてください。値をプッシュできるように、コレクションクエリからid、title、handle、priceRangeが返されることを確認します。
構築する順序
新しい Hydrogen ストアフロントを一から構築する場合:
- Hydrogen の
<Analytics.Provider>をルートで接続します。<CustomAnalytics />コンポーネントでイベントを購読します。(architecture.mdを参照) - インラインの
<head>に Consent Mode v2 のデフォルト拒否ブロック、dataLayer、gtm.start マーカーを配置します。 - nonce を付けた
gtm.js外部スクリプトを、インラインブロックの後に<head>へ追加します。 - dataLayer にプッシュし、共通の
event_idを付けてsendBeacon('/api/track')を送信するtrackEvent()ヘルパーを作成します。 - ペイロードを検証し、サーバー側で PII をハッシュ化して、GA4 MP、Meta CAPI、Google Ads のフォワーダーに振り分ける
/api/trackサーバーエンドポイントを作成します。 - 注文を
event_id = "purchase_" + orderId(再試行時にも同じ値になる決定的な値)を持つpurchaseイベントにマッピングする Shopifyorders/createwebhook を作成します。 - Shopify の「Google & YouTube」販売チャネルと Customer Events Pixel を設定し、チェックアウト側のイベント(Meta Pixel イベントや、GTM からアクセスできない Shopify チェックアウト内で発火させる必要があるイベント)に対応します。
- dataLayer イベントごとに GA4 イベントタグを設定し、必要に応じて Meta Pixel、TikTok、Google Ads コンバージョンタグも追加した GTM コンテナを用意します。
script-src、connect-src、img-srcで各ベンダーのドメインを許可するよう CSP を更新します。strict-dynamicと nonce を使用します。Oxygen-Cache-Control: public, max-age=N, ...ヘッダーを使って、ルートごとに Oxygen のフルページキャッシュを有効にします。キャッシュ可能なレスポンスからSet-Cookieを削除するよう、entry.server.tsxを設定します。
スキルレベルの規約
このスキルの対象範囲で Hydrogen のトラッキング実装に取り組む場合:
- サーバーコードは
app/.server/tracking/に配置します(フォワーダー、バリデーター、ハッシュユーティリティ、監査ログ)。 - クライアントヘルパーは
app/utils/track-client.tsに配置します(trackEvent、同意リスナー、アトリビューション取得をエクスポート)。 - dataLayer ブリッジは
app/components/root/custom-analytics.tsxに配置します(Hydrogen の<Analytics.Provider>イベントを購読)。 - インラインの Consent Mode と GTM のブートストラップは、nonce を付けて
app/root.tsxの<head>に配置します。 - CSP 設定は
app/weaverse/csp.ts(Weaverse プロジェクトの場合)、またはストアフロントで CSP を設定している場所に配置します。 - ベンダーごとのフォワーダーモジュールは
app/.server/tracking/forwarders/{ga4,meta-capi,google-ads}.tsに配置します。それぞれ{forwarder, ok, skipped?, reason?}を返すことで、監査ログにイベントが破棄された理由を記録できます。
質問が単一ベンダーにとどまらない場合は、特定ベンダーのドキュメントよりも、アーキテクチャ層を扱うリファレンスドキュメントを優先してください。
最新のドキュメント
これらは、このスキルのフォルダーから実行してください。ヘルパーは隣接する
shopify-hydrogen スキルに含まれているため、パック全体をインストールしていれば
../shopify-hydrogen/scripts/ が存在します。
このスキルだけをインストールした場合、そのフォルダーは存在せず、以下のコマンドは
MODULE_NOT_FOUND で失敗します。ヘルパーを一度追加してください:
npx skills add Weaverse/shopify-hydrogen-skills --skill shopify-hydrogen
このスキルの references/ ファイルは、インストールせずに利用できるオフラインの代替資料として引き続き使用できます。
最新の公式情報を確認するには:
# Shopify Hydrogen / Oxygen
node ../shopify-hydrogen/scripts/search_shopify_docs.mjs "oxygen full-page cache"
node ../shopify-hydrogen/scripts/search_shopify_docs.mjs "consent mode"
node ../shopify-hydrogen/scripts/search_shopify_docs.mjs "analytics provider"
# Weaverse (if using Weaverse CMS)
node ../shopify-hydrogen/scripts/search_weaverse_docs.mjs "csp"
ベンダーのドキュメント(ブラウザーで開いてください。スクリプトは不要です):
- GA4 Measurement Protocol — https://developers.google.com/analytics/devguides/collection/protocol/ga4
- Meta Conversions API — https://developers.facebook.com/docs/marketing-api/conversions-api
- Google Ads Enhanced Conversions for Web — https://developers.google.com/google-ads/api/docs/conversions/enhanced-conversions-for-web
- Shopify「Customer Events」/Web Pixels — https://shopify.dev/docs/api/web-pixels-api