Every tracking audit I run starts the same way: someone swears the tag is set up right, and it is. In the workspace. Which was never published. Here are the 12 real reasons a GTM tag doesn't fire, in the order they actually happen. Work down the list. Don't skip ahead to the exotic stuff.
- Is the container published? — Preview shows your workspace; visitors get the last published version
- Do the trigger conditions match? — Trailing slash, query string and casing all break a URL equals match
- Did you mean OR, not AND? — Conditions in one trigger must all be true; multiple triggers give you OR
- Does the event name match exactly? — purchase never matches Purchase; read Preview's left-hand timeline
- Is consent blocking the tag? — The Consent tab shows each state at the moment the tag was evaluated
- Then check delivery, not firing — Fired only means GTM ran the code; the Network tab proves it left
What should I check first when a GTM tag isn't firing?
The boring things first, because the boring things are the culprit most of the time. The list is sorted by how often I find each cause in real audits: 1 through 5 cover most cases, while 9 through 12 make you feel crazy because Preview looks fine and the data still isn't there.
1. Is the container actually published?
Preview mode shows your workspace, not the live container. Your tag fires beautifully in Preview and does nothing for real visitors, because they get the last published version. If GTM shows a Submit button with pending changes, your work is not live. Confirm in the Versions tab. This catches everyone, including people who've used GTM for years.
2. Are the trigger conditions subtly wrong?
Trigger conditions fail on details you can't see at a glance. Page URL equals example.com/thank-you won't match example.com/thank-you/ (trailing slash), example.com/thank-you?session=abc (query string), or example.com/Thank-You (matching is case-sensitive). In Preview, click your tag under "Tags Not Fired": GTM marks each condition with a check or an X. Then compare the actual Page URL value in the Variables tab, character by character. When in doubt, use Page Path contains /thank-you instead of a full-URL equals match.
3. Did you put multiple conditions in one trigger when you meant OR?
Inside a single trigger, every condition must be true at once. That's AND logic. Add "Page URL contains /checkout" and "Page URL contains /thank-you" to one trigger and it can never fire, because no URL contains both. For OR logic, create two triggers and attach both to the tag. Multiple triggers = OR. Multiple conditions in one trigger = AND. A huge share of the broken triggers I see are exactly this mix-up.
4. Does the dataLayer event name match exactly?
A Custom Event trigger listening for purchase will never catch a push named Purchase or purchase_complete. Event names are case-sensitive, exact-match strings. This bites hardest on ecommerce: the platform pushes GA4-style purchase, but the trigger listens for a custom name some previous developer invented. Preview's left-hand timeline lists every event name that actually hit the dataLayer. Read them, then match what's really there.
5. Is the dataLayer.push happening before GTM loads?
Timing kills more tags than typos. Two common failure modes here:
- The code does
dataLayer = [...](assignment) instead ofdataLayer.push(...). An assignment after GTM loads replaces the array GTM is watching, and every push after that is invisible. - The push fires so late (after a redirect, inside a slow callback) that the visitor already left the page.
The safe pattern:
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
event: "purchase_complete",
transaction_id: "T-1001",
value: 149.00
});
Pushes made before GTM loads are fine. Assignments are the poison.
6. Is the GTM snippet actually on that page?
Different templates, different snippets. Your product template has GTM, but the checkout runs on a separate template, subdomain, or third-party page that doesn't. View source on the exact failing page and search for your container ID (GTM-XXXXXXX). If Preview won't even connect, this is usually why. Also check for a staging container ID pasted into production.
7. Is consent blocking the tag?
With Consent Mode v2 enforced for EEA traffic, this has moved way up the list. If consent defaults are denied and nothing updates them, tags with built-in consent checks (Google tags respect ad_storage and analytics_storage) simply hold or drop. GTM can also require additional consent per tag, and a CMP can block everything until the banner is answered. In Preview, the Consent tab shows each consent state at the moment your tag was evaluated. A tag that fires for you but "not for EU visitors" is a consent problem until proven otherwise.
8. Is a blocking trigger (exception) suppressing it?
Tags can have exceptions: triggers that prevent firing even when the main trigger matches. Someone added "block on pages containing /test" two years ago, and your new landing page URL contains that string. Scroll past the firing triggers in the tag's configuration and read the exceptions. Preview shows a failed exception in the same firing-status view.
9. Did the tag fire but never deliver?
This is the one Preview mode actively hides from you. "Fired" only means GTM executed the tag's code. Whether the request to Google, Meta, or TikTok ever left the browser is a different question, and ad blockers plus browser privacy features kill it after firing. Open DevTools, Network tab, reload, and filter for the endpoint (collect for GA4, facebook.com/tr for Meta Pixel). Fired with no matching network request means the tag is fine and delivery is broken. Preview will never show you those losses. More on this class below.
10. Is it a single-page app without a history trigger?
On SPAs (React, Vue, Next.js, many funnel builders), navigation doesn't reload the page, so a Page View trigger fires once at first load and never again. Use a History Change trigger, or better, have developers push an explicit dataLayer event on each route change. If your tag fires on the first page a visitor lands on and never after that, this is your answer.
11. Is the element inside an iframe?
GTM can't see inside iframes. Embedded booking widgets, payment forms, third-party checkouts: if the button lives in an iframe, your click trigger in the parent page will never hear it. Right-click the element; "View frame source" means it's framed. Fixes: a container inside the iframe (if you control it), a postMessage to the parent turned into a dataLayer push, or the vendor's own callback events.
12. Is a JavaScript error upstream killing the container?
An uncaught error in a Custom HTML tag or the page's own scripts can stop later tags from running. Open the console on the failing page and look for red. Test by pausing recently added Custom HTML tags one at a time and re-checking in Preview.
How do I use Preview mode without fooling myself?
Ask it one question at a time. The left timeline: did my event reach the dataLayer (reasons 4 and 5)? The "Tags Not Fired" detail: which condition failed (reasons 2, 3, 8)? The Variables tab: what values did GTM actually see? The Consent tab: reason 7. What Preview cannot answer is whether the fired request survived the trip to the ad platform. That takes the Network tab.
- Tag fires in Preview — Green check: GTM executed the tag's code
- Request leaves browser — collect for GA4, facebook.com/tr for Meta
- Ad blocker kills it — No network request; Preview still shows green
- Nothing is counted — Conversions missing, container looks fine
- Server-side delivery — One request to your subdomain, then fan-out
Why is server-side tracking the fix for "fired but not received"?
Because reasons 1 through 8 are configuration problems you can repair, but reason 9 is structural. Your tags run in the visitor's browser, and the browser is hostile territory: ad blockers strip Meta Pixel and GA4 requests, Safari's ITP caps cookie lifetimes, iOS privacy features degrade what gets through. A perfect container can still lose a meaningful slice of conversions in transit, with Preview showing green checkmarks the whole time.
Server-side tracking, in plain terms: instead of the browser sending data straight to Meta or Google, it sends one lightweight request to a server you control, on your own subdomain (something like track.yourstore.com). That server forwards clean, complete events to every platform. Because the request goes to your first-party domain, ad blockers and browser privacy rules mostly leave it alone, your cookies live longer, and you decide exactly what each platform gets, per the visitor's consent. One server source of truth also means Meta, Google Ads, and GA4 finally report from the same events, deduplicated properly, instead of three scripts each losing a different slice. Platforms optimize your campaigns on real conversions instead of a sample.
Frequently asked questions
Why is my GTM tag firing in Preview mode but not on the live site?
Almost always because the container isn't published: Preview shows your workspace draft, while live visitors get the last published version. Publish, verify in the Versions tab, then check consent and ad blockers.
Why does my Custom Event trigger not fire even though I see the dataLayer push?
The trigger's event name doesn't exactly match the pushed name, and matching is case-sensitive. Compare it to the name in Preview mode's left timeline, character for character.
What's the difference between multiple triggers and multiple conditions in GTM?
Conditions inside one trigger must all be true at once (AND). Multiple triggers attached to one tag fire it if any one matches (OR). Need OR logic? Build separate triggers.
How do I know if an ad blocker is blocking my tag?
Open DevTools, Network tab, reload, and look for the tag's outbound request (like facebook.com/tr for Meta). If Preview says the tag fired but there's no request, an ad blocker or browser privacy feature killed it after firing.
Why do my GTM tags only fire on the first page of my site?
Your site is a single-page app, so navigation doesn't trigger a real page load. Add a History Change trigger, or push a dataLayer event on every route change, and fire tags from that instead of Page View.
Can Consent Mode stop my tags from firing completely?
Yes. If consent defaults are denied and your banner never sends an update, Google tags with built-in consent checks won't fire, and tags with additional consent requirements stay blocked. Check the Consent tab in Preview mode.
Does server-side tracking mean I can delete my web GTM container?
No. The web container still collects events and sends them to your tagging server, which forwards them to the ad platforms. Server-side replaces the fragile browser-to-platform leg, not the container itself.
- gtm
- debugging
- fix it

