Shopify GTM Custom Pixel Generator
Push a clean, GA4-style data layer from Shopify's checkout events for Google Tag Manager to read.
Your details
Paste into Settings > Customer events > Add custom pixel
// Pushes a clean GA4-style data layer from Shopify's Web Pixels API, for Google Tag Manager.
// Paste into Settings > Customer events > Add custom pixel, save, then click Connect.
window.dataLayer = window.dataLayer || [];
const plainId = (id) => (id == null ? undefined : String(id).split('/').pop());
const money = (m) => (m && m.amount != null ? Number(m.amount) : 0);
const round = (x) => Math.round(x * 100) / 100;
function itemOf(variant, quantity) {
variant = variant || {};
const product = variant.product || {};
const variantTitle = variant.untranslatedTitle || variant.title;
return {
id: variant.sku || plainId(variant.id),
name: product.untranslatedTitle || product.title || variant.title,
variant: variantTitle && variantTitle !== 'Default Title' ? variantTitle : undefined,
price: money(variant.price),
quantity: quantity || 1,
};
}
function checkoutItems(checkout) {
return (checkout.lineItems || []).map((line) => {
const quantity = line.quantity || 1;
const unit = money(line.variant && line.variant.price);
const allocated = (line.discountAllocations || []).reduce((sum, d) => sum + money(d.amount), 0);
const price = round(Math.max(0, unit * quantity - allocated) / quantity);
return Object.assign(itemOf(line.variant, quantity), { price });
});
}
const itemsValue = (items) => round(items.reduce((sum, item) => sum + item.price * item.quantity, 0));
/* ---------- Events ---------- */
analytics.subscribe('product_viewed', (event) => {
const variant = event.data.productVariant;
const payload = { event: 'view_item', ecommerce: { currency: variant.price.currencyCode, value: money(variant.price), items: [itemOf(variant, 1)] } };
window.dataLayer.push({ ecommerce: null });
window.dataLayer.push(payload);
});
analytics.subscribe('product_added_to_cart', (event) => {
const line = event.data.cartLine;
if (!line) return;
const payload = { event: 'add_to_cart', ecommerce: { currency: line.cost.totalAmount.currencyCode, value: money(line.cost.totalAmount), items: [itemOf(line.merchandise, line.quantity)] } };
window.dataLayer.push({ ecommerce: null });
window.dataLayer.push(payload);
});
analytics.subscribe('checkout_started', (event) => {
const checkout = event.data.checkout;
const items = checkoutItems(checkout);
const payload = { event: 'begin_checkout', ecommerce: { currency: checkout.currencyCode, value: itemsValue(items), items } };
window.dataLayer.push({ ecommerce: null });
window.dataLayer.push(payload);
});
analytics.subscribe('checkout_completed', (event) => {
const checkout = event.data.checkout;
const order = checkout.order || {};
const items = checkoutItems(checkout);
const payload = {
event: 'purchase',
ecommerce: {
transaction_id: plainId(order.id) || checkout.token,
currency: checkout.currencyCode,
value: itemsValue(items),
tax: money(checkout.totalTax),
shipping: money(checkout.shippingLine && checkout.shippingLine.price),
coupon: (checkout.discountApplications || []).map((d) => d.title).filter(Boolean).join(',') || undefined,
items,
},
};
window.dataLayer.push({ ecommerce: null });
window.dataLayer.push(payload);
});
To add it: Shopify admin > Settings > Customer events > Add custom pixel. Name it "GTM Data Layer", paste the code, Save, then click Connect. Shopify only runs custom pixels after the shopper accepts Marketing/Analytics where consent is required; check that under Customer privacy > Permission.
Wire it up in GTM: 1. In GTM: Variables > New > Data Layer Variable, one each for ecommerce.value, ecommerce.currency, ecommerce.items, ecommerce.transaction_id (and any others you need). 2. In GTM: Triggers > New > Custom Event, one per event name used above (view_item, add_to_cart, begin_checkout, purchase). 3. In GTM: Tags > your ad or analytics tag > fire on the matching trigger, and map the fields to the variables from step 1. 4. Preview mode in GTM won't see this pixel directly (custom pixels run in a separate sandbox). Use GTM's own debug console after publishing, or turn on "Log each push" above and check the storefront's browser console.
This isn't an importable GTM container file: Shopify's custom pixel sandbox can't run Google Tag Manager itself, so there's nothing to "install" GTM into here. This script pushes plain objects to window.dataLayer; GTM (loaded normally in your theme, or through the Google & YouTube app) reads them the same way it reads any other data layer push.
Why this needs a custom pixel
Shopify's checkout runs in a locked-down environment: apps and theme code can't inject scripts into checkout pages directly. Instead, Shopify runs custom pixels in a separate sandbox that subscribes to standard events (product_viewed, checkout_completed, and so on) through the Web Pixels API.
This generator turns those events into the data layer shape Google's own GTM ecommerce guide recommends: an event name plus an ecommerce object with currency, value and items, cleared with ecommerce: null before each push so old values don't leak into the next event.
Wiring it up in GTM
- 01
Install the pixel
Shopify admin: Settings > Customer events > Add custom pixel. Paste the generated code, save, then Connect.
- 02
Add Data Layer Variables in GTM
One each for ecommerce.value, ecommerce.currency, ecommerce.items, ecommerce.transaction_id.
- 03
Add Custom Event triggers
One per event name used: view_item, add_to_cart, begin_checkout, purchase.
- 04
Point your tags at the triggers
Your ad platform or analytics tags fire on the matching trigger and read the variables from step 2.
GTM's own Preview mode can't see inside the pixel sandbox. Turn on the debug option in this tool to log every push to the storefront's browser console while you test.
Questions people ask
Does this replace Google Tag Manager itself?
No. GTM still runs normally in your theme or through the Google & YouTube app. This pixel only pushes checkout and product event data to window.dataLayer for GTM to read.
Can I get an importable GTM container file?
Not from this tool: the custom pixel sandbox can't run GTM, so there's nothing to import a container into. Set up the triggers and variables directly in GTM using the steps in the guide; it's a one-time, few-minute setup.
Will this double-count if I already have GA4 tracking?
It can, if another pixel or theme script already sends the same GA4 events. Keep only one source of ecommerce events per platform.
Does it work with Shopify Markets / multiple currencies?
Yes. Currency and value come from the checkout's own currencyCode and line item prices, whatever currency the shopper is checking out in.
Related tools
Last reviewed 30 September 2026.
Sources: Shopify: Web Pixels API standard events · Shopify: checkout_completed event · Shopify: Pixel privacy (customerPrivacy) · Shopify: Web Pixels browser API · Shopify Help Center: Create custom pixel code · Shopify Help Center: Manage custom pixels · Google: GA4 events via Google Tag Manager
