The symptom is easy to recognise and easy to misdiagnose. Sessions look fine, page views are roughly double, and the conversion rate has halved without anything changing on the site. Somewhere, one page load is sending two hits.
Almost every answer to this says the same thing: open DevTools, filter the network on
collect, reload, and count the page_view requests. That is right, and it is
incomplete in one way that matters.
Counting the hits is not enough
Two hits are only a duplicate if they went to the same property. The measurement ID
travels in tid, and a page that sends two page views to two different IDs is not broken —
it is a site running a second property for an agency, a regional rollout, or a migration that has not
finished.
So the question is never "how many hits", it is "how many hits per tid". Read the ID on
each one before concluding anything. Tag Master compares the event and the account rather than
only counting, and badges the second hit DUPLICATE; DevTools gets you there too, once you
know what to look for.
The four setups that cause it
- gtag.js on the page and a GA4 tag in GTM, same ID. The most common one by a distance. A plugin, a theme option or Site Kit writes the snippet, and the container also configures the property. Both send the page view.
- Two tags inside one container. A Google tag and an older GA4 Configuration tag for the same ID, both firing on All Pages. Preview Mode shows both firing and reports it as healthy, because it is: two tags fired, exactly as configured.
- Two containers. One in the theme, one added by a plugin or a tag manager migration, each carrying its own copy of the same GA4 tag.
- A history change on a single-page app. Enhanced measurement's page view on history change, plus a manual page view tag on the same route change. This one produces two hits only on in-app navigation, which is why it survives testing on the home page.
Telling them apart
The four look different on the wire, and that is what identifies them without touching the setup:
- Both hits carry the same
tidand arrive within milliseconds on the first load — a snippet and a container tag, or two tags in one container. - Both hits carry the same
tidbut each has a different_svalue in the same session — two separate initialisations, so two containers or two snippets. - The second hit only appears after clicking an in-app link — a route change firing twice.
- A
purchasewith the sametransaction_idarriving twice minutes apart — not a tagging duplicate at all, but a page somebody reloaded.
Fixing it, in the right order
Remove the duplicate configuration, not the tag you happen to find first. If the site uses a container for anything else, keep the container and remove the on-page snippet; if the container exists only for GA4, the reverse is simpler. What you must not do is remove both and check later.
Then load one page and count again, per tid. A fix that is not verified against the
requests is a guess, and this is a bug that hides well: it will not show in the tag setup, and it will
look perfectly healthy in Preview Mode, which is
a category of bug Preview Mode structurally cannot
report.
Questions
How do I know if GA4 is double counting?
Load one page and look at the /g/collect requests it sends. Two page_view hits carrying the same tid is a duplicate. Two hits with different tid values are two properties, which is a normal setup.
Can I have gtag.js and GTM on the same page?
Yes, and plenty of sites do it deliberately. What breaks is having both configure the same measurement ID, because then both send the page view. One ID, one place that configures it.
Why does my purchase event fire twice?
Usually the thank-you page is reachable twice — a reload, a back-navigation, or a single-page checkout that re-renders. The hits are identical including transaction_id, which is also what lets GA4 deduplicate them if the ID is actually set.
Does the duplicate show up in DebugView?
Often not clearly, because DebugView shows events after GA4 has processed them and the two hits arrive within the same session and second. Reading the requests as they leave the browser is unambiguous.
The rest of this group: GA4, server-side and attribution
- Debugging GA4 when DebugView shows nothing
- How to debug server-side GTM
- Google Tag Gateway: checking that it actually works
- When GA4 says the traffic came from somewhere else
More in GA4, server-side and attribution
Try it on your own site
Tag Master is free, needs no account, and collects no data.
Add to Chrome — Free