Skip to content
Back to blog
GTMJul 11, 2026 · Ludde Nyström · 15 min read

GTM Tag Firing Twice? Why It Happens and How to Stop Duplicate Events.

GTM tag firing twice? Overlapping triggers, duplicate GA4 config tags, and SPA history triggers — the real causes, and the fix for each.

GTM Tag Firing Twice? Why It Happens and How to Stop Duplicate Events

A GTM tag fires twice because it has two independent paths to firing that are both true at once — not because GTM glitched. The usual suspects: two triggers on the same tag that both match the same action, a page-load trigger stacked on top of a History Change trigger on a single-page app, a duplicated GA4 Configuration tag or a duplicated GTM snippet sitting on the page, or a tag wired into Tag Sequencing while it still keeps a live trigger of its own. Each of these is a specific, checkable configuration state, and GTM's Preview mode will tell you exactly which trigger fired it each time. The fix is to remove the second firing path — not to mask the symptom by changing a firing option and hoping.

This is a different problem from a tag that won't fire at all — see our GTM tag not firing guide if that's what you're actually chasing — and different again from a tag that fires once but reads a variable back as blank, which is usually a dataLayer-timing issue covered in our GTM dataLayer variable undefined guide. Here, the tag is firing, building a correct payload, and firing again for the same real-world action. Work down the table below in order — confirming or ruling out each cause narrows the rest.

The 7 Causes, Ranked by How Often They're the Real One

# Cause 10-second check Typical fix
1 Two triggers on the tag both match the same action Open the tag → Triggering — more than one trigger listed, both plausible for this page/event Consolidate into one trigger with AND'd conditions; delete the redundant one
2 Wired to both a Page View trigger and a History Change trigger Preview timeline shows two entries close together for one navigation Add a History Source condition; reconsider whether the base trigger is still needed
3 Firing option is Unlimited/Once per Event, not Once per Page Tag's Advanced Settings shows Unlimited on a conversion/confirmation tag Switch the radio to Once per Page
4 Two GA4 Configuration tags share the same Measurement ID Tags list, filter by type — more than one row with the identical G-ID Delete or pause the duplicate; keep exactly one config tag per property
5 gtag.js is hardcoded on the page as well as GTM's tag View source for a raw gtag/js script tag outside GTM's own injection Remove the hardcoded snippet, or set send_page_view: false on one
6 The GTM container snippet is installed twice on the page View source, search "GTM-" — the same ID appears in two script blocks Find and remove the redundant snippet (theme, plugin, or add-on)
7 Tag Sequencing fires it as a setup/cleanup tag, and its own trigger still matches This tag is listed as another tag's setup/cleanup tag AND has a live trigger Remove its independent trigger, or pause it and let the sequence own it

1. Are Two Triggers on the Same Tag Both Matching?

The most common cause, and the easiest to overlook: a tag's Triggering list is OR logic. GTM fires the tag once for every listed trigger that evaluates true — it does not deduplicate across them, because as far as GTM is concerned, two different triggers matching is two different reasons to fire.

The classic version: a tag has one trigger firing on All Pages and a second, narrower trigger — say a custom event equal to purchase — attached to the same tag. On a normal page, only the All Pages trigger fires. But on the one page where both conditions are true at once — the order-confirmation page, which is both "a page" and the page where your purchase event gets pushed — the tag fires twice: once because it's a page, once because the event happened. Neither trigger is misconfigured on its own. The problem only exists in the overlap between them.

A subtler variant: two separately-built triggers that were each meant to cover a different scenario, but whose conditions turn out to overlap on one specific page — a "Page View, Page Path contains /checkout" trigger and a "Custom Event equals checkout_step" trigger both attached to the same analytics tag, both legitimately true on the final checkout step.

Check it in Preview mode: click the timeline entry where you suspect the double fire, open the tag under Tags Fired, and look at which trigger Tag Assistant names as the reason. If the same tag appears against two different timeline entries for what you know was one real user action — or the tag's detail panel lists more than one satisfied trigger — you've found the overlap.

Fix: decide what you actually meant — usually it's AND logic ("this event, but only on this page"), which GTM expresses as a single trigger with multiple conditions, not two separate triggers each sufficient on its own. Consolidate to one trigger, or delete whichever of the two is redundant once the other covers the real case.

2. Is It Wired to Both a Page View Trigger and a History Change Trigger?

The single-page-app version of cause #1 — and the mirror image of a problem we cover in our GTM tag not firing guide: there, a tag needed a History Change trigger and didn't have one, so it never re-fired on client-side navigation. Here, it has one in addition to a base Page View or Initialization trigger, and the two overlap.

Two distinct ways this shows up. First: some frameworks emit more than one history-change-shaped signal for a single real navigation — a hash update and a pushState call firing together, for instance. A History Change trigger with no source condition catches both, so your tag fires twice for one navigation, on every navigation, not just the first. Second: some client-side routers normalize the URL with their own history call during initial bootstrap, so the very first load can trigger both the base Page View trigger (it's a real hard load) and the History Change trigger (the router just called pushState) — a double fire that's specific to the first pageview of a session and clean afterward. The give-away for which variant you have is whether the duplicate is every navigation or only the very first one.

Check it in Preview mode: navigate the app the way a real visitor would and watch the left-hand timeline. If a single click produces two entries close together — gtm.js immediately followed by gtm.historyChange, or two gtm.historyChange rows back to back — both are genuinely separate GTM events, and any tag listening to both will fire once per entry.

Fix: for duplicate sources on every navigation, add a History Source equals pushState (or whichever single source your framework actually uses — check the built-in {{History Source}} variable's value on the duplicate entries) condition on the History Change trigger, collapsing it to one match per real navigation. For a first-load-only double, setting the tag's firing option to Once per Page (see #3 below) is the safest general fix — it puts a hard ceiling on that one page regardless of how many triggers matched.

3. Is the Firing Option Set to Unlimited When It Needs a Hard Cap?

Often not the root cause on its own, but the missing guardrail that turns causes #1 and #2 into a real problem. Google's own documentation on tag firing options defines exactly three choices, found in Advanced Settings on any tag:

  • Unlimited: "Tags will fire whenever triggers tell it to" — Google's own note adds that this option "is only used with tag sequencing."
  • Once per event: "The tag will fire only once when the specified event occurs," intended to stop "multiple pieces of the same data" landing in the data layer for one event.
  • Once per page: "The tag will fire only once, when the page loads" — regardless of how many times a trigger condition is satisfied afterward.

The practical translation: for a tag with no Tag Sequencing relationship — the overwhelming majority — Unlimited and Once per Event behave identically in day-to-day use. Both fire on every trigger match, with no cap. If a page reloads, a trigger re-evaluates, or (see #1 and #2 above) two triggers both match, the tag fires again exactly as configured. Once per Page is the only one of the three that puts a ceiling on it — one fire, full stop, no matter how many times a trigger matches during that page's lifetime. A conversion tag double-firing when a confirmation page reloads under Unlimited isn't a bug — it's functioning exactly as configured, minus the cap you needed.

Fix: open the tag → Advanced Settings, and switch the firing-option radio to Once per Page. This is the right default for anything tied to a conversion — purchase, lead, sign-up — because a page reload, a browser back-forward, or an SPA re-render of the same confirmation view should never count as a second event. For the full tag-by-tag breakdown of which of your other tags should stay Unlimited versus switch, see our dedicated tag firing options guide.

4. Do You Have Two GA4 Configuration Tags Pointing at the Same Property?

The one that costs the most before anyone notices. Over time — an agency handoff, a second developer, a migration that never got cleaned up — a container accumulates two separate GA4 Configuration tags (GTM's newer tag-type picker may show this as a plain "Google tag," with your Measurement ID as its Tag ID — same underlying mechanism) carrying the identical G-XXXXXXX. Both usually fire on the same base Initialization or All Pages trigger, and both ship with "Send a page view event when this configuration loads" checked by default. Every page load now initializes the same property twice and sends two page_view events for it.

This is exactly the failure mode our GTM audit's duplicate-configuration check exists to catch: a container-level scan for GA4 Config tags sharing a Measurement ID, flagged before it inflates a full month of session data.

Check it: open the Tags list and filter by type — if more than one row of type "Google Analytics: GA4 Configuration" (or "Google Tag") carries the identical Measurement ID, that's confirmed. GA4 DebugView shows it too: two page_view events land within the same second, same page_location, often otherwise identical.

Fix: delete or pause the duplicate. Keep exactly one Configuration tag per Measurement ID in a container. If a second config genuinely needs to exist for a separate purpose — a consent-gated re-init, a delayed-load scenario — uncheck "Send a page view event when this configuration loads" on every copy except the one meant to own the pageview.

5. Is gtag.js Hardcoded on the Page Alongside the GTM-Managed Tag?

A common pattern practitioners call "double tagging." A gtag.js snippet — added by a theme, a page builder's "head code" field, a legacy migration nobody removed, or a marketing plugin bundling its own analytics call — loads directly on the page and configures the same Measurement ID that GTM's own GA4 Configuration tag also targets.

gtag.js has no built-in awareness that another gtag.js instance on the same page already configured the same property. Each call independently starts a session and, by default, sends its own page_view. Nothing merges them, and nothing warns you — the browser happily runs both.

Check it: view source (not the rendered DOM — the raw HTML) and search for gtag( or a <script src="…googletagmanager.com/gtag/js?id=G-…"> tag sitting outside GTM's own injected script block — GTM's tags are injected at runtime by gtm.js, so a gtag reference visible directly in the static page source, rather than inside GTM's own injection, is the hardcoded copy. In DevTools Network, filter for collect and look for two hits with the same page_location firing milliseconds apart.

Fix: remove the hardcoded snippet if GTM is meant to own GA4 entirely — the normal, recommended setup, with one system owning the tag. If the hardcoded gtag.js has a separate reason to stay (it's also serving a different destination's global site tag), add send_page_view: false to its config call and let the GTM-managed tag be the one that owns the pageview.

6. Is the GTM Container Snippet Itself Installed Twice on the Page?

The one that doubles everything, not just one tag. The head/body GTM snippet — the actual container ID, GTM-XXXXXXX — got pasted onto the page more than once: a developer hardcoded it in the theme and a plugin, an app embed, or a separate tag-management add-on injects its own copy of the same container. The dataLayer is shared across both loaded copies, so tags in either instance can also see pushes that were meant for the other.

The give-away that distinguishes this from causes #1–5: if your GA4 purchase tag, your remarketing pixel, and a third unrelated tag are all firing twice at once, on every page, a single duplicated container is a much more likely explanation than five separate, coincidental per-tag misconfigurations. When only one tag doubles, look at causes #1–5 first.

Check it: view source and search for GTM- — if the identical container ID appears in two separate script blocks, or DevTools Network shows two requests to googletagmanager.com/gtm.js on one page load, the container is loading twice. Worth checking specifically: a theme's own "Google Tag Manager ID" settings field running alongside a manually-pasted snippet in a custom code area; a Shopify app or WordPress plugin that ships its own GTM injection in addition to one a developer already added; a header/footer script manager or CMP with its own "paste your GTM ID" field, separate from the code already in the theme.

Fix: find and remove the redundant snippet. Only one copy of the container should ever load on a given page.

7. Is Tag Sequencing Firing It as a Setup Tag — And On Its Own Trigger?

The rarest cause here, and the one that looks the most like a GTM bug. Tag Sequencing lets any tag specify a setup tag (checkbox: "Fire a setup tag before <this tag> fires") or a cleanup tag ("Fire a cleanup tag when <this tag> is finished") under Advanced Settings → Tag Sequencing.

The nuance that causes the double fire: when Tag B is wired as Tag A's setup or cleanup tag, Tag B fires as part of that sequence regardless of Tag B's own trigger conditions — GTM ignores Tag B's own trigger for the sequenced fire and runs it purely because Tag A fired. What that doesn't do is disable Tag B's independent trigger for its other firing path. If Tag B also has a live trigger that separately matches on the same page or event, it fires twice: once through the sequence, and once entirely on its own account.

This most commonly bites teams who reuse an already-triggered tag as a convenient setup or cleanup tag for a new flow — a "consent check" Custom HTML tag that already had its own All Pages trigger gets wired as a setup tag for a new marketing pixel, and nobody pauses or narrows the original trigger.

Check it: open the tag suspected of double-firing. Confirm two things — does it have a Triggering condition that could plausibly match on its own, and is it also referenced as a setup or cleanup tag inside another tag's Advanced Settings → Tag Sequencing? If both are true, this is it.

Fix: a tag used purely for sequencing shouldn't rely on its own trigger — give it a trigger that can never legitimately match anything real, so the sequence is the only path that fires it. The only way to stop the sequenced fire itself is pausing the tag entirely; you can't exclude a tag from just the sequence while leaving it live everywhere else.

What a Tag Firing Twice Actually Costs You

Pageviews inflate. Engagement rate and average engagement time distort, because the denominator (sessions) and the numerator (engaged events) don't inflate at the same rate. And for any tag mapped to a GA4 key event, conversions and revenue double directly — GA4's deduplication on transaction_id only helps within a limited processing window (Google doesn't publish the exact duration) and only for the events it applies to; a BigQuery export receives both rows regardless, and non-purchase key events (leads, sign-ups) get no deduplication at all.

If the doubled tag is also imported as a Google Ads conversion action, paid-media bidding starts optimizing against a number that's roughly double the real one — Smart Bidding chases a target that doesn't exist. That's a distinct enough failure mode that we've written a full breakdown of every way Ads and GA4 conversion counts can diverge; read that guide if double-firing turns out not to fully explain your gap.

A duplicated tag firing a GA4 key event is also one of the three checks we run the moment a GA4 property and a GTM container are paired in the same workspace, because neither product's own audit can see it alone: GA4 only sees "two purchase events arrived," with no way to know that's wrong; GTM only sees "two tags are configured to fire the same event," with no way to know whether that's a bug or a legitimate coincidence. Cross-referencing both is the only way to catch it — the full mechanics, and the other two checks in that chapter, are in our GA4×GTM cross-check breakdown.

Catch duplicate tags before they double your reported revenue

NiceLookingData's GTM audit runs 44 checks against your live container, including a dedicated duplicate-GA4-configuration-tag check and a duplicate-trigger check. Connect a paired GA4 property and 3 additional cross-checks run — including the one that catches the specific case where two GTM tags are both firing the same GA4 key event. Read-only, never touches your live workspace.

Run the GTM Audit →

Confirm the Cause, Then Confirm the Fix

Checking seven possible causes one at a time is slow. In practice, this order gets you to the answer fastest, because each step rules out several others at once:

  1. Open GTM Preview mode, find the tag's two firing entries in the left-hand timeline, and open each one under Tags Fired — Tag Assistant names which trigger satisfied it. Two different triggers named → you're looking at #1 or #2 (an ordinary trigger overlap, or a Page View + History Change pairing).
  2. Same trigger named both times → the trigger itself is fine. The tag's firing option is letting one trigger's repeated match through uncapped — check Advanced Settings for #3 (Unlimited/Once per Event where Once per Page belongs) and #7 (whether it's also chained into another tag's Tag Sequencing).
  3. Preview shows only one fire, but GA4 DebugView or your reports still show two — the duplication isn't happening inside that GTM session at all. Open DebugView (GA4 Admin → DebugView) and compare the two events' parameters side by side: a byte-for-byte match, arriving seconds apart, points outside GTM entirely — a duplicate GA4 Configuration tag (#4), a hardcoded gtag.js (#5), or the whole container loading twice (#6). View-source is the fastest way to confirm any of the three: search for a second Measurement ID reference, a raw gtag( call outside GTM's injection, or a repeated GTM- container ID.
  4. Once you've found and removed the second firing path, publish, then re-run the same check — Preview and DebugView both — to confirm you're down to exactly one fire. Don't assume the fix worked just because you found a plausible cause.

Frequently Asked Questions

Why is my GTM tag firing twice?

Almost always because the tag has two independent, simultaneously-true paths to firing: two triggers on the same tag both matching one action, a Page View trigger stacked with a History Change trigger on a single-page app, a duplicated GA4 Configuration tag or GTM snippet on the page, or Tag Sequencing firing it as a setup/cleanup tag while its own trigger also matches. Open Preview mode and check which trigger fired it each time — that single check rules out most of the list immediately.

Does setting a tag to "Once per Page" always fix duplicate firing?

Only for causes where the duplication happens within that one tag's own trigger evaluation on a single page — overlapping triggers, a re-rendered SPA route, or a reloaded confirmation page. It does nothing for a duplicated GA4 Configuration tag, a hardcoded gtag.js, or a container installed twice, because each of those is a completely separate tag or script instance running its own "once per page" independently — Once per Page caps one tag, not the whole page's tracking surface.

Will GA4's built-in deduplication cover a tag that fires twice?

Partially, and only for specific cases. GA4 deduplicates on transaction_id for purchase-type key events within a limited window that Google doesn't publish an exact duration for — useful as a second line of defense, not a substitute for fixing the tag. It doesn't cover most other event types, a BigQuery raw export still receives both rows, and Google Ads conversion imports don't reliably apply the same logic — a doubled lead or sign-up event has no deduplication safety net at all.

How do I tell whether the duplicate is coming from GTM or from GA4 itself?

Run both checks together. Open GTM Preview mode and watch the tag under Tags Fired — if it appears once per real navigation there, GTM only ever asked it to fire once, and the second event is being created outside that GTM session entirely (a duplicate Configuration tag, a hardcoded gtag.js call, or two copies of the container). If Preview clearly shows the tag firing twice itself, with a named trigger each time, the cause is inside GTM's own trigger or sequencing configuration. GA4 DebugView is the tiebreaker either way: two events with identical parameters arriving seconds apart confirm a true duplicate rather than two legitimately different user actions.

Written by
Ludde Nyström — Founder, NiceLookingData

Analytics consultant turned founder. After years running the same GA4 and GTM audits across client engagements, Ludde built the audit into a product — so the pattern-matching takes a minute, not a meeting. More about Ludde →

Free tool

Check your GTM container.

Upload your GTM export or connect live. Our auditor checks 44 best practices and gives you actionable fixes.

Thanks for reading.