Shopifyの「カスタムピクセル(Custom Pixel)」は、Customer Eventsという新しい計測基盤に追加する、Shopify公式のイベント購読コードです。2026年8月26日のcheckout.liquid / Additional Scripts廃止以降、非Plusストアでもアフィリエイト計測のクライアント側実装はこのカスタムピクセルが主要経路になります。

この記事では、Shopifyカスタムピクセルでアフィリエイト計測をどう組むかを、Web Pixel APIの仕組み・実装できる範囲・サンドボックス制約・checkout_completedイベントの取得・App Pixelとの違い・実装の落とし穴まで整理します。 ASP連携や自社アフィリエイトをShopifyで動かそうとしている方、UpPromoteなどアプリを使いつつ裏で独自計測も仕込みたい方が対象です。

結論サマリー

  • カスタムピクセルは「カスタムJSでShopifyの標準イベント(checkout_completed等)を購読するコード」。Settings > Customer events から追加する
  • lax sandbox(iframe)内で動作。DOM操作・window.location直接アクセス・document.cookie直接読み書きは不可。Cookie関連は browser.cookie API経由
  • アフィリエイト計測では、クリック時のaffiliate ID保存は「ストアフロント(テーマ)側」、コンバージョン時の計測は「カスタムピクセル側」に分離する設計が現実解
  • App Pixelとの違い: アプリ配布用/再利用しやすい/Consent APIで同意ステータスが制御できる/Shopify App Storeに公開可能
  • 実装の落とし穴: checkout_completedの発火漏れ、lax vs strict sandboxの挙動差、Customer Privacyでの同意拒否時の自動マスキング、Thank you pageへの移動タイミング

Shopify Pixelとは — Customer Eventsの新しい計測基盤

Webアクセス計測とピクセル計測のイメージ。Shopifyのピクセル実装が計測の入り口になる

Shopify Pixelは、正式には Web Pixels API として提供されている計測フレームワークで、2022年にShopifyが発表しました。従来 Additional Scriptscheckout.liquid、ScriptTag API に直接書いていたピクセル系のコードを、サンドボックス化された独自のコンテキストで動かす仕組みです。

カスタムピクセルには大きく2種類あります。

  • Customer Events(カスタムピクセル): ストアの管理者が Settings > Customer events から追加する。そのストアでのみ動く
  • App Pixel: アプリ開発者が Shopify CLI で作り、インストールしたストアで動く。App Storeに公開可能

この記事が対象にするのは前者、マーチャント自身が自分のストアに追加するカスタムピクセルです。

なぜPixelが新設されたのか

「ピクセルだけ」を独立させた背景には、チェックアウト画面のセキュリティとパフォーマンスの問題があります。

  • 任意JSがチェックアウトで動くリスク: 過去、Additional Scripts経由でカード情報を盗むコードを混入させる攻撃事例が世界各地で報告されていた
  • パフォーマンス劣化: 複数アプリが同時に<script>を差し込むと、チェックアウト画面の読み込みが重くなりCV率が落ちる
  • モバイル・1ページチェックアウトとの非互換: Liquid上の直書きコードは、ShopifyのUI刷新のたびに壊れる

Pixel化された世界では、計測コードはトップフレームから隔離されたサンドボックス(iframe allow-scripts allow-forms 環境または独自のWeb Worker)で動き、DOMやCookieへの直接アクセスは禁止されます。代わりに、Shopifyが提供する analytics.subscribe APIで標準化されたイベントだけを購読するモデルです。

2026年8月26日で非Plusストアの checkout.liquid・Additional Scripts・ScriptTag APIは動作停止するため、移行の全体像はShopifyチェックアウト追加スクリプト廃止への対応ガイドをあわせて参照してください。

カスタムピクセルでできること・できないこと

開発画面でコードを書いているイメージ。カスタムピクセルのJSはサンドボックス内で動く

カスタムピクセルで実装できる範囲と、できない範囲を先に明確にしておきます。ここを誤解すると実装途中で「このケースが動かない」とハマります。

できること

  • 標準イベントの購読checkout_completed, page_viewed, product_viewed, cart_viewed, product_added_to_cart, checkout_started, payment_info_submitted など約20種類)
  • 外部サーバーへのFetch/Beacon送信(ASPのポストバックURL、自社の計測エンドポイント)
  • 第三者ピクセルのロード(Google Tag Manager、Meta Pixel、各ASPのピクセル等)
  • Cookieの読み書きbrowser.cookie API経由、Shopify同意設定に準拠)
  • localStorageの読み書きbrowser.localStorage API経由)

できないこと

  • トップフレームのDOM操作(ボタンの見た目変更、モーダル表示、フォーム書き換え)
  • window.locationへの直接アクセス・遷移制御
  • document.cookieへの直接アクセスbrowser.cookie API経由のみ)
  • XMLHttpRequestの直接発行fetchは可能、sendBeaconも可能)
  • 他のPixelの結果やレスポンスを受け取って条件分岐(各Pixelは独立サンドボックス)

何が重要か

アフィリエイト計測の文脈で一番引っかかるのは、「document.cookieを直接読めない」「トップフレームでクリック時のaffiliate IDをCookieに仕込めない」という制約です。この2つを理解しないまま従来ロジックをそのままPixelに移植しようとすると、動かない箇所が大量に出ます。

アフィリエイト計測の基本設計 — affiliate IDの流れを先に決める

カスタムピクセルに入る前に、アフィリエイト計測で何を誰がいつ保持するかの全体像を決めます。これが曖昧なまま実装に入ると、同じロジックをテーマ側とPixel側に二重実装してしまったり、注文イベントにaffiliate IDが乗ってこず計測が空になったりします。

標準的な3ステップ

アフィリエイト計測は、大きく次の3ステップで構成されます。

  1. クリック時: アフィリエイター経由のリンクに ?afid=abc123 等が付与されてユーザーがストアに到達する
  2. 買い物中: afid を保存しておき、ユーザーが別ページに遷移しても失われないようにする
  3. CV時: 注文確定時に、保存しておいた afid を注文データに紐づけて計測サーバーに送る

カスタムピクセルが担当できるのは主に3番(CV時の送信)です。1〜2番(クリック時の受け取りと保存)は、サンドボックス制約のためカスタムピクセルではなくテーマ側のJSで行う必要があります。

テーマ側でやること(Pixelの外)

  • URLクエリから ?afid=xxx 等のパラメータ読み取り
  • Cookie または cart.attributes にそのIDを書き込み
  • リダイレクトなく通常のShopify体験を維持

コード例(theme.liquid または専用のJSアセット内):

// クリック時にクエリパラメータを読み取ってCart Attributesに書き込む
const params = new URLSearchParams(window.location.search);
const afid = params.get('afid');
if (afid) {
  fetch('/cart/update.js', {
    method: 'POST',
    headers: {'Content-Type': 'application/json'},
    body: JSON.stringify({attributes: {afid: afid}})
  });
  // Cookieにも保険として書いておく(30日等)
  document.cookie = `afid=${afid}; max-age=2592000; path=/; SameSite=Lax`;
}

Cart Attributesに書き込むと、その値は注文確定時に note_attributes として保持されるため、カスタムピクセル側でもWebhook側でも取り出せるという利点があります。

カスタムピクセル側でやること

  • checkout_completed イベントを購読
  • イベントペイロードの checkout.attributes から afid を取り出す
  • ASPのポストバックURLまたは自社計測エンドポイントに送信

カスタムピクセルでのイベント購読 — 最小構成のコード

それでは実際のカスタムピクセル実装を見ていきます。Shopify管理画面の Settings > Customer events > Add custom pixel で新しいPixelを作成し、以下のようなコードを貼り付けます。

// カスタムピクセルの骨格
analytics.subscribe('checkout_completed', (event) => {
  const checkout = event.data.checkout;
  const attributes = checkout.attributes || [];
  const afidAttr = attributes.find((a) => a.key === 'afid');
  const afid = afidAttr ? afidAttr.value : null;

  if (!afid) {
    return; // アフィリエイト経由でない購入はスキップ
  }

  const orderId = checkout.order?.id;
  const total = checkout.totalPrice?.amount;
  const currency = checkout.totalPrice?.currencyCode;

  // ASPのポストバックURLまたは自社計測サーバに送信
  fetch('https://example.com/affiliate/postback', {
    method: 'POST',
    headers: {'Content-Type': 'application/json'},
    body: JSON.stringify({
      afid,
      order_id: orderId,
      amount: total,
      currency,
    }),
    keepalive: true, // ページ遷移後も送信継続
  });
});

ポイント

  • analytics.subscribe の第1引数が購読イベント名
  • 第2引数のコールバックに event オブジェクトが渡され、event.data に標準化されたペイロードが入る
  • fetchkeepalive: true を指定しておくと、サンクスページから離脱しても送信が継続する
  • 同期的なsendBeaconでも同様の効果が得られる(navigator.sendBeacon(url, data)

Customer Privacy API との関係

同意ステータスによっては、イベントペイロードの個人情報フィールドが自動で落とされます(email / phone / address 等)。同意拒否ユーザーでも注文ID・金額のような匿名な数値は残るため、アフィリエイト計測としての最低限は成立します。ただしリード情報(メール)を取り扱いたい場合は同意状況の確認と代替フローが必要です。

checkout_completedイベントの取得 — ペイロード構造とよくある勘違い

ダッシュボード表示のイメージ。計測で取得したデータを後工程で集計する

アフィリエイト計測で主軸になる checkout_completed イベントのペイロード構造を整理しておきます。

主なフィールド

event.data.checkout = {
  order: { id: "gid://shopify/Order/5432109876543" },
  token: "abc...",                    // Checkout token
  totalPrice: { amount: 5480, currencyCode: "JPY" },
  subtotalPrice: { amount: 5000, currencyCode: "JPY" },
  totalTax: { amount: 480, currencyCode: "JPY" },
  shippingLine: { title: "宅急便", price: {...} },
  lineItems: [
    {
      id: "...",
      quantity: 2,
      variant: { id: "...", product: { id: "...", title: "..." } },
      finalLinePrice: { amount: 2500, currencyCode: "JPY" }
    }
  ],
  attributes: [
    { key: "afid", value: "abc123" }   // Cart Attributesで書いた値
  ],
  email: "...",                        // 同意次第でマスクされる
  phone: "...",                        // 同意次第でマスクされる
  shippingAddress: {...}
}

よくある勘違い

Q. checkout_completed は毎回発火するのか?

A. 原則として発火しますが、Shopify Bug Trackerで「一部のAccelerated Checkout(Apple Pay / Shop Pay経由)で発火しないケースがある」との報告があります。100%の信頼性が必要な場合はOrder Webhookとの二重化が推奨されます。

Q. order.id はすぐ取れるのか?

A. checkout_completed の時点で checkout.order.id は含まれますが、gid://shopify/Order/... 形式のGlobal IDで返ってくるため、note_attributes で取り扱うREST系のnumeric IDとは形式が違います。サーバー側で突き合わせる場合は形式変換が必要です。

Q. 金額は税込/税抜どちら?

A. totalPrice は税・送料込みの合計、subtotalPrice は税抜の商品合計(送料除外)です。アフィリエイト報酬の対象が「商品代金のみ」なのか「全額」なのかで、どちらを使うかを明確に定義する必要があります。

他イベントも必要なら追加で購読

アフィリエイト計測でよく使う補助イベントは以下です。

  • checkout_started — チェックアウト画面に到達した時点(アフィリエイト経由の離脱率分析に使える)
  • payment_info_submitted — 支払い情報入力完了(直前離脱の分析)
  • product_viewed — 商品ページ閲覧(アフィリエイト経由のLTV分析)

購読する場合は同じ要領で analytics.subscribe('イベント名', ...) を追加します。

Shopify App Pixelとの違い

カスタムピクセルと似て非なる存在として App Pixel があります。両者の違いを整理します。

カスタムピクセル(Customer Events)

  • ストア管理者が管理画面から追加する
  • そのストアでのみ動作
  • マーチャント自身がコードを管理
  • 短期・単発の計測や自社ストア専用の実装に向く

App Pixel

  • アプリ開発者がShopify CLIで作る
  • アプリをインストールしたストアで動作
  • Shopify App Storeに公開可能
  • 複数ストアに展開する場合や、計測ロジックをSaaSとして配布する場合に使う
  • 開発にはPartner Dashboardとアプリ審査が必要

アフィリエイト計測の文脈ではどちらを使うか

  • 自社ストアのアフィリエイト計測のみ: カスタムピクセルで十分。管理画面だけで完結
  • 複数ストアに同じ計測を展開 or 計測をSaaS化したい: App Pixelが必要
  • 既存アプリ(UpPromote / Affitch 等)を使う: アプリがApp Pixelとして実装済みで、マーチャント側はApp Embedの有効化等だけで済む

UpPromoteのようなShopifyアフィリエイトアプリは、2025年の checkout.liquid 廃止に合わせてScriptTag方式からWeb Pixel方式(App Pixel)への移行を完了しています。導入・運用の実際はUpPromoteの使い方ガイドで解説しています。

実装の落とし穴

ECチェックアウト画面のイメージ。実装段階で気づきにくい落とし穴がいくつかある

カスタムピクセルで実装するときに、公式ドキュメントだけ読んでいると気づきにくい落とし穴をいくつか挙げておきます。

1. checkout_completed の発火漏れ

Apple Pay / Shop Pay / Google Pay など Accelerated Checkout経由の一部ケースで、checkout_completed が発火しないケースが報告されています。ここが欠けると「買い物は立っているのにアフィリエイト成果が出ない」状態になり、気づくのが遅れがちです。

対策として、Order Webhook(orders/paid または orders/create)を並行で購読し、Pixelで拾えた分とWebhookで拾えた分を突合する二重化構成が推奨されます。Webhookは note_attributes から afid を取り出せるため、Pixelと同じロジックでサーバー側でも動きます。

2. サンドボックスの laxstrict の違い

カスタムピクセルには実は2つのモードがあります。

  • lax(デフォルト): iframe allow-scripts allow-forms 環境。fetch, browser.cookie, browser.localStorage が使える
  • strict: 同意未取得のユーザーに対するモード。Cookieアクセス・永続化が自動で制限される

同意設定(Customer Privacy)が有効なストアでは、ユーザーの同意ステータスに応じて自動で strict が適用されることがあります。同意拒否ユーザーに対しては browser.cookie が期待通り動かないケースがあり、この際 afid の保存・読み出しが失敗します。

対策は、Cookieではなく cart.attributes をプライマリにすることです。Cart Attributesは同意ステータスに関係なく動作するため、アフィリエイト計測のIDのような「匿名な機能ID」には安全な保存先です。

3. サンクスページで完了イベントが発火するタイミング

checkout_completed は注文完了画面に遷移した直後に発火します。このタイミングで fetch を投げる場合、ユーザーがすぐにブラウザを閉じたり別ページに移動すると、リクエストがキャンセルされることがあります。

対策は以下の2つです。

  • fetch(url, { keepalive: true }) を使う
  • navigator.sendBeacon(url, data) を使う

どちらもページ離脱後も送信が継続する仕組みです。keepalive はBodyサイズに上限(約64KB)があるため、軽量なイベントにのみ使う前提です。

4. 返金・キャンセル時の扱い

checkout_completed は注文確定時のみに発火するため、後から返金・キャンセルされた場合の取り消し処理はカスタムピクセルではハンドリングできません

アフィリエイト報酬を正確に管理したい場合は、サーバー側で orders/updated Webhook を購読して、返金・キャンセル時にレコードをマイナス計上するロジックが必要です。これはPixel単独では解決できない領域のため、カスタムピクセル+Webhook の二重化が事実上の前提になります。

5. 複数のアフィリエイター経由で来たときの扱い

ユーザーが複数回別のアフィリエイトリンクを踏んで来訪した場合、後勝ち・先勝ち・分割報酬のどれを採用するかを事前に決めておく必要があります。Shopifyの cart.attributes は後から値を上書きできる仕様のため、実装の素直さで言えば**後勝ち(Last Click)**が一番シンプルです。

ただしASPや契約によってはFirst Clickを要求される場合もあり、テーマ側の読み取りロジックで「既存の afid があれば上書きしない」処理を入れる必要があります。

まとめ

  • Shopifyカスタムピクセル = Customer Eventsに登録するJSで、標準イベント(checkout_completed 等)を購読する仕組み
  • アフィリエイト計測の全体像は「テーマ側でaffiliate ID受け取り → Cart Attributesに保存 → カスタムピクセルで注文時に送信」の分担が基本
  • サンドボックス制約document.cookie・DOM直操作・window.locationは使えない。browser.cookie API経由または cart.attributes を使う
  • checkout_completed の発火漏れ問題があるためOrder Webhookとの二重化が推奨
  • 実装コストを嫌うなら既存アプリ(UpPromote / Affitch)に任せるのが合理的。既にApp Pixel方式に移行済み

既存アプリを使う選択肢と自前実装のトレードオフは、事業規模・報酬体系の複雑さ・運用体制で変わります。ASPに乗るか自社アフィリエイトを運用するかの前段の判断も含めて、自社アフィリエイトとASPの違いや、Shopifyアフィリエイトが動かない時のチェックリストであるShopifyアフィリエイトの成果が出ない?5つの診断ポイントも参考にしてみてください。