GTM 11 min read

7 Common GTM Mistakes That Break Your Analytics (And How to Fix Them)

The most expensive Google Tag Manager mistakes we see in client audits, duplicate tags, broken data layers, missing variables, and triggers that fire on the wrong pages.

A
Ashwani Bhasin
·

After auditing dozens of GTM containers, the same mistakes appear over and over. Some are innocent setup errors. Others are ticking time bombs, containers that look like they’re working until someone checks the data and finds three years of inflated sessions and double-counted conversions.

Here are the seven most damaging GTM mistakes we find in client containers, and exactly how to fix each one.


Mistake #1: Duplicate Tags Firing on Every Page

What it looks like: GA4 pageview events showing up twice in GA4 DebugView. Session counts are 1.5–2x higher than your actual traffic. Reports look inflated but you can’t figure out why.

Why it happens:

  • Someone installed the GA4 tag via GTM and hardcoded the gtag.js snippet in the page <head>
  • A second GTM container was added to the site without removing the first
  • The GA4 Configuration Tag was duplicated inside the container (two tags with the same Measurement ID)

How to diagnose:

Open Chrome DevTools → Network tab → filter by collect? or g/collect. If you see two requests firing on every pageview, you have a duplicate.

// In the browser console, check how many GA4 instances are running:
window.dataLayer.filter(d => d[0] === 'config')
// Should show ONE entry per page load. Multiple = duplicates.

Also check the page source (Ctrl+U) and search for G-XXXXXXXXXX (your Measurement ID). It should appear only once, inside the GTM script.

How to fix:

  1. Search the site’s codebase for the Measurement ID, remove any hardcoded gtag.js or ga.js snippets
  2. Inside GTM, check for duplicate Configuration Tags: GTM → Tags → search your Measurement ID
  3. Verify only one GTM container snippet is on the page

Reference: GA4 Deduplication in GTM


Mistake #2: The All Pages Trigger on Conversion Tags

What it looks like: Your “thank you page” event or purchase event fires on every page, not just the confirmation page. Your conversion numbers are wildly inflated.

Why it happens: Someone created a conversion tag and used the All Pages trigger instead of a page-specific trigger. This is one of the most common mistakes made by developers who are new to GTM.

How to diagnose:

In GTM Preview mode, navigate to your homepage. If your conversion tag (e.g., GA4 - Purchase Event) fires on the homepage, it’s broken.

How to fix:

Create a proper trigger for confirmation/thank-you pages only:

  1. GTM → Triggers → New
  2. Trigger Type: Page View
  3. Fire on: Some Page Views
  4. Condition: Page Pathcontains/order-confirmation (or your actual path)

For e-commerce, the better approach is to use a dataLayer event trigger:

// Push this from your order confirmation page:
window.dataLayer.push({
  event: 'purchase',
  ecommerce: {
    transaction_id: 'T_12345',
    value: 59.99,
    currency: 'USD',
    items: [...]
  }
});

Then in GTM, trigger on Custom Event → Event name: purchase.

Reference: GTM Trigger types


Mistake #3: Missing or Broken dataLayer Variables

What it looks like: Your GA4 events fire, but custom dimensions are blank. Product names, categories, prices are missing from e-commerce reports. You see undefined or (not set) in GA4.

Why it happens: GTM variables are referencing dataLayer keys that either:

  • Don’t exist (typo in the key name)
  • Haven’t been pushed yet when the tag fires
  • Are nested incorrectly (e.g., ecommerce.items[0].item_name vs ecommerce.items.0.item_name in GTM variable syntax)

How to diagnose:

In GTM Preview, click on a tag that’s supposed to send product data. In the Variables tab, look for variables showing as undefined.

Also check the dataLayer panel, expand the relevant event and verify the key names match exactly what your GTM variables reference.

Common variable path issues:

What you wantGTM variable path
ecommerce.valueecommerce.value
First item’s nameecommerce.items.0.item_name
ecommerce.items[0].priceecommerce.items.0.price

GTM uses dot notation for nested objects. Bracket notation ([0]) doesn’t work in GTM variable paths.

How to fix:

  1. Open GTM Preview → click the event → Variables tab
  2. Find any variable showing undefined
  3. Cross-reference the variable’s Data Layer Variable Name with the actual dataLayer push from your developer
  4. Correct any typos or nesting mismatches

For debugging, add this to your browser console:

// See everything in the dataLayer
window.dataLayer.forEach((entry, index) => {
  console.log(index, JSON.stringify(entry, null, 2));
});

Mistake #4: Tags Firing in Preview/Debug Mode But Not in Production

What it looks like: Everything works perfectly in GTM Preview. You publish. GA4 DebugView stops showing events. Your live reports never see the data.

Why it happens (three common causes):

A) Tag blocked by Content Security Policy (CSP) Your site’s CSP header blocks GTM’s domains from loading scripts or making requests. GTM works in Preview because Preview injects differently.

Check: Open DevTools → Console. Look for CSP errors like:

Refused to load script from 'https://www.googletagmanager.com'

Fix: Add GTM’s domains to your CSP script-src and connect-src directives:

script-src 'self' https://www.googletagmanager.com;
connect-src 'self' https://www.google-analytics.com https://analytics.google.com;

B) Trigger fires on URL pattern that doesn’t exist in production Your trigger uses Page URL contains staging.yoursite.com or a development path that doesn’t exist live.

Fix: Review all trigger conditions. Remove environment-specific URL conditions.

C) Tag never published (Draft status) GTM containers have versions. If a tag is in a workspace but no new version was published, it won’t run on the live site.

Fix: GTM → Submit → Publish new version. Verify the live container version number matches.


Mistake #5: Cross-Domain Tracking Not Configured

What it looks like: Users who move from yoursite.com to shop.yoursite.com (or to a payment processor) show up as two separate sessions. Conversion attribution is broken, GA4 attributes the purchase to (direct) instead of the original traffic source.

Why it happens: GA4 and GTM need explicit configuration to pass the _ga session cookie across domains.

How to diagnose:

  1. In GA4 → Reports → Traffic Acquisition, check if a huge percentage of conversions come from (direct) / (none)
  2. This is a red flag, real users rarely type URLs directly before purchasing

How to fix in GA4:

  1. GA4 → AdminData Streams → your web stream
  2. Configure tag settingsConfigure your domains
  3. Add all domains that should share session data:
    • yoursite.com
    • shop.yoursite.com
    • checkout.paymentprovider.com (if applicable)

How to fix in GTM:

If using GTM’s GA4 Configuration Tag:

  1. Open your GA4 Configuration Tag
  2. Fields to Set → Add field:
    • Field Name: linker
    • Value: {"domains": ["shop.yoursite.com", "yoursite.com"]}

Reference: GA4 cross-domain measurement


Mistake #6: Excluding Internal Traffic But Not Bot Traffic

What it looks like: Your traffic numbers look healthy, but engagement rate is unusually low. Bounce rate is high from certain sources. Your own visits inflate session counts.

Why it happens: Most people know to exclude their own IP in GA4, but forget about:

  • Office IPs (when the team works from an office)
  • Contractor and agency IPs
  • Bot and crawler traffic
  • Staging/preview environments

How to fix internal traffic:

In GA4:

  1. AdminData Streams → your stream → Configure tag settings
  2. Define internal traffic → add your IP ranges
  3. AdminData filtersInternal Traffic → set to Active

In GTM (alternative approach): Create a Lookup Table variable that returns true for known internal IPs, then add an exception trigger to all tags.

How to fix bot traffic:

GA4 automatically filters known bots (IAB list), but unknown bots slip through.

  1. GA4 → AdminReporting Identity
  2. Verify “Filter out known bots and spiders” is enabled (it should be by default)

For additional bot filtering, create a GA4 audience exclusion or use a custom filter:

// In GTM, block tags from firing on headless browsers
// (Many bots don't have userAgent strings with standard browser identifiers)
{{JS - Is Not Bot}} variable:
function() {
  return !/bot|crawler|spider|crawling/i.test(navigator.userAgent)
    && navigator.webdriver !== true;
}

Reference: GA4 data filters


Mistake #7: Firing the Purchase Event Without Deduplication

What it looks like: Your GA4 purchase events and revenue figures are significantly higher than your actual orders. You have a Shopify store where purchase fires 1.8x per transaction on average.

Why it happens: The order confirmation page can be:

  • Refreshed by the user (double submission)
  • Hit by the browser’s back button
  • Cached and re-served

Without deduplication, the purchase event fires every time the confirmation page loads, even for the same order.

How to fix:

Method 1: Transaction ID deduplication in GA4

GA4 automatically deduplicates purchase events with the same transaction_id within a 7-day window, but only if you’re consistently sending the transaction_id parameter.

Verify your purchase event includes it:

window.dataLayer.push({
  event: 'purchase',
  ecommerce: {
    transaction_id: 'ORDER-12345',  // ← This MUST be unique per order
    value: 59.99,
    currency: 'USD',
    items: [...]
  }
});

Method 2: sessionStorage flag

// On the confirmation page:
const orderId = 'ORDER-12345';
const key = `tracked_${orderId}`;

if (!sessionStorage.getItem(key)) {
  sessionStorage.setItem(key, '1');
  window.dataLayer.push({
    event: 'purchase',
    ecommerce: { transaction_id: orderId, ... }
  });
}

Method 3: GTM trigger with custom condition

In GTM, create a JavaScript variable that returns true only if the order ID hasn’t been tracked this session, then add it as a trigger condition on your purchase tag.

Reference: GA4 ecommerce measurement


Run a GTM Container Audit

Before your next campaign launch, run through this checklist:

□ Search page source for duplicate GTM containers or hardcoded GA tags
□ Preview mode: check each tag fires on the RIGHT pages only
□ Preview mode: no conversion tags fire on the homepage
□ All dataLayer variables return actual values (not undefined)
□ Cross-domain tracking configured if using multiple subdomains
□ Internal traffic filter active in GA4
□ Purchase event includes transaction_id
□ All tags are published (current container version is live)
□ Consent Mode v2 defaults set before any tags fire

When to Get Help

If your GA4 data doesn’t match your Shopify, Stripe, or CRM data by more than 15%, something is broken. The earlier you find it, the less historical data is poisoned.

We do GTM container audits as a standalone engagement, you get a documented list of every broken tag, variable, and trigger, with prioritised fixes. Book a free consultation to discuss your setup.

#gtm#google-tag-manager#analytics#debugging#data-layer#ga4

Share this article

Want This Implemented Correctly?

Let our team apply these concepts to your specific setup — with QA validation and 30 days of support.