Appearance
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.
| Event | When it fires | Payload |
|---|---|---|
savelayer:item_saved | Item was saved successfully | entityGid, entityType, context, listHandle |
savelayer:item_removed | Item was removed successfully | Same as saved |
savelayer:item_toggled | Toggle completed | Same fields plus saved (boolean; true when the item is active) |
savelayer:list_viewed | List was fetched successfully | context, 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.