We’re upgrading our email infrastructure — for immediate response, email andrewjgaber@gmail.com meanwhile.
Skip to main content
Part of Digital Empire
Google Tag Manager

GTM container window.dataLayer.push in checkout.liquid

Google Tag Manager · Web Pixels API replacement · confidence: medium

Dies 2026-08-26

Paste-ready snippet
// IMPORTANT — read the honesty label before using this snippet. GTM itself
// (the container, its tag-firing rules, its own dataLayer) CANNOT run inside
// the Web Pixels sandbox: pixels execute in an isolated Web Worker with no
// DOM access, so there is no window.dataLayer to push to and no way to load
// the GTM container script. There is no 1:1 "GTM replacement" snippet.
//
// The real fix is per-tag: identify every tag GTM was firing off the
// checkout.liquid dataLayer.push('purchase') trigger (GA4, Google Ads,
// Meta, affiliate pixels, etc.) and re-implement EACH ONE as its own
// Web Pixels analytics.subscribe() call — see this library's other
// per-network templates (ga4-gtag-purchase-checkout-liquid,
// meta-fbq-checkout-liquid, etc.). This template covers the single most
// common case: GTM was configured to fire a GA4 purchase tag on that push.
analytics.subscribe('checkout_completed', (event) => {
  const { checkout } = event.data;
  if (!checkout || !checkout.totalPrice) return;

  fetch(`https://www.google-analytics.com/mp/collect?measurement_id=MEASUREMENT_ID&api_secret=API_SECRET`, {
    method: 'POST',
    keepalive: true,
    body: JSON.stringify({
      client_id: event.clientId,
      events: [{
        name: 'purchase',
        params: {
          transaction_id: checkout.order ? checkout.order.id : checkout.token,
          value: checkout.totalPrice.amount,
          currency: checkout.totalPrice.currencyCode,
          items: checkout.lineItems.map((item) => ({
            item_id: item.variant && item.variant.id,
            item_name: item.title,
            quantity: item.quantity,
          })),
        },
      }],
    }),
  });
});

Legacy pattern detected via: dataLayer\.push\(\s*\{[\s\S]{0,200}['"]event['"]\s*:\s*['"]purchase['"]

What this does NOT cover

What this does NOT cover: any custom GTM variable/trigger logic beyond the standard purchase push (e.g. conditional firing rules) — those require manual review, not a template.

Test-event verification checklist

  • Merchant has audited EVERY tag inside their GTM container that was triggered off the checkout dataLayer.push — this snippet only re-implements the GA4 purchase tag, the most common single tag; other tags (Meta, Ads, affiliate) need their own subscription per this library.
  • Fires once per completed order, matching the fields the old GTM-fired GA4 tag sent (transaction_id, value, currency, items).
  • GTM container tag itself has been REMOVED from checkout.liquid / Additional Scripts, not left running — a still-present dead GTM snippet is inert after Aug 26 but should be deleted for cleanliness, not relied on.
  • Verify live against the platform's own test-event tool: https://developers.google.com/analytics/devguides/collection/protocol/ga4/validating-events

Related paste-ready snippets

Google Analytics / Ads / GTM family · GA4, Google Ads conversion, GTM dataLayer, and the legacy Universal Analytics enhanced-ecommerce path.