Skip to main content

Command Palette

Search for a command to run...

Installing GTM on Shopify in 2026 — Complete Guide

Updated
4 min read
Installing GTM on Shopify in 2026 — Complete Guide

Shopify has moved away from direct theme code injection for tracking. The Customer Events system (via Web Pixels API) is now the standard approach.

Why this matters:

  • Shopify's checkout is sandboxed — you can't inject arbitrary scripts into checkout pages on non-Plus stores

  • Custom Pixels run in a sandbox iframe, which affects how GTM behaves

  • Direct theme injection still works for non-checkout pages, but you'll have gaps in conversion tracking


2. Setup — Two-Part Installation

Part A: Theme Code (Head & Body snippets)

This covers all pages except checkout.

Step 1: Go to Shopify Admin → Online Store → Themes → Edit Code

Step 2: Open theme.liquid

Step 3: Paste this right after the opening <head> tag:

<!-- Google Tag Manager -->
<script>(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');</script>
<!-- End Google Tag Manager -->

Step 4: Paste this right after the opening <body> tag:

<!-- Google Tag Manager (noscript) -->
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-XXXXXXX"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<!-- End Google Tag Manager (noscript) -->

Part B: Custom Pixel (for Checkout & Post-Purchase Tracking)

This is critical — without this, you lose conversion/purchase data.

Step 1: Go to Shopify Admin → Settings → Customer events

Step 2: Click Add custom pixel

Step 3: Name it GTM Checkout Tracking

Step 4: Paste this code:

// GTM Custom Pixel for Shopify Checkout
const script = document.createElement('script');
script.src = 'https://www.googletagmanager.com/gtm.js?id=GTM-XXXXXXX';
script.async = true;
document.head.appendChild(script);

window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
  'gtm.start': new Date().getTime(),
  event: 'gtm.js'
});

// Subscribe to Shopify standard events
analytics.subscribe('page_viewed', (event) => {
  window.dataLayer.push({
    event: 'page_view',
    page_location: event.context.document.location.href,
    page_title: event.context.document.title
  });
});

analytics.subscribe('product_viewed', (event) => {
  window.dataLayer.push({
    event: 'view_item',
    ecommerce: {
      items: [{
        item_id: event.data.productVariant?.id,
        item_name: event.data.productVariant?.title,
        price: event.data.productVariant?.price?.amount,
        currency: event.data.productVariant?.price?.currencyCode
      }]
    }
  });
});

analytics.subscribe('cart_viewed', (event) => {
  window.dataLayer.push({
    event: 'view_cart',
    ecommerce: {
      items: event.data.cart?.lines?.map(line => ({
        item_id: line.merchandise?.id,
        item_name: line.merchandise?.title,
        price: line.merchandise?.price?.amount,
        quantity: line.quantity
      }))
    }
  });
});

analytics.subscribe('product_added_to_cart', (event) => {
  window.dataLayer.push({
    event: 'add_to_cart',
    ecommerce: {
      items: [{
        item_id: event.data.cartLine?.merchandise?.id,
        item_name: event.data.cartLine?.merchandise?.title,
        price: event.data.cartLine?.merchandise?.price?.amount,
        quantity: event.data.cartLine?.quantity
      }]
    }
  });
});

analytics.subscribe('checkout_started', (event) => {
  window.dataLayer.push({
    event: 'begin_checkout',
    ecommerce: {
      value: event.data.checkout?.totalPrice?.amount,
      currency: event.data.checkout?.currencyCode,
      items: event.data.checkout?.lineItems?.map(item => ({
        item_id: item.variant?.id,
        item_name: item.title,
        price: item.variant?.price?.amount,
        quantity: item.quantity
      }))
    }
  });
});

analytics.subscribe('payment_info_submitted', (event) => {
  window.dataLayer.push({
    event: 'add_payment_info',
    ecommerce: {
      value: event.data.checkout?.totalPrice?.amount,
      currency: event.data.checkout?.currencyCode
    }
  });
});

analytics.subscribe('checkout_completed', (event) => {
  window.dataLayer.push({
    event: 'purchase',
    ecommerce: {
      transaction_id: event.data.checkout?.order?.id,
      value: event.data.checkout?.totalPrice?.amount,
      tax: event.data.checkout?.totalTax?.amount,
      shipping: event.data.checkout?.shippingLine?.price?.amount,
      currency: event.data.checkout?.currencyCode,
      items: event.data.checkout?.lineItems?.map(item => ({
        item_id: item.variant?.id,
        item_name: item.title,
        price: item.variant?.price?.amount,
        quantity: item.quantity
      }))
    }
  });
});

Step 5: Set Customer data sharing to "Not required" (or adjust based on your consent needs)

Step 6: Click Save → then Connect


3. Important Caveats

Sandbox Limitations

Custom Pixels run in a sandboxed iframe, which means:

  • Cookies set by GTM tags inside the pixel won't share with the main page

  • Facebook Pixel, Google Ads, GA4 — these work fine via GTM in the sandbox for event tracking

  • Session stitching between browse → checkout can be tricky — use Shopify's built-in integrations for Facebook/Google where possible as a backup

For your clients in Taiwan/Asia, if GDPR-style compliance isn't required, this is simpler. But if needed:

  • Implement Google Consent Mode v2 in your GTM container

  • Use the pixel's permission settings to control when it fires

Server-Side GTM (Advanced)

For clients like ALUXE or JOYCOLORi where data accuracy is critical:

  • Consider setting up server-side GTM (sGTM) as a proxy

  • This bypasses ad blocker issues and improves data quality

  • Runs on Google Cloud or a custom domain endpoint


4. Testing Checklist

  1. GTM Preview Mode — Use GTM's debug/preview to verify tags fire on browsing pages

  2. Place a test order — Verify purchase event fires with correct transaction_id, value, and items

  3. GA4 DebugView — Check real-time events in GA4

  4. Facebook Events Manager — If running Meta Pixel via GTM, verify events in Test Events

  5. Check for duplicates — Make sure you're not double-firing if Shopify's native Google/Meta integrations are also active


5. Common Pitfalls

IssueSolution
Purchase event not firingMake sure custom pixel is Connected (not just saved)
Duplicate transactionsDisable Shopify's native GA4 integration if using GTM for GA4
GTM tags blocked by ad blockersConsider server-side GTM
Cookie/session mismatch between site and checkoutUse Shopify's first-party integrations as backup for key conversions
dataLayer events not appearing in GTM PreviewPreview mode doesn't work inside the sandbox — test with real events

Quick Summary

For your Shopify clients, the two-part approach (theme.liquid + Custom Pixel) gives you the best coverage. For high-value e-commerce clients, layer in server-side GTM for maximum data accuracy. Always test with a real order before going live.

Need me to help configure specific GTM tags (GA4, Meta, Google Ads conversions) inside the container as well?

More from this blog

D

DTC Insider™ | Shopify Expert Tenten

58 posts

Partner with Tenten, a top-tier Shopify Plus agency Taiwan, to unlock the full potential of your B2B, DTC business. Benefit from our Shopify experts, insights, and tailored solutions