Tracking and Consent

How the app captures and attributes checkouts through the order webhook and the web pixel, why both exist, and what a shopper's consent choice changes

Guide~4 min read

Copy this guide and your current settings as a prompt for your AI agent.

Preview agent promptSee the guide, code and settings included when you copy.

Two independent paths carry a Shopify checkout to Coframe. Both exist because each covers a case the other cannot, and since September 2026 the sale is captured for every shopper, whether or not they allowed analytics.

Watch: 106s — the consent-aware change: the pixel loads for every shopper, the sale is always captured, and existing installs need no action
On this page
  1. 01Two paths to Coframe
  2. 02The visitor token
  3. 03Why both paths
  4. 04What consent changes
  5. 05Debugging which channel won
  6. 06Where in the code

01Two paths to Coframe

Path Runs where Trigger Consent
Order webhooks The Coframe app server Shopify’s checkouts/create, checkouts/update, orders/create Independent: server to server, never in the shopper’s browser
Web pixel Shopify’s pixel sandbox in the shopper’s browser checkout_started, checkout_completed Loads for every shopper; what it sends depends on the shopper’s analytics consent

The webhook forwards the order to the Coframe Conversion API with the store’s conversion API key. The pixel posts straight to Coframe ingest; the app server is not on that path. Both carry the same deduplication key, shopify:<orderId> (or shopify:<cart_token> for a checkout in progress), so one purchase that arrives twice is counted once at query time.

02The visitor token

Attribution needs the visitor’s Coframe token, the same coframe.user.token cookie the SDK uses everywhere. The app’s helper script writes it into the cart as the attribute __coframe_user_token on every page load. Shopify carries cart attributes into the checkout and into the order:

Surface Where it reads the token
Web pixel checkout.attributes.__coframe_user_token, populated by Shopify, so it works on any checkout origin including Shop Pay; cookie and local storage are narrow fallbacks
Order webhook note_attributes on the order payload (or the cart attributes on an in-progress checkout)

Two outcomes are kept separate throughout: captured means the event, SKU and revenue reached Coframe; attributed means that event also carries the visitor token and can be tied to an experiment.

03Why both paths

Dynamic checkout buttons (Buy it Now, Shop Pay, Google Pay, Apple Pay) create a fresh server-side cart that never received the cart attribute, so the order arrives without a token and the webhook alone cannot attribute it. The pixel can, because Shopify populates checkout.attributes from the visitor’s earlier cart writes regardless of which cart produced the order.

Buyer segment Webhook Pixel Outcome
Add to cart → checkout, analytics allowed Token present Loads, token present Captured and attributed, deduplicated on the order id
Add to cart → checkout, analytics declined Token present Loads, sends the sale without identity Captured and attributed by the webhook
Buy it Now / Shop Pay, analytics allowed Token usually absent Loads, token present Captured and attributed by the pixel
Buy it Now / Shop Pay, analytics declined Token usually absent Loads, sends the sale without identity Captured, not attributed

04What consent changes

The pixel declares no required privacy purposes, so Shopify runs it for every visitor. Inside the sandbox it reads the shopper’s live consent state from Shopify’s Customer Privacy API and keeps listening for changes. Every event it sends carries that state in metadata.consent.

  • Analytics allowed: the storefront helper reuses the cookie or mints a token, and the pixel sends the full event.
  • Analytics declined: the helper reuses a readable cookie but never mints one; the pixel keeps the order id (needed for deduplication), the SKUs and the revenue, and drops customer identity and behaviour. An empty token never blocks capture.

Read consent from metadata.consent, never from the token’s presence or shape. The previous behaviour, where the pixel did not load at all for a shopper who declined analytics, is why Buy it Now orders from those shoppers produced no row at all; that gap is closed.

05Debugging which channel won

Every pixel post carries metadata.user_token_source (checkout_attributes, cookie or localStorage), visible in the Network panel on the checkout page. No pixel post at all means the pixel skipped the send, and its sandbox console says why. A purchase present from the webhook but without a token is a dynamic checkout from a shopper the pixel could not identify; it counts as revenue, not as an experiment conversion.

06Where in the code

Place What to look for
sdk/app-shopify/extensions/coframe-pixel The web pixel: manifest privacy declaration, consent subscription, event posts
sdk/app-shopify/extensions/coframe-embed The theme app embed that serves the SDK and helper script
sdk/app-shopify/app Dashboard, connect flow, webhook forwarder, pixel registration
sdk/docs/shopify-app.md The full architecture document with the coverage matrix, token propagation and pixel lifecycle

Content and video lessons from Coframe documentation. Code examples are not executed on this page.

BACK TOShopify App

Documentation

Open Coframe App

Search documentation

Search all guides and references↑ ↓ Navigate · Esc Close