Shopify Pixel integration
How the Apex Shopify Web Pixel maps Shopify customer events, dedupes event IDs, and buffers attribution.
The Apex Shopify Web Pixel runs inside Shopify's sandboxed pixel iframe. It subscribes to standard Shopify customer events, maps them to Apex events, and posts them to the Worker event pipeline.
Settings
The pixel receives settings from Shopify's webPixelCreate configuration:
| Setting | Purpose |
|---|---|
shopId | Public Apex shop ID on outgoing events. |
endpoint | Worker base URL; the pixel posts to {endpoint}/events. |
ingestShopId | Shop ID covered by the signed ingest token. |
ingestSignature | Signed pixel ingest token sent as _signature. |
enabledEvents | Shopify event names Apex should forward. |
trackPageViewed | Controls whether page_viewed is forwarded. |
queueUnattributedMs | Time to buffer events waiting for SDK assignment sync; default 3000 ms. |
maxBufferedEvents | Maximum buffered unattributed events; default 20. |
Assignment sync
The storefront SDK publishes assignment state through the Shopify analytics bridge:
Shopify.analytics.publish("drip_assignment_sync", {
visitorId: "visitor_demo_123",
sessionId: "session_demo_123",
assignments: [
{
experimentId: "22222222-2222-4222-8222-222222222222",
variationId: "33333333-3333-4333-8333-333333333333"
}
],
qaMode: false
});The pixel normalizes that payload, stores it in memory, and persists it best-effort to Shopify pixel local storage and a cookie named drip_assignment_sync_v1 for two hours.
Event mapping
| Shopify event | Apex event type | Key fields |
|---|---|---|
checkout_completed | goal | goalId: "__revenue__", funnelStep: "purchase_completed", revenue, currency, order ID, line items |
checkout_started | goal | goalId: "__checkout_started__", checkout value fields |
checkout_contact_info_submitted | goal | goalId: "__checkout_contact_info_submitted__" |
checkout_address_info_submitted | goal | goalId: "__checkout_address_info_submitted__" |
checkout_shipping_info_submitted | goal | goalId: "__checkout_shipping_info_submitted__" |
payment_info_submitted | goal | goalId: "__payment_info_submitted__" |
product_added_to_cart | goal | goalId: "__add_to_cart__", product, variant, price, quantity |
product_removed_from_cart | product_removed_from_cart | Product, variant, price, quantity |
cart_viewed | cart_viewed | Cart total and item count |
product_viewed | product_viewed | Product ID, title, type, vendor, price |
collection_viewed | collection_viewed | Collection ID and title |
search_submitted | search_submitted | Query and result count |
page_viewed | pageview | Page title and URL, only when trackPageViewed is true |
alert_displayed | alert_displayed | Message, alert type, area, target field, discount code when present |
ui_extension_errored | ui_extension_errored | Error and extension metadata |
drip_checkout_experiment_viewed | experiment_viewed | Checkout-block experiment and variation IDs |
Most mapped events add source: "shopify_pixel" in the event data before sending. The checkout-block view event uses source: "shopify_checkout_block" so checkout extension exposures stay distinguishable.
Event IDs and dedupe
The pixel creates stable IDs when Shopify or commerce data provides one:
- Shopify event
id - Shopify event
eventId - Shopify event
clientId - Mapped
orderId - Mapped
order_id - Mapped
checkoutToken
Stable IDs use this shape:
shopify_pixel:{event_type}:{source_id}If no stable source identifier exists, the pixel generates a random event ID. The Worker performs bounded event ID dedupe before publishing to Tinybird.
Unattributed buffer
When no assignment sync is available yet, the pixel builds an unattributed event with visitorId: "shopify_anonymous" and needs_attribution: true.
If buffering is enabled, the event is kept in memory until assignment data arrives or queueUnattributedMs expires. When assignments arrive, the buffer replays each queued event with needs_attribution: false and one event per active assignment. If the timer expires, the buffer drains as unattributed.
The perf_shopify_pixel_buffer_v1 assignment flag can disable buffering by setting it to false.