[Analytics Implementation](/categories/analytics-implementation) November 3, 2026

# Google Tag Manager on Shopify: set it up and verify it

How to add Google Tag Manager to Shopify in 2026: the theme, a custom pixel for checkout, Shopify events mapped to GA4, consent, and how to check the data.

![](/images/65d75b0ae8d69ef95785a5d6_david-pombar.webp)

**[David Pombar](/author/david-pombar)** Swiss army knife at Trackingplan

8 min read · 1737 words

Google Tag Manager on Shopify now lives in two places. The theme loads it on the storefront, where it can see the page. A custom pixel loads it in checkout, inside a sandbox where it can only hear the events Shopify publishes. Most broken Shopify tracking comes from treating those two as one.

This guide covers both: how to install each, how to map Shopify’s events to GA4, where consent goes wrong, and how to check that what reaches GA4 and your ad platforms is what your store actually did.

![A miniature shopping cart on a desk next to an open laptop](/images/google-tag-manager-shopify-online-store.jpg)

Online shopping, measured in two places at once. Image: Shixart1985, Wikimedia Commons, CC BY 2.0

## The short answer

-   **Storefront:** paste the GTM container snippet into `theme.liquid`. Tags there can read the page: clicks, forms, scroll.
-   **Checkout and purchase:** add GTM to a custom pixel under Settings → Customer events, subscribe to Shopify’s standard events, and push them to `window.dataLayer`. Since August 26, 2026, this is the only way for your own tags to reach the Thank you and Order status pages ([Shopify](https://help.shopify.com/en/manual/checkout-settings/customize-checkout-configurations/upgrade-thank-you-order-status)).
-   **Then check it on real traffic,** not only in Preview. On Shopify, the hits you can’t see in Preview are the ones that pay for your campaigns.

![One GTM container runs in two places on Shopify: on the storefront page through theme.liquid, where it sees clicks, forms, and scroll but not checkout, and in a custom pixel sandbox, where it hears Shopify’s events through checkout and purchase. What matters is what arrives at GA4, Google Ads, Meta, and TikTok.](/images/google-tag-manager-shopify-two-places.webp)

One GTM container runs in two places on Shopify: on the storefront page through theme.liquid, where it sees clicks, forms, and scroll but not checkout, and in a custom pixel sandbox, where it hears Shopify’s events through checkout and purchase. What matters is what arrives at GA4, Google Ads, Meta, and TikTok.

## Your options, side by side

|     | GTM in the theme | GTM in a custom pixel | Google & YouTube app |
| --- | --- | --- | --- |
| Where it runs | Storefront pages | Storefront, checkout, Thank you, and Order status pages | Shopify-managed |
| What it can see | The page and its DOM | Only the events Shopify publishes | Standard Google events |
| Checkout and purchase | No  | Yes | Yes |
| Your own tags and triggers | Yes | Yes, inside the sandbox’s limits | No  |
| Preview and Tag Assistant | Work as usual | Tag Assistant’s Troubleshoot tag is not compatible | Not applicable |

The Google & YouTube app is the route Shopify recommends for Google tags alone. Its help page notes that Google doesn’t recommend the GTM custom pixel route and can’t provide technical support for it ([Shopify](https://help.shopify.com/en/manual/checkout-settings/customize-checkout-configurations/upgrade-thank-you-order-status/replace-google-tag)). If GTM also manages Meta, TikTok, Pinterest, or your own tags, the custom pixel is still the place to do it. Just don’t run both for the same Google events.

## Step 1: GTM in the theme

1.  In GTM, open Admin → Install Google Tag Manager and copy both snippets.
2.  In Shopify, go to Online Store → Themes, open the menu of your live theme and choose Edit code.
3.  In `layout/theme.liquid`, paste the `<script>` snippet right after `<head>` and the `<noscript>` snippet right after `<body>`. Save.

This container sees storefront pages only. To give it product and cart data, render a [dataLayer](/blog/data-layer) push from Liquid on the templates that need it, or leave ecommerce events to the pixel in step 2 and keep the theme container for what needs the DOM.

## Step 2: GTM in a custom pixel

Shopify’s pixels load on the storefront, checkout, Thank you page, and Order status page, and custom pixels run in a lax sandbox ([Shopify](https://help.shopify.com/en/manual/promoting-marketing/pixels/custom-pixels)). In Settings → Customer events, choose Add custom pixel, then:

1.  Paste the GTM `<head>` snippet without its `<script>` tags.
2.  Subscribe to the events you need and push each to `window.dataLayer`.
3.  Under Permission, choose which purposes the pixel needs (see consent, below), then save and connect.

```js
window.dataLayer = window.dataLayer || [];

// GTM <head> snippet, without the <script> tags
(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');

analytics.subscribe('checkout_completed', (event) => {
  const checkout = event.data.checkout;
  window.dataLayer.push({ ecommerce: null });
  window.dataLayer.push({
    event: 'purchase',
    page_location: event.context.window.location.href,
    ecommerce: {
      transaction_id: checkout.order?.id,
      value: checkout.totalPrice?.amount,
      tax: checkout.totalTax?.amount,
      shipping: checkout.shippingLine?.price?.amount,
      currency: checkout.currencyCode,
      items: checkout.lineItems.map((item) => ({
        item_id: item.variant?.sku || item.variant?.id,
        item_name: item.variant?.product?.title || item.title,
        item_brand: item.variant?.product?.vendor,
        price: item.variant?.price?.amount,
        quantity: item.quantity,
      })),
    },
  });
});
```

In GTM, the trigger is a Custom Event whose name matches the `event` key, and the parameters come from dataLayer variables. Three limits from Shopify’s own [GTM tutorial](https://help.shopify.com/en/manual/promoting-marketing/pixels/custom-pixels/gtm-tutorial) catch most teams:

-   **Page URLs carry the sandbox.** Send `event.context.window.location.href` as `page_location`, as above, or GA4 records the iframe’s URL.
-   **Outbound clicks and other enhanced measurement events don’t fire on their own** inside the pixel.
-   **The site’s dataLayer isn’t there.** The pixel has its own `window`. Values set on the storefront need another way in, such as `localStorage`, which also works in the sandboxed checkout ([Trackingplan docs](/docs/installing-trackingplan/installing-trackingplan-on-your-websites)).

## Step 3: map Shopify’s events to GA4

Shopify publishes 15 standard events ([Shopify](https://shopify.dev/docs/api/web-pixels-api/standard-events)). These are the ones a GA4 ecommerce setup needs:

| Shopify event | GA4 event |
| --- | --- |
| `page_viewed` | `page_view` |
| `collection_viewed` | `view_item_list` |
| `product_viewed` | `view_item` |
| `search_submitted` | `search` |
| `product_added_to_cart` | `add_to_cart` |
| `product_removed_from_cart` | `remove_from_cart` |
| `cart_viewed` | `view_cart` |
| `checkout_started` | `begin_checkout` |
| `checkout_shipping_info_submitted` | `add_shipping_info` |
| `payment_info_submitted` | `add_payment_info` |
| `checkout_completed` | `purchase` |

Two decisions to make once and write down. Which ID is `item_id`, the SKU or the variant ID, because Meta’s catalog and GA4’s item reports have to agree. And whether `value` includes tax and shipping, because every platform that receives it has to get the same number.

## Consent: the line most setups copy wrong

Shopify’s example pixel sets every Consent Mode signal to `granted`, and warns that those values might not match what your store requires. Copy it as is and GA4 and Google Ads receive “granted” for visitors who said no.

Two settings decide what really happens:

-   **The pixel’s permission.** In markets that require consent, usually the EEA and the UK, pixels run only when the visitor has given the permissions they need. New pixels require Marketing and Analytics by default ([Shopify](https://help.shopify.com/en/manual/promoting-marketing/pixels/overview)).
-   **The Consent Mode state inside the pixel.** Read it from Shopify instead of hard-coding it: `init.customerPrivacy` holds the state when the pixel loads, and `api.customerPrivacy.subscribe('visitorConsentCollected', …)` reports changes, with `analyticsProcessingAllowed` and `marketingAllowed` among its fields ([Shopify](https://shopify.dev/docs/api/web-pixels-api/pixel-privacy)). Map those to `analytics_storage`, `ad_storage`, `ad_user_data`, and `ad_personalization` before GTM loads.

Expect fewer events after the switch from checkout scripts to pixels. Shopify says so itself: pixels only track customer behavior with consent.

## Why Preview mode is not enough on Shopify

The usual checks still apply: Preview mode on storefront pages, GA4 DebugView, and a test order through Shopify’s test gateway with the value, currency, and items checked. The [GTM debugging guide](/blog/gtm-debugging-guide) covers each one.

Shopify adds three gaps they don’t cover:

-   **The checkout container is out of reach.** Tag Assistant’s Troubleshoot tag doesn’t detect Google tags inside a custom pixel, so the purchase tag is the one you see least.
-   **Duplicates come from the admin, not from GTM.** A new app pixel, sales channel, or the Google & YouTube app can send the same event a second time, and the platform counts both ([Shopify](https://help.shopify.com/en/manual/checkout-settings/customize-checkout-configurations/upgrade-thank-you-order-status/additional-scripts)). Nobody touches the container, so nobody opens Preview.
-   **Consent changes what fires.** Your test order runs with your consent. Real visitors in the EEA run with theirs.

Fact, a Copenhagen ecommerce agency, has seen the second one at clients. A client changes their Shopify store without telling anyone, and something as small as a new sales channel not connected properly to Meta starts firing extra events: duplicate `view_item`, and an artificial spike in items viewed. Without monitoring, Fact found out when the reports showed it [two weeks later](/customer-stories/how-fact-keeps-analytics-accurate-for-a-growing-client-portfolio), and those duplicates had fired before Consent Mode.

## Keep it measured correctly with Trackingplan

A Shopify setup is correct the day you test it. After that it changes with every app, theme update, and campaign. Trackingplan checks it on real traffic, every hour, so a broken purchase or a consent breach shows up in hours, not weeks.

On Shopify, the Trackingplan SDK goes at the top of every custom pixel, so it sees the checkout hits that Preview can’t ([install guide](/docs/installing-trackingplan/installing-trackingplan-on-your-websites)). The storefront takes the usual GTM tag or snippet. From there it learns your events and their properties from traffic, with no tracking plan to write first, and flags what changes:

-   **Missing or duplicate events,** such as a second `purchase` from a new app pixel or a `view_item` that doubled overnight.
-   **Wrong values and properties,** such as a `transaction_id` that went null or a currency that doesn’t match the value.
-   **The same purchase across platforms:** GA4, Meta Pixel and CAPI, Google Ads, with the same value, counted once.
-   **Consent breaches:** vendors firing before opt-in and Consent Mode signals that don’t match what the visitor chose, per market.

Each issue arrives with the hits behind it and the event, property, or tag that changed, so the fix is a change in the pixel or the container, not an investigation. As Fact’s founder put it, with “sandboxed Shopify environments, Consent Mode, and such a variety of setups”, it’s not easy to know that what you believe is correct. That is the part worth automating.

## FAQ

**Can I add Google Tag Manager to Shopify without coding?** Partly. Pasting the GTM snippet into `theme.liquid` needs no code of your own, but it does not reach checkout. To track checkout and purchases you need a custom pixel that subscribes to Shopify’s events and pushes them to the dataLayer, which is a few lines of JavaScript. An app can write that pixel for you, at the cost of control over what it sends.

**Why doesn’t GTM Preview mode work on Shopify checkout?** GTM in a custom pixel runs inside Shopify’s sandbox, an iframe, not on the page itself. Shopify’s own documentation says Google Tag Assistant’s Troubleshoot tag feature isn’t compatible with custom pixels. Check checkout events with a test order and the GA4 DebugView, or by reading the hits each platform receives.

**Do I need Shopify Plus to use Google Tag Manager?** No. Any plan can add GTM to the theme and run it in a custom pixel. Since August 26, 2026, no store can add scripts to the Thank you and Order status pages, so the custom pixel is the way to reach checkout on every plan.

**Why does GA4 show duplicate purchases on Shopify?** Usually because two sources send the same event: GTM in the theme and in a custom pixel, or GTM next to the Google & YouTube app or another app pixel. Shopify warns that a platform counts events both from a script and from an app pixel. Pick one source per event and per platform. For the wider pattern, see [duplicate conversion tracking](/blog/duplicate-conversion-tracking).

On this page

1.  [*01*The short answer](#the-short-answer)
2.  [*02*Your options, side by side](#your-options-side-by-side)
3.  [*03*Step 1: GTM in the theme](#step-1-gtm-in-the-theme)
4.  [*04*Step 2: GTM in a custom pixel](#step-2-gtm-in-a-custom-pixel)
5.  [*05*Step 3: map Shopify’s events to GA4](#step-3-map-shopify-s-events-to-ga4)
6.  [*06*Consent: the line most setups copy wrong](#consent-the-line-most-setups-copy-wrong)
7.  [*07*Why Preview mode is not enough on Shopify](#why-preview-mode-is-not-enough-on-shopify)
8.  [*08*Keep it measured correctly with Trackingplan](#keep-it-measured-correctly-with-trackingplan)
9.  [*09*FAQ](#faq)

**Stop babysitting tags**

Trackingplan audits your real user data around the clock and flags issues before they cost you.

[Start free trial →](https://app.trackingplan.com/signup)

![](/images/65d75b0ae8d69ef95785a5d6_david-pombar.webp)

**David Pombar** Swiss army knife at Trackingplan

Read more from David, a Senior Product Strategist with 18+ years in digital product development and an atypical error detection knack.

Share Copy link [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fwww.trackingplan.com%2Fblog%2Fgoogle-tag-manager-shopify) [X](https://twitter.com/intent/tweet?url=https%3A%2F%2Fwww.trackingplan.com%2Fblog%2Fgoogle-tag-manager-shopify&text=Google%20Tag%20Manager%20on%20Shopify%3A%20set%20it%20up%20and%20verify%20it)

Read next

[All Blog →](/blog)

-   [
    
    16 minAnalytics ImplementationOctober 14, 2026
    
    ### GTM debugging: manual methods vs continuous monitoring
    
    How to debug Google Tag Manager with Preview Mode, extensions, the Network tab and server-side preview, and when continuous monitoring takes over.
    
    by **David Pombar**](/blog/gtm-debugging-guide)
-   [
    
    19 minPaid MediaMay 22, 2026
    
    ### Duplicate conversion tracking: how to find and fix it
    
    Prevent inflated metrics. Detect, fix, & prevent duplicate conversion tracking across all platforms with our 2026 step-by-step guide.
    
    by **David Pombar**](/blog/duplicate-conversion-tracking)
-   [
    
    18 minAnalytics ImplementationMarch 29, 2026
    
    ### Unlocking Your Data Layer A Guide for 2026
    
    Learn what a data layer is and why it's essential for your analytics. This complete guide covers schemas, best practices, and automated validation.
    
    by **David Pombar**](/blog/data-layer)

Trackingplan

## See everything. Miss nothing.

Your implementations audited around the clock with real-time, real-user data. Real-time alerts about errors or changes in your data, campaigns, pixels, privacy and consent. Let AI flag issues before they cost you.

[Start free trial →](https://app.trackingplan.com/signup) [Book a demo](/demo)
