TRACKING SPECIALIST — BARIS ASA · LONDON
Synctag
Start the check → TRACKING SPECIALIST — BARIS ASA · LONDON
F-602
F-602 · CONFIGURATION & DATA INTEGRITY · FILED 2026 · REVISED 3 NOV 2026 · FREQ ▮▮▮▮▮

Internal & bot traffic counted

Also filed as “how to exclude internal traffic in GA4”“GA4 internal traffic filter not working”“GA4 bot traffic not filtered”“exclude my own visits from GA4”“staging site traffic showing in GA4”“GA4 developer traffic filter debug mode”

To exclude internal traffic in GA4, list your office and agency IP addresses under Define internal traffic on the web data stream, then set the Internal Traffic data filter to Active. A filter left in Testing excludes nothing. Known bots are excluded automatically. Other scripts that run your tag are counted: stop them before the tag, or mark them and filter them. GTM Preview and staging sites need their own filters. Filed as F-602.

Symptom and cause

Symptom
Sessions look healthy until you realise a chunk of them are you: the office, the dev team, the agency, and a swarm of bots dressed as customers.
Cause
Internal-traffic filters never defined or left sitting in "testing"; staging and preview domains feeding the production property; known-bot exclusion assumed to catch what it doesn't.
Where it's caught
Geography reports starring the office's city; conversion spikes that match deploy days; the hostname report listing staging URLs.

How GA4 excludes internal and bot traffic, and what gets through

GA4 counts every hit your tag sends. It cannot tell a customer from your own team. It gives you four controls, and each one catches only its own kind of traffic. F-602 is a gap in one or more of them.

Internal traffic: a rule, then a filter. Most properties I open have the rule. Fewer have the filter switched on. The rule sits on the web data stream (Admin → Data collection and modification → Data streams → your website). It adds a label called traffic_type, internal by default, to every event that comes from an IP address you listed. On its own that changes nothing in your reports. The filter does the excluding: an Internal Traffic data filter, set to Exclude, matching one traffic_type value. A data filter has three states. Testing marks matching events in a Test data filter name dimension you can see in Explore, and still counts them. Active removes them. Inactive does nothing. The exhibit below is the Testing version: the filter exists and has excluded nothing. Google allows 10 data filters per property, and each takes 24 to 36 hours to start working.

Filtering is permanent and only works forwards. Events excluded while a filter is Active are never processed, so they are not in your reports or your BigQuery export, and switching the filter off later does not bring them back. Nothing collected before it went Active is cleaned. It covers websites only: Google says internal traffic cannot be filtered for app users.

An IP rule only sees the addresses it lists. The office line is easy. Everyone else is not. Staff at home, the agency and a developer on a phone hotspot arrive from addresses an office rule never sees, and home broadband addresses change. Google lets you set traffic_type yourself, so the tag can mark a known staff browser as internal without relying on its IP. A first-party cookie set from a private URL is one way to do it.

Developer traffic: GTM Preview and Tag Assistant switch on debug mode, GA4's flag for test sessions, and those sessions land in the production property. The Developer Traffic filter removes events sent in debug mode. Check one thing before you activate it. If debug_mode was set on the Google tag for every visitor, the filter removes every visitor. Setting it to false does not switch it off; the field has to be removed.

Staging and copies of the site: staging, preview and local builds often share the production measurement ID. The web hostname filter (Web hostname traffic in the filter menu) can Exclude the test hostnames, or Include only a list of real ones. Include only drops every hostname you forgot to list, so it needs the full list first.

Bots: Google excludes known bots and spiders automatically, using its own research and the IAB's International Spiders and Bots List. You cannot turn that off and you cannot see how much it removed. A crawler that does not run JavaScript never sends a GA4 hit at all. What gets counted is automation that runs your tag and is not on the list: headless browsers (scripts that load your site like a person would), uptime and test scripts, scrapers, and new bots the list has not caught up with. GA4 has no bot filter you can configure for those. They are stopped before the tag, marked with traffic_type and filtered, or separated in reports.

One thing looks like this fault and is not: a real spike from your own city after a local campaign. The tell is behaviour, not location. Internal and automated sessions pile onto one landing page and one browser with near-zero engagement, often on deploy days.

GA4 sessions by source of non-customer traffic · one ecommerce property, 30 days · reconstructed · client data anonymised
TrafficShare of sessionsGA4 controlStatus
Office and agencyabout 6%Internal Traffic filterTesting: labelled, still counted
staging. hostnameabout 3%Web hostname filternone set up
Uptime and test scriptsabout 2%none in GA4counted
Known crawlersnot shownAutomatic bot exclusionremoved by Google

How to catch it

  1. (Anyone with GA4 access, no tools) Start here: it is the quickest check. Open Admin → Data collection and modification → Data filters and read the state of each filter. No Internal Traffic filter, or one in Testing or Inactive, means your own visits are still counted. Open the filter and note the traffic_type value it matches.
  2. (GA4 Editor) Open Data streams → your website → Configure tag settings → Show more → Define internal traffic. Every rule's traffic_type value must be the one the filter matches. A rule labelled office_london and a filter matching internal exclude nothing. Then compare the listed addresses with the public IP of the office, the agency and the people working from home.
  3. (Anyone with report access) If a filter is in Testing, build a free-form exploration in Explore with Test data filter name and Event name as rows and Event count as values. Empty after 36 hours usually means the rule is not matching: the IP is not listed, the values differ, or a VPN, a corporate proxy or a server container that does not forward the visitor's IP changes the address GA4 sees.
  4. (Anyone with report access) In the same exploration, swap in Hostname as rows and Sessions as values for the last 90 days. A staging, dev, localhost or preview hostname is test traffic in the production property. Keep a note of every hostname real customers use as well (checkout, translation, regional domains) before anyone builds a hostname filter.
  5. (Whoever owns GTM) Open the Google tag and look for a debug_mode field. If it is set for all visitors, activating the Developer Traffic filter would remove every visitor. Remove the field first, then filter.
  6. (Anyone with report access) Look for automation the bot list misses. Add City, Browser, Landing page and Engagement rate. Sessions packed into one landing page and one browser with engagement near zero, arriving in bursts or on deploy days, are scripts. Your server or CDN logs will show the same requests with their user agents.

What putting it right involves

  1. (GA4 Editor or above) Define internal traffic per location: one rule per office or agency network, using CIDR ranges (a whole block of addresses written as one entry) where it has more than one address, IPv6 included. Keep the traffic_type value internal on every rule, so one filter covers them all. Separate values per location need a filter each, out of the 10 allowed.
  2. (Whoever owns GTM) Cover the people an IP rule cannot. Set traffic_type to internal on the tag for marked staff browsers, for example from a first-party cookie set by visiting a private URL. Stop your own uptime and test scripts at the source with a trigger exception on their user agent, or point them at a page without the tag.
  3. (GA4 Editor or above) Create the Internal Traffic data filter as Exclude, in Testing. After 24 to 36 hours, check the Test data filter name exploration shows only your own traffic. Then set it to Active. Data excluded while it is Active is gone for good, so that check matters.
  4. (GA4 Editor or above) Add the Developer Traffic filter once debug_mode is off for the public. For staging, a web hostname filter set to Exclude the test hostnames is the safer choice; Include only drops any real hostname you did not list. Test both the same way. Better still, give staging its own measurement ID so the hits never arrive.
  5. (Whoever owns bot protection) For automation that is not yours and not on the list, block it before the page loads with your CDN's bot controls, then rerun the last diagnostic check to confirm the bursts have stopped. If you cannot tell people from bots yet, label suspect sessions and compare rather than delete: the evidence is what tunes the rule.
  6. (Whoever owns reporting) Record the date each filter went Active and the share of sessions it removed. Every chart that crosses that date will show a drop that is not a drop. Note it on the dashboard and in the measurement plan (F-501).
How I'd fix this

Sources on file

Cited in these case files

F-602 turns up as evidence across the archive. It is cited in:

Questions on this file

How do I exclude internal traffic in GA4?

Two steps. Define the IP addresses on the web data stream (Configure tag settings → Show more → Define internal traffic), which labels their events with traffic_type internal. Then create an Internal Traffic data filter set to Exclude, test it, and switch it to Active. Until it is Active, nothing is excluded.

Does GA4 filter out bot traffic automatically?

Known bots, yes. Google excludes them using its own research and the IAB International Spiders and Bots List, and you cannot turn that off or see how much it removed. Automation that runs your tag and is not on the list, such as headless browsers, test scripts and new bots, is counted. Find it by behaviour (one landing page, one browser, near-zero engagement), then stop it before the tag or label it and filter it.

Why is internal traffic still showing in GA4 after I set up the filter?

Usual reasons: the filter is still in Testing; it went Active less than 36 hours ago; the rule's traffic_type value is not the one the filter matches; the IP rule does not match the address your team actually uses, common for home workers, agencies and VPNs; or you are looking at dates before the filter went Active, which it never changes.

How do I exclude staging or dev site traffic from GA4?

In Admin → Data collection and modification → Data filters, create a Web hostname traffic filter set to Exclude your staging hostnames, test it, then activate it. Include only your live hostnames also works, but drops any real hostname you forget, such as a checkout or translation domain. The cleaner fix is a separate measurement ID for staging.

Can I remove internal traffic from data GA4 already collected?

No. Data filters only apply from the moment they are active and do not change historical data. For older dates, hide it at report level with a report filter or a comparison on the traffic you can identify, and note the date the filter went live.

How do I exclude staff who work from home from GA4?

An IP rule cannot follow a home broadband address that changes. GA4 lets you set the traffic_type parameter yourself, so GTM can mark a staff browser as internal, for example from a first-party cookie set by a private URL. Use the value internal, and the same Internal Traffic filter excludes it.

Does GTM preview mode count in GA4 reports?

Yes, unless you filter it. Preview and Tag Assistant send hits in debug mode to the same property. The Developer Traffic data filter removes them. Check first that debug_mode is not set on the Google tag for every visitor, or the filter removes everyone.