GA4 shows (not set) in source/medium when it received the hit but could not classify where the visit came from. It is not the same as direct / (none). Six causes account for nearly all of it: UTM parameters stripped by in-app browsers, Consent Mode blocking the cookies GA4 needs, an over-broad referral exclusion list, Safari and iOS privacy limits, a GTM tag firing before the URL resolves, and dark traffic that arrives with no referrer at all.
Each has a different fix, so the first job is working out which one you have. The dimension where (not set) appears is the clue. In session source/medium but not first user source means a session-level problem, usually consent or a referral exclusion. In both means the data collection layer.
That is the diagnosis, and it takes about an hour. The harder question, and the one this article is really about, is what to do when the diagnosis comes back and the cause turns out to be something you have no authority over.
The newsletter
Join our KISS newsletter
One short read a week on what actually moves revenue, in a free email. Read by 10,000+ operators and founders.
No spam. Unsubscribe in one click.
I.It is a classification failure, and its address names the cause
(not set) is not missing data. The hit arrived and GA4 declined to label it, which is a much more informative failure than an absence.
A.Why it is not direct / (none)
Direct / (none) is a verdict. GA4 saw the hit, looked for a referrer and campaign parameters, found neither, and classified the visit as direct. That is an expected outcome and a share of every site’s traffic is legitimately in it.
(not set) is the absence of a verdict. The event was collected, and at the moment GA4 tried to attach a source dimension to it, the input it needed was not there. The distinction matters because (not set) indicates a data collection problem while direct / (none) is an expected classification. Treating them as interchangeable leads to misdiagnosis, usually in the direction of blaming a channel for underperforming when the channel is fine and the labelling is broken.
The useful consequence is that the dimension it lands in tells you which layer failed. Source data enters GA4 at two moments: at collection, when the tag reads the URL and the referrer, and at session start, when GA4 decides whether this visit begins a new attributed session. A problem at the first moment poisons every dimension, including first user source, because the raw input never existed. A problem at the second moment leaves first user source intact and corrupts only the session dimensions, because the original acquisition was recorded correctly and this particular visit was not.
B.The six causes, and which layer each one lives in
Three causes sit upstream of GA4 entirely. UTM stripping is the most common: Meta’s in-app browser, TikTok’s webview and LinkedIn’s mobile app all rewrite outbound URLs in ways that drop or corrupt parameters, and redirect chains in your own stack, link shorteners and landing page tools, finish the job. Test by clicking your own ads on a phone and reading the address bar. UTMs that work on desktop and break on mobile is the standard finding, and mobile is where social ad traffic lands. iOS and Safari privacy features cap first-party cookie lifetimes and mask referrers on some traffic, so returning Safari users lose their original attribution. Dark traffic from native apps, email clients and messengers arrives with no referrer header at all, and the behaviour changes with OS updates.
Three sit inside your own configuration. Consent Mode stops GA4 setting the cookies it needs when a user declines analytics storage; the page view still fires as a cookieless ping, with nothing to attach source data to. An over-broad referral exclusion list tells GA4 to ignore referrals from domains that send you real traffic, which is easy to do in a multi-domain setup. And a GTM configuration tag that fires before the page URL resolves, or on a virtual pageview without the original URL passed through, destroys the source before GA4 ever sees it. Single-page app routing and custom history change triggers are the usual culprits, and a GTM preview that disagrees with your reports is often the first sign.
Where (not set) concentrates, and what that implies
Campaign performance view| Concentrated in | Most likely cause | First thing to check |
|---|---|---|
| Mobile sessions only | UTM stripping in in-app browsers | Click your own ads on a phone, read the address bar |
| One region or one browser | Consent denials, Safari ITP | Consent acceptance rate for that region |
| Session source but not first user source | Referral exclusion list | Domains on the list that send you real traffic |
| Every dimension at once | Tag firing before the URL resolves | GTM publish history against the spike date |
II.Diagnosis is cheap. Half the causes have no fix
The sequence that identifies the cause takes an hour. What it usually identifies is something outside your control, which is why the number resists a year of settings changes.
A.The hour that names it
Work the sequence rather than guessing, because each step eliminates a group. Start by quantifying: Reports, then Acquisition, then Traffic Acquisition, with Device category as a secondary dimension, filtered to (not set). Overwhelmingly mobile points at UTM stripping or iOS privacy. Spread evenly across devices points at consent or the container.
Then read the time shape, because the shape distinguishes a deploy from a drift.
Share of sessions landing in (not set), by day
Activity report viewWith the shape in hand, two tests settle it. DebugView, visited through search, social, email and direct in turn, shows whether page view events arrive carrying the expected parameters; if they do not, the loss is upstream of GA4 and no GA4 setting will recover it. If they arrive correctly and the reports still show (not set), the loss is in GA4 processing, which means attribution settings or data thresholds. Server logs are the definitive version of the same test: compare referrer headers and query strings as received against what GA4 reports, and the boundary where the data disappears is exact.
B.And what it names is usually not yours to fix
The three configuration causes are genuine bugs and they close permanently once found. The three upstream causes do not close at all, because none of them is a mistake anyone made. They are the current behaviour of browsers, platforms and privacy law.
In regions where consent acceptance runs below 50%, Consent Mode alone can push (not set) above 30%, and no GA4 configuration reduces that without compromising the compliance the consent banner exists to deliver. The Safari limit is policy set by a browser vendor. The missing referrer from a native app is a decision made by the app. You can improve UTM hygiene at the margins, and you should, but the parameters are stripped by an intermediary you do not operate.
One cause is newer and structurally unfixable by UTM. Visits that begin inside ChatGPT, Claude, Gemini or Perplexity are a growing slice of the bucket. Some send a recognisable referrer. Some send nothing, and the desktop apps behave like any other native application. You cannot tag those links because you did not place them, so the only route to sizing that traffic is classification at the collection layer, from the referrer plus the landing URL fingerprint, before any channel grouping runs.
This is the real cost of the (not set) bucket, and it is not the missing label. It is that the unclassifiable share is not distributed evenly. It concentrates in mobile social, in privacy-strict regions, in Safari, and in whichever channels happen to be newest. Every channel comparison you run is therefore biased against exactly those, and the bias grows as they grow.
III.What to do about the part that will not go away
Two responses, and they are not alternatives. Contain the fixable share with process, then stop depending on the mechanism that produces the floor.
A.Contain the share that is yours
The configuration causes recur, because containers get published and domain architectures change. Four habits keep them from creeping back. Put a validation snippet on landing pages that logs when UTM parameters are present in the referrer and absent in the landing URL, which catches stripping as it happens rather than in a monthly report. Verify your top campaigns by spend across desktop, iOS and Android on a schedule, not after a spike. Review the referral exclusion list against your actual domains quarterly and delete anything that sends legitimate traffic. And describe every GTM publish, so a step change can be matched to a container version in minutes rather than reconstructed from memory. Our campaign tracking best practices covers the naming discipline underneath all of that, and the GA4 accuracy audit puts it in a checklist.
Monitor consent acceptance weekly while you are at it, not because you can move it much, but because it is the leading indicator for the floor. When it falls, (not set) rises with a lag, and knowing that in advance is the difference between a diagnosis and a panic.
B.Then stop depending on reconstructing a source per visit
The floor exists because of a specific design decision: GA4 works out where a visit came from at the moment the visit happens, from whatever survived the click, and stores the answer against a cookie. Every one of the three unfixable causes attacks one of those three dependencies. Strip the parameters and the input is gone. Deny consent and the cookie is gone. Send no referrer and there was never an input to begin with.
The alternative is to attach the source to a person rather than to a visit, and to classify at collection rather than at report time. A first-party identity that persists across visits means the acquisition source recorded once stays attached through later visits that carry no referrer at all, which converts the recurring loss into a one-time one. Classifying at the collection layer means a visit from an assistant is labelled from the referrer and landing URL before any channel grouping can bucket it as direct, which is what the LLM Acquisition report does, and it separates real people arriving from an assistant from the crawlers the same assistants run. Downstream, Campaign Performance and Funnels then read from that same identity instead of re-deriving a source per session. Our privacy-first analytics guide covers the consent plumbing that has to sit underneath it.
This is not a claim that identity removes the problem. Consent still gates storage, and a visitor who never identifies themselves anywhere is still unattributed. It shifts what the loss depends on: from surviving a redirect chain and a cookie policy on every single visit, to being recognised once. That is a materially better bet, and it is the only one available that does not require a browser vendor to change its mind.
Verdict
Spend one hour, not one quarter. Split the bucket into the part that stepped on a date and the part that has been flat, fix the stepped part, and then stop optimising. The flat part is not a misconfiguration you have failed to find. It is the sum of a browser cookie policy, a consent framework you are legally obliged to honour, and intermediaries who rewrite your links, and there is no GA4 setting behind which it is hiding.
What matters after that is not shrinking the number but distrusting it correctly. The unattributed share is concentrated in mobile social, in privacy-strict regions, in Safari, and in traffic from AI assistants, so every channel report you read is systematically unkind to those and generous to email, branded search and direct. Publish the (not set) share next to any channel comparison you act on, treat any budget decision within that margin as unsupported, and put the effort you were spending on settings into an identity layer that does not need to rebuild the answer on every visit.
One analytics idea a week
Short, specific, written by the team building the product. No digest, no roundup.
This is part of GA4 problems and how to fix them, under attribution that does not add up. The guide puts the rest of the pieces in order.
Continue Reading
Campaign Tracking Best Practices: From UTM Parameters to Revenue Attribution
Consistent campaign tracking is the foundation of marketing analytics. Without proper UTM parameters and tracking, every attribution model is built on unreliable data. Here is how to get it right.
Read articleHow to Audit GA4 for Data Accuracy (And What to Do When the Numbers Don't Add Up)
If you have ever compared GA4 numbers to your backend and found a 20-40% gap, you are not alone. This guide provides a systematic audit process to identify where your data is leaking and what to do about it.
Read articleGA4 Traffic Dropped Suddenly? Here's a Systematic Diagnosis Guide
A sudden traffic drop triggers immediate panic. But before assuming the worst, you need a systematic diagnosis process. Most drops have a technical cause that is fixable once identified.
Read article