Shopify Customer Events and Custom Pixels: Connect GTM to Checkout
By Alessandro Colarossi, Founder, Triangle Digital · Published · 9 min read
Short answer
Shopify Customer Events is Shopify's pixel framework (Settings → Customer events). A custom pixel is a script you add there that subscribes to Shopify's standard events, such as product_added_to_cart or checkout_completed. To use it with Google Tag Manager, the pixel loads your GTM container and pushes each event into dataLayer in GA4 ecommerce format. It is the supported way to get checkout and purchase data into GTM, because your theme code does not run in checkout.
What are Shopify Customer Events?
Customer Events is the part of the Shopify admin where you manage tracking pixels. Shopify publishes a set of standard events (page views, product views, cart actions, each checkout step) and delivers them to every connected pixel. There are two kinds of pixel:
- App pixels, installed by apps such as the Google & YouTube channel or a Meta app.
- Custom pixels, where you paste your own JavaScript. This is what you use to run Google Tag Manager yourself.
Customer events are available on all Shopify plans. They cover the storefront and, importantly, checkout and the thank-you page, which your theme code cannot reach.
How custom pixels run: the sandbox
Custom pixels execute in an isolated sandbox rather than directly on your page. Practical consequences:
- The pixel cannot read your theme's DOM or its
window.dataLayer. It has its ownwindow. - To use GTM there, the pixel loads its own GTM container instance and pushes events to its own
dataLayer. - You get events through
analytics.subscribe(...), not by listening to clicks on page elements. - Tags that depend on the page DOM (scroll depth, click triggers on theme elements) will not work from inside the pixel. Use the standard events instead.
Shopify events mapped to GA4 events
Each Shopify standard event corresponds to a GA4 ecommerce event. This mapping is the core of any Shopify to GTM integration:
| Shopify event | GA4 event | Notes |
|---|---|---|
page_viewed | page_view | Fires on storefront and checkout pages. |
collection_viewed | view_item_list | Collection page. |
product_viewed | view_item | Product page. |
search_submitted | search | Site search. |
product_added_to_cart | add_to_cart | Payload is a cartLine. |
product_removed_from_cart | remove_from_cart | Payload is a cartLine. |
cart_viewed | view_cart | Cart page or drawer. |
checkout_started | begin_checkout | Payload is a checkout object. |
checkout_shipping_info_submitted | add_shipping_info | Shipping step. |
payment_info_submitted | add_payment_info | Payment step. |
checkout_completed | purchase | Thank-you page. Contains the order. |
If you also have a theme data layer (see the Shopify data layer guide), pick one source per event. Sending page_view or view_item from both the theme and the pixel duplicates them.
Example: a custom pixel that feeds Google Tag Manager
This is a trimmed, illustrative example. The structure is the important part: load GTM, define a push helper, then subscribe to events and map payloads to GA4 format. Shopify's event payloads are documented in the Web Pixels API reference, and field names can evolve, so check them against the current reference.
// 1. Load Google Tag Manager inside the sandboxed pixel
window.dataLayer = window.dataLayer || [];
(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':new Date().getTime(),event:'gtm.js'});
var f=d.getElementsByTagName(s)[0],j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';
j.async=true;j.src='https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-XXXXXXX');
// 2. Helper: clear the previous ecommerce object, then push
function push(event, ecommerce) {
window.dataLayer.push({ ecommerce: null });
window.dataLayer.push({ event: event, ecommerce: ecommerce });
}
const lineToItem = (line) => ({
item_id: line.merchandise.sku || line.merchandise.id,
item_name: line.merchandise.product.title,
item_variant: line.merchandise.title,
item_brand: line.merchandise.product.vendor,
price: Number(line.merchandise.price.amount),
quantity: line.quantity,
});
// 3. Subscribe to Shopify events and map them to GA4 ecommerce events
analytics.subscribe('product_added_to_cart', (event) => {
const line = event.data.cartLine;
push('add_to_cart', {
currency: line.merchandise.price.currencyCode,
value: Number(line.merchandise.price.amount) * line.quantity,
items: [lineToItem(line)],
});
});
analytics.subscribe('checkout_completed', (event) => {
const c = event.data.checkout;
push('purchase', {
transaction_id: String((c.order && c.order.id) || c.token),
currency: c.currencyCode,
value: Number(c.subtotalPrice.amount),
tax: Number(c.totalTax ? c.totalTax.amount : 0),
shipping: Number(c.shippingLine ? c.shippingLine.price.amount : 0),
items: c.lineItems.map((li) => ({
item_id: li.variant.sku || li.variant.id,
item_name: li.title,
item_variant: li.variant.title,
price: Number(li.variant.price.amount),
quantity: li.quantity,
})),
});
});Replace GTM-XXXXXXX with your container ID, add the remaining events from the table above, then click Save and Connect. A saved but unconnected pixel never runs.
Decide what “value” means, then keep it consistent
GA4 defines the purchase value as the sum of item price times quantity, with tax and shipping sent as separate parameters. The example above uses the order subtotal for value. Whichever definition you choose (subtotal, or total including shipping and tax), use the same one in GA4, Google Ads and every other platform, or your numbers will never reconcile.
Customer privacy settings on the pixel
Each custom pixel has Customer privacy settings: whether it requires marketing, analytics or preferences consent before it runs, and whether it counts as a sale of data. If you use Shopify's consent banner or a compatible consent platform, Shopify respects those settings. If you configure Google Consent Mode inside GTM, make sure the two layers agree. The Consent Mode v2 guide covers this.
Tags and triggers on the GTM side
- Create a Custom Event trigger for each event name you push (
add_to_cart,begin_checkout,purchase, and so on). - Create GA4 Event tags using Send Ecommerce data → Data Layer. See the GA4 ecommerce guide.
- Add Google Ads and other platform tags to the same triggers. The multi-platform guide shows how.
- Test with a real order. See the debugging guide.
A tested pixel instead of a blank editor
Writing and maintaining this pixel is the fiddly part of Shopify tracking. The Shopify DIY Tagging Packs include a tested customer-event-shopify-pixel.js with every standard event mapped, plus the GTM container that consumes it. You paste the file in, replace the container ID, and connect it.
Frequently asked questions
Can I use Google Tag Manager in a Shopify custom pixel?
Yes. Load your GTM container snippet at the top of the custom pixel, then push Shopify's events into dataLayer. GTM runs inside the pixel's sandbox, separate from any GTM container in your theme.
Why can't my custom pixel read the page or window.dataLayer from my theme?
Custom pixels run in an isolated sandbox for security and performance. They have their own window and no access to your theme's DOM, so they rely on the events Shopify delivers through analytics.subscribe.
What is the difference between Save and Connect on a custom pixel?
Save stores your code. Connect activates the pixel on your store. Until it is connected, it will not receive any events.
Do Customer Events work on every Shopify plan?
Yes. Customer events and custom pixels are available on all Shopify plans.
Should the purchase event come from the theme or the pixel?
From the pixel. The thank-you page is part of checkout, which your theme code does not run on, so checkout_completed is the reliable source for the purchase event.
