What this means for your store
GTM on your theme does not run inside Shopify checkout - that context is sandboxed. Custom pixels use the analytics, browser, and init APIs to subscribe to checkout_completed and push the same event shape your web container expects. Theme GTM handles browse and cart; the pixel bridges checkout so purchase is not missing or duplicated.
Scenario on a real storefront
A US Shopify Plus store loads GTM on the theme for view_item and add_to_cart. Checkout lives on Shopify's extensible surface, so a custom pixel forwards purchase with the same dataLayer fields the container already maps:
// Shopify Admin → Customer events → Add custom pixel
analytics.subscribe('checkout_completed', (event) => {
const checkout = event.data.checkout;
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
event: 'purchase',
event_id: checkout.order.id,
ecommerce: {
transaction_id: checkout.order.id,
value: checkout.totalPrice.amount,
currency: checkout.currencyCode,
items: checkout.lineItems.map(/* map to GA4 items */)
}
});
});
// Theme GTM picks up the push; pixel runs where theme JS cannot
What to do next
- Map checkout_completed fields to the same item schema as theme pages - mixed schemas break GA4 product reports.
- Check customerPrivacy in the pixel before firing marketing tags; checkout consent can differ from storefront banners.
- Test with Shopify's pixel debugger plus GTM Preview on a dev store before Plus checkout go-live.
Bottom line
Custom pixels cover checkout; GTM covers the rest of the storefront. Align event names and item parameters across both so analytics sees one purchase, not two dialects.