Skip to content

Customer events and Web Pixels

SaveLayer publishes custom customer events into Shopify’s pipeline so merchants can subscribe with Custom Web Pixels or app web pixels. Published data appears on the event object as customData for subscribers (see Emitting data).

Events are emitted from the Online Store after successful app proxy responses (Shopify.analytics.publish on window) and from the headless SDK when that API is available. Standard Shopify events (for example product_viewed) are unchanged.

Event reference

Custom event names are prefixed with savelayer: to avoid collisions with standard events.

EventWhen it firesPayload
savelayer:item_savedItem was saved successfullyentityGid, entityType, context, listHandle
savelayer:item_removedItem was removed successfullySame as saved
savelayer:item_toggledToggle completedSame fields plus saved (boolean; true when the item is active)
savelayer:list_viewedList was fetched successfullycontext, itemCount (number of items in that response page, not the full list)

context and listHandle

The public API identifies a list with context (for example wishlist or favorites). Pixel payloads include both context and listHandle; today the theme embed and SDK set listHandle to the same string as context. That value is the logical list key, not necessarily the canonical Shopify save_list metaobject handle.

Subscribing in a Custom Pixel

In Settings → Customer events → Custom pixel, use the Web Pixels Standard API. Custom pixel code runs in a sandbox; analytics.subscribe receives SaveLayer payloads under customData.

javascript
analytics.subscribe("savelayer:item_saved", (event) => {
  console.log(event.name, event.customData);
});

analytics.subscribe("savelayer:item_toggled", (event) => {
  console.log("toggled", event.customData?.saved, event.customData);
});

analytics.subscribe("savelayer:list_viewed", (event) => {
  console.log("list items in page", event.customData?.itemCount);
});

Example: forward to an analytics endpoint

Replace the URL with your collector. Respect merchant consent and privacy policies.

javascript
analytics.subscribe("savelayer:item_saved", (event) => {
  fetch("https://example.com/collect/savelayer", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      shop: init.data?.shop?.myshopifyDomain,
      event: event.name,
      payload: event.customData,
      timestamp: event.timestamp,
    }),
  }).catch(() => {});
});

Payload shape matches the Zod schemas in @savelayer/contracts (pixel-events module), which the SaveLayer SDK uses before publishing.

App web pixels

For an app web pixel, register with @shopify/web-pixels-extension and subscribe to the same event names:

javascript
import { register } from "@shopify/web-pixels-extension";

register(({ analytics }) => {
  analytics.subscribe("savelayer:item_saved", (event) => {
    console.log(event.customData);
  });
});

Headless SDK

SaveLayerSdk calls window.Shopify.analytics.publish when present (for example in some storefront contexts). In SSR or non-Shopify browsers the call is skipped; internal SaveLayerSdk.on / emit still run for your app code.

Customer Account UI extensions (future)

When using SaveLayer from Customer Account or Checkout UI extensions, use the extension analytics.publish API (checkout, customer account) with the same event names and payload shapes—subscribers in Web Pixels see them the same way as Online Store–published events.