Skip to main content

Web Pixel Extensions

Web Pixels run in a sandboxed iframe on the storefront and listen for customer-events (page_viewed, product_viewed, product_added_to_cart, checkout_started, checkout_completed). They are how analytics and marketing apps observe customer behavior without direct DOM access to the store theme.

Sandbox guarantees

The pixel iframe is loaded with sandbox="allow-scripts" only. It cannot:
  • Read or write cookies on the parent page.
  • Read or write localStorage / sessionStorage on the parent.
  • Make same-origin requests against the store.
  • Read the parent DOM.
It can make cross-origin requests to your analytics service. Event delivery is via postMessage from the parent storefront to the pixel iframe — your pixel subscribes to a stable event API documented below.

Manifest

Register a Web Pixel in your extensions/ directory:
extensions/<domainSlug>/<app-handle>/web-pixels/<pixel-handle>.js
with a sibling JSON manifest:
{
  "type": "web_pixel",
  "handle": "my-pixel",
  "settings": [
    { "key": "accountId", "type": "single_line_text_field", "label": "Account ID" }
  ]
}
settings follows the same schema as theme blocks — merchants configure your pixel from the apps admin and the values are passed to your pixel’s init() as the second argument.

Pixel runtime API

Your pixel module exports a default function:
export default function ({ analytics, settings, browser }) {
  analytics.subscribe('page_viewed', (event) => {
    sendBeacon(settings.accountId, event);
  });

  analytics.subscribe('product_added_to_cart', (event) => {
    sendBeacon(settings.accountId, event);
  });
}
Where:
ArgumentTypeDescription
analytics{ subscribe(eventName, cb): void }The event bus.
settingsRecord<string, string>Merchant-configured values from the manifest.
browser{ cookie, localStorage, sessionStorage }Sandboxed proxies — these are no-ops on the storefront and only persist inside the pixel iframe.

Event catalogue

Event nameFired byPayload includes
page_viewedInline pixel loader on every storefront page(empty payload)
product_viewedServer render of a product pageproduct, variant
collection_viewedServer render of a collection pagecollection
search_viewedServer render of search resultssearch (query + count)
cart_viewedServer render of the cart pagecart
product_added_to_cartStorefront add-to-cart actionline, cart
cart_updatedAny cart mutation (add / remove / update / clear)cart
checkout_started/checkout page rendercart, customer?
checkout_completed/checkout/success after order placedorder, cart
Payloads use the stable customer-event shapes documented above, so a pixel can subscribe to event names and read the listed payload fields without further translation.

Installation

Register the pixel via POST /api/apps/install-extensions with your app’s full manifest. The install handler deploys the pixel JS + manifest and the storefront’s pixel loader picks it up on the next page load. Uninstall removes the pixel directory and the storefront stops sending events to it on the next render.

Best practices

  • Subscribe inside init, not at module top-level. Module top-level runs once when the pixel is loaded; subscribing inside the default export gives you access to the merchant’s settings.
  • Use navigator.sendBeacon over fetch. The pixel iframe may be unloaded during navigation — sendBeacon survives.
  • Don’t expect cookies to persist between visits. The pixel iframe has its own storage scope.