A client once showed me a GA4 report where "Direct" was their biggest revenue channel, right after they had doubled their Meta budget. Nobody had suddenly started typing their URL from memory. The paid clicks were real; GA4 had simply lost the information that told it where those visitors came from. When paid traffic shows up as Direct, Unassigned or (not set), your channel reports become useless for budget decisions. This guide explains why it happens and how I fix it, step by step.
Why does paid traffic show as Direct, Unassigned or (not set) in GA4?
Paid traffic lands in the wrong bucket when GA4 receives a session without a usable source, medium or click ID, or when the values it receives do not match any of its channel rules. The three labels mean different things, and each points to a different kind of problem:
| Label | What GA4 is telling you | Most likely cause |
|---|---|---|
| Direct | The session arrived with no referrer, no UTM parameters and no click ID | Click IDs or UTMs stripped by redirects, apps or consent banners |
| Unassigned | GA4 has source/medium data but no default channel rule matches it | Non-standard utm_medium values, or events without a session |
| (not set) | A dimension has no value for that data | Google Ads not linked, missing session_start, server events without session data |
Before fixing anything, look at the Traffic acquisition report with Session source / medium and Session campaign added as dimensions. The raw source and medium usually reveal the cause within minutes.
How does GA4 decide which channel a session belongs to?
GA4 assigns each session to a channel using the default channel group, a fixed set of rules based on source, medium, campaign name and click IDs. You cannot edit those rules. You can only send values that match them, or build a custom channel group for your own reports.
The rules that matter most for paid traffic:
- Paid Search: the source matches a known search engine and the medium matches the paid pattern (
cpc,ppc,retargeting, or anything starting withpaid, or containingcp). Google Ads clicks with auto-tagging qualify through the click ID. - Paid Social: the source matches a known social site (such as
facebook,instagram,tiktok) and the medium matches the same paid pattern. - Organic Social: the source matches a social site, or the medium is a social value like
social, without a paid medium. - Paid Other: the medium is paid, but the source is not a recognised search, social, video or shopping site.
- Direct: the source is
(direct)and the medium is(none)or(not set). - Unassigned: nothing else matched.
Google publishes the full list of conditions in its default channel group help article, and it is worth reading once. The practical lesson is that GA4 expects standard values. The rules are not case sensitive, but they are strict about wording, so inventive labels break channel assignment.
How do UTM mistakes cause Unassigned traffic?
UTM mistakes cause Unassigned traffic because a utm_medium value GA4 does not recognise falls through every rule. These are the patterns I find most often in audits:
| What was used | What GA4 does | Use instead |
|---|---|---|
utm_medium=facebook_ads with utm_source=facebook |
Organic Social (medium is not a paid value) | utm_medium=paid_social or cpc |
utm_medium=fb with utm_source=meta |
Unassigned, if neither value matches a rule | utm_source=facebook, utm_medium=paid_social |
utm_medium=boost with utm_source=facebook |
Organic Social, so paid boosts look free | utm_medium=paid_social |
utm_medium=whatsapp_blast |
Unassigned | A consistent value you map in a custom channel group |
Only utm_campaign, no source or medium |
Unreliable channel assignment | Always include source, medium and campaign |
In Meta Ads, set your URL parameters once at the ad level, using Meta's dynamic placeholders for campaign and ad names, and keep the source and medium fixed. I use utm_source=facebook&utm_medium=paid_social for Facebook and Instagram, so it maps cleanly to Paid Social. My free UTM builder creates consistent links so the team does not invent new values each month.
Never add UTM parameters to Google Ads final URLs when auto-tagging is on, unless you have a specific reason. The gclid already tells GA4 everything it needs, and mixed signals make reports harder to read.
How do redirects and stripped click IDs cause Direct traffic?
Redirects cause Direct traffic when they drop the query string, so the landing page loads without gclid, fbclid or UTM parameters. Without those, and often without a referrer, GA4 has nothing to attribute and records the session as Direct.
Where I usually find stripped parameters:
- HTTP to HTTPS or
wwwredirects configured at the server or CDN without passing the query string. - Link shorteners, booking widgets and landing page builders that forward to the main site.
- Country or language redirects that send visitors to a localised URL.
- Single-page app routing that rewrites the URL before the Google tag reads it.
- In-app browsers in Facebook and Instagram, which sometimes do not pass a referrer, so missing UTMs hurt even more.
To check, click a real ad (or paste the final URL with a test gclid) and watch the address bar after every redirect. My free click ID checker helps confirm whether gclid, gbraid, wbraid or fbclid survives to the landing page. If it disappears, fix the redirect rule so it preserves the full query string.
Why do Google Ads clicks show (not set) campaigns?
Google Ads clicks show (not set) campaigns when GA4 sees the gclid but cannot pull the campaign details from Google Ads, usually because the accounts are not linked or auto-tagging is off. Work through these settings:
- In Google Ads, confirm auto-tagging is on in the account settings.
- In GA4, open Admin > Product links > Google Ads links and confirm the right Google Ads account is linked.
- If you use a manager account, confirm the link covers the client accounts that actually spend.
- Check that the landing page keeps the
gclid(see the redirect section above). - Allow some time after linking. Data recorded before the link may stay as
(not set).
If the campaign is set but conversions do not match between platforms, that is a different issue. I explain it in why GA4 and Google Ads show different conversion numbers.
How does consent mode affect paid traffic attribution?
Consent Mode affects attribution because when visitors decline analytics or ad cookies, GA4 cannot store identifiers that link a later page view or purchase back to the ad click. With advanced consent mode, Google tags send cookieless pings, and GA4 may use behavioural modelling to fill gaps in some reports if your property is eligible.
Problems I see often:
- The banner blocks the Google tag until consent, so the first page view, the one with the
gclid, never fires. If the visitor consents on page two, the click ID is already gone from the URL. url_passthroughis not enabled, so click information is not carried through internal links while consent is pending or denied.- The consent default is set too late, after tags have already fired.
The fix is to set consent defaults before any tag fires, update consent on the same page when the visitor accepts, and consider enabling url_passthrough. My Consent Mode v2 guide covers the full setup, and the Consent Mode v2 generator gives you a starting snippet.
How do payment gateways and cross-domain journeys break attribution?
Payment gateways and other domains break attribution when a visitor leaves your site and returns, starting a new session credited to the gateway as a referral, or losing the original source. In Bangladesh, I see this with payment pages like SSLCommerz or bKash; elsewhere it is often PayPal, Stripe Checkout or a separate booking domain.
To fix it, in GA4 go to Admin > Data streams > your web stream > Configure tag settings:
- Under Configure your domains, add every domain you own that is part of the journey, so GA4 passes its linker parameter between them.
- Under List unwanted referrals, add the payment gateway domains, so their return visits do not overwrite the original source.
- Test a real journey and confirm the purchase is credited to the original campaign.
My guide to GA4 cross-domain tracking covers the linker and testing in more detail.
Why do Measurement Protocol and server events show as Unassigned?
Measurement Protocol and server-side events show as Unassigned or (not set) when they arrive without the client_id and session_id of the browser session they belong to. GA4 then cannot attach them to an existing session, so they have no source.
If you send purchases from a backend, webhook or CRM, capture client_id and session_id in the browser (from the _ga cookies or the Google tag), store them with the order, and include them in the Measurement Protocol request. Send events soon after they happen. Measurement Protocol is designed to supplement browser data, not to create attributed sessions on its own.
Final thoughts
Paid traffic hiding in Direct or Unassigned is almost always fixable: standardise UTMs, protect click IDs through redirects, link Google Ads, configure consent and cross-domain settings correctly, and send server events with session IDs. Clean attribution is part of every advanced conversion tracking project I take on. If your channel report does not match your ad spend, book a free tracking audit.

