Why Your GTM Trigger Won't Fire and GTM Won't Tell You Why
GTM's Preview mode shows a green checkmark when a tag fires and a red x when it doesn't. It shows the trigger conditions, the evaluated values, and whether each condition matched. What it doesn't show is why the conditions were evaluated the way they were, what logic connects them, or why a setup that looks correct produces no output.
The most common trigger problems aren't bugs. They're misunderstandings of how GTM evaluates conditions, matches events, and sequences tags. Each one looks correct in the GTM interface and fails silently on the live site.
AND versus OR in trigger conditions
This is the most common trigger mistake. It's also the most frustrating because the GTM interface doesn't make the logic visible.
When you add multiple conditions to a single trigger, GTM requires ALL conditions to be true simultaneously. This is AND logic. A trigger with three URL conditions (Page URL contains /blog/, Page URL contains /news/, Page URL contains /resources/) requires the current URL to contain all three strings at the same time. No single URL will match this trigger because no URL contains /blog/ AND /news/ AND /resources/ simultaneously. The trigger never fires, and GTM doesn't warn you that the conditions are mutually exclusive.
The intended behavior was almost certainly OR logic: fire on pages that contain /blog/ OR /news/ OR /resources/. GTM supports this, but not through multiple conditions on a single trigger. The options are:
Regex in a single condition. Use "Page URL matches RegEx" with the pattern /blog/|/news/|/resources/. The pipe | operator is OR logic in regex. One condition, one trigger, fires on any matching URL.
Multiple triggers on the same tag. Create three separate triggers (one for /blog/, one for /news/, one for /resources/) and attach all three to the tag. Multiple triggers on a single tag use OR logic: the tag fires when ANY of its triggers match. This is the GTM-native way to express "fire on page A or page B or page C."
The confusion comes from the GTM interface presenting multiple conditions on a trigger as a list, which visually suggests OR ("fire on any of these"). The logic is AND ("fire when all of these are true"), but nothing in the interface says so. Google's documentation on trigger types explains this, but it's easy to miss if you're building triggers by intuition.
Blocking triggers and the type restriction
Blocking triggers (also called exceptions) prevent a tag from firing when specific conditions are met. A tag with a firing trigger AND a blocking trigger fires when the firing trigger matches AND the blocking trigger does NOT match. Straightforward in concept.
The restriction that catches people: a blocking trigger can only block a firing trigger of the same event type. A Page View blocking trigger can only block Page View firing triggers. A Click blocking trigger can only block Click firing triggers. A Custom Event blocking trigger can only block Custom Event firing triggers.
This means you can't create a universal blocking trigger that prevents a tag from firing in all circumstances. A tag with a Page View firing trigger and a Click blocking trigger will fire on page views regardless of the blocking trigger, because the blocking trigger's event type (Click) doesn't match the firing trigger's event type (Page View). The blocking trigger is simply ignored.
If you need to block a tag across all event types, the workaround is to create a blocking trigger for each event type the tag's firing triggers use, or to use a Custom JavaScript variable that returns true when the tag should be blocked and add that as a condition on each firing trigger.
Case sensitivity in event matching
GTM is case-sensitive for everything: event names, variable values, trigger conditions, and regex patterns. A trigger configured to fire on the custom event formSubmissionComplete will not match a dataLayer push with the event name formsubmissioncomplete or FormSubmissionComplete. No warning, no partial match, no fuzzy matching. The strings must be identical.
This is the second most common trigger debugging problem after AND/OR confusion. A developer pushes a dataLayer event with one casing convention, and a marketer configures a trigger with a different convention. The event appears in GTM's Preview panel (it's in the dataLayer), the trigger conditions look correct (the event name is spelled the same), but the trigger doesn't fire because the casing differs by one capital letter.
The debugging process is maddening because Preview mode shows the event, shows the trigger, and shows the conditions as "not matched" without explaining why. The fix is always the same: copy the exact event name from the Preview panel's dataLayer tab and paste it into the trigger configuration. Typing the event name manually introduces the possibility of case mismatches.
GA4 compounds this problem by treating event names as case-sensitive in reports. generate_lead and Generate_Lead appear as two separate events in GA4 even though they represent the same action. The safest convention is all-lowercase snake_case for every event name, enforced at the dataLayer push level, not at the trigger level.
Tag sequencing and firing order
GTM fires tags asynchronously by default. When a trigger matches and multiple tags are attached to it, all tags fire simultaneously with no guaranteed execution order. This is fine when the tags are independent (a GA4 event, a Google Ads conversion, and a Meta Pixel can all fire in any order), but it's a problem when one tag depends on another's output.
A common scenario: a Custom HTML tag pushes data to the dataLayer, and a GA4 event tag reads that data as a parameter. If both tags fire on the same trigger, the GA4 tag may fire before the Custom HTML tag has pushed the data, reading undefined values instead. The result is intermittent: sometimes the GA4 tag fires first (parameters are empty), sometimes the Custom HTML fires first (parameters populate correctly). The behavior appears random because asynchronous execution order is non-deterministic.
Tag Sequencing (the "Tag Sequencing" section in a tag's Advanced Settings) solves this by creating explicit before/after relationships. A Setup tag fires before the main tag and must complete before the main tag begins. A Cleanup tag fires after the main tag completes. The sequence is guaranteed.
The trap with Tag Sequencing: a tag used as a Setup or Cleanup tag in a sequence fires as part of that sequence regardless of its own triggers. If the same tag also has an independent trigger, it fires twice: once from its own trigger and once as part of the sequence. This is a common source of double-firing that's difficult to diagnose because the duplicate isn't visible in the tag's trigger configuration.
Tags that work in Preview but not on the live site
Several configurations cause tags to fire in Preview mode but fail on the published site:
"Only fire in published containers" is an Advanced Setting that prevents a tag from executing in Preview/Debug mode entirely. It exists for billing-sensitive tags (ad pixels where impressions cost money during testing) and conversion tags where test fires would corrupt data. A tag with this setting enabled appears in the Preview panel with its triggers evaluated, but the tag itself never executes. The Preview panel doesn't prominently flag this setting, making it easy to miss during debugging.
Consent state differences. Preview mode may operate with a different consent state than the live site. If the CMP grants consent during preview (because the consent banner was already dismissed in the testing session) but denies consent for new visitors on the live site, tags with consent requirements fire in preview but not in production. This is especially common with CMPs that remember consent choices in cookies: the tester's browser has "granted" from a previous session, but first-time visitors start with "denied."
Domain restrictions. Some triggers include URL conditions that match the production domain but not the preview URL. A trigger requiring "Page URL contains example.com" won't fire if Preview mode loads the site from a different URL or preview proxy.
Race conditions with external scripts. Custom HTML tags that depend on external vendor scripts (waiting for a global function to be defined) may work in Preview because the slower debug environment gives scripts more time to load, but fail on the faster production page where the tag fires before the external script is ready.
Debugging parameters in production
A related problem that isn't about triggers but shows up during trigger debugging: gtm_tag_name is a parameter that records which GTM tag fired an event. It's useful during development because it tells you exactly which tag produced which event. But the parameter persists when the container is published, sending debugging data to GA4 on every event for every visitor.
This consumes one of GA4's 25 custom parameter slots per event with data that has no analytical value in production. It also clutters BigQuery exports with a column that's only useful during development. If your container sends gtm_tag_name or debug_mode as event parameters, consider whether they're still needed or whether they're development artifacts that should have been removed before publishing.
The pattern is the same as dead UA tags: something useful during setup becomes invisible debt in production because nobody removed it when the development phase ended.