AnalyticScan
KO
← All posts

27 October 2026·4 min read

When development and staging traffic mixes into production

Hostname shows localhost and vercel.app, and sessions spike only on release days. When development shares a measurement ID with production, the checkout flow your QA team walked lands in your revenue. Why the volume matters less than the shape, and how to separate environments.

GA4GTMSettingsChecksTG-02

Symptom

Expand hostname in a report and, under your production domain, there is localhost, a preview deployment address (*.vercel.app, *.netlify.app), or something starting with staging. or dev.. Sessions spike on the days you shipped and drop back the day after.

The worse symptom shows up in revenue. On the day QA ran the checkout flow ten times, GA4 has ten purchase events that your order system has never heard of. You sit down to explain why GA4 revenue disagrees with real revenue and discover the cause was your own team.

Cause

Development and staging are using the same measurement ID as production. GA4 has no idea which environment an event came from; wherever the tag is loaded, it collects. These are the routes it usually takes.

How it mixes in What it leaves in hostname
The measurement ID is hardcoded, so every environment sends the same one Every non-production domain
Preview deployments built per pull request carry the production tag *.vercel.app, *.netlify.app
A dev server left running while a feature is checked locally localhost, 127.0.0.1
One GTM container shared across environments with no separation All staging domains
QA repeats checkout scenarios on a staging site carrying the live tag staging., test.

AnalyticScan looks at the session share per hostname. The patterns it treats as non-production are localhost, addresses starting with 127., hosts ending in .vercel.app or .netlify.app, and hosts starting with staging., dev. or test.. Above 0.5% of sessions it warns, above 2% it counts against the score.

If 0.5% sounds strict, it is because the problem with this traffic is its shape, not its volume. Ordinary visitors look at a page or two and leave; developers and QA walk the conversion path over and over, on purpose. Traffic that is one percent of sessions can be a far larger share of key events such as purchase or generate_lead. Your visitor count is off by one percent while your conversion rate and revenue are off by much more.

How to check in GA4

1) Split by hostname. Put hostname on the rows of an exploration and count sessions. What exists besides your production domain, and at what percentage, fits on one screen.

2) Recount key events by hostname. Add purchase or your form submission event to the same table. If the event share is much larger than the session share, the non-production traffic is landing exactly where it hurts.

3) Line the dates up with your release schedule. Break the non-production sessions down by day and they usually cluster. Matching those days against releases and QA cycles narrows down whose traffic it is immediately.

How to fix it

A different measurement ID per environment is the only reliable answer. Inject the measurement ID from an environment variable and, outside production, either leave it empty so the tag never loads or point it at a development property. Turning one hardcoded ID into an environment variable is a thirty-minute job in most codebases. With GTM, container environments or an environment-aware variable does the same work.

If you cannot ship today, filter as a stopgap. Register the development IPs under Admin → Data Streams → Configure tag settings → Define internal traffic, then set that filter to active under Admin → Data collection and modification → Data filters. It is IP-based, so it misses remote and mobile connections, and a filter left in testing removes nothing — that trap had an article of its own.

Local debugging can also be caught by the developer traffic filter. GA4 data filters come in a developer traffic type as well as internal traffic, and it excludes events arriving with debug mode on. That suits a local environment you debug in; it does nothing for a staging server running normally without debug mode.

Test purchases leave a mark. Fake orders already collected are not removed by a filter. Nothing is retroactive, so analysing past periods means reading them through a segment that excludes the non-production hostnames.

In one line

Development traffic breaks your most expensive numbers with very little volume. One look at the hostname dimension settles it in five minutes, and the real fix is not a filter but a different measurement ID per environment.

Related posts