How to Fix GA4 (not set) Source/Medium & Unassigned Traffic
Lately, we've been asked to investigate a lot setups where major portion of the traffic is not being assigned to any source/medium.
What Unassigned means?
In Google Analytics 4, Unassigned traffic means GA4 successfully recorded the user’s visit, but it could not match the event’s traffic source parameters to any rule in its Default Channel Grouping.
Unlike (not set) - which usually means a parameter was entirely missing, unassigned traffic means GA4 did get source/medium data, but it didn't fit into GA4's pre-defined categories (like Paid Search, Organic Social, Direct, or Email).
GA4 uses strict, rule-based logic to categorize incoming traffic based on utm_source, utm_medium, and utm_campaign. If those parameters fall outside GA4's recognized syntax, or if critical session events fire out of order, the traffic gets dumped into the Unassigned bucket.
What (not set) means?
In Google Analytics 4, (not set) is a system placeholder that means GA4 failed to receive or process information for a specific dimension. In terms of dimensions, this could mean:
- 1. Session source / medium = (not set) - GA4 recorded a session, but it could not determine how the user arrived on the site.
- 2. Landing page = (not set) - A session took place, but GA4 never registered an initial page load for that session.
- Custom Dimensions = (not set) - You registered a Custom Dimension in GA4 Admin (e.g., user_type or author_name), but the incoming event didn't contain that event parameter.
Why this happens?
A sudden increase in unassigned, (not set), or (direct) / (none) transactions across multiple clients using GTM and GA4 usually stems from broken session continuity, tag execution timing, or payment gateway redirects.
Missing Unwanted Referral Exclusions (Payment Gateways)
Cause:
When a customer is redirected to an external payment provider (e.g., PayPal, Stripe, Klarna, regional gateways) and returned to the order confirmation page:
- If the payment domain isn't in GA4's Unwanted Referrals list, GA4 treats the return visit as a new session driven by the payment processor as a referrer.
- If referral headers get stripped during HTTPS/HTTP cross-domain redirects, GA4 falls back to (direct) / (none) for the purchase event.
Fix:
- In GA4: Admin > Data Streams > [Web Stream] > Configure Tag Settings > List Unwanted Referrals. Add all third-party payment gateway domains (e.g., paypal.com, checkout.stripe.com).
Consent Mode v2 & Tag Firing Order Race Conditions
Cause:
GA4 event tags (like purchase or page_view) fire on early triggers before the main Google Tag updates the consent state or initializes the session. If an event tag fires without a valid session context established by the Google Tag, GA4 records the purchase without session attribution parameters, resulting in (not set) or Unassigned.
Fix:
- Ensure the Google Tag fires on Consent Initialization - All Pages or Initialization - All Pages.
- Verify that purchase and other GA4 event tags fire after consent is granted, or use a Trigger Group pairing the purchase trigger with the consent update event.
Server-Side GTM (sGTM) Mismatches & Dual Initialization
This applies for clients that are using sGTM (Server-Side Google Tag Manager)
Cause:
Web tags use the browser's _ga cookie, while server-side events rely on FPID. If some web requests bypass the server endpoint while others go through sGTM, GA4 treats them as two completely separate users, stripping the original acquisition source from the server-fired purchase.
Also third-party app plugins or hardcoded gtag() snippets on the thank-you page can re-initialize GA4 without the server_container_url parameter, severing session continuity.
Fix:
Inspect the browser Network tab on the thank-you page:
- Filter for v=2 or your GA4 Measurement ID.
- Ensure all requests route exclusively to your sGTM custom domain (or web endpoint) and that no native client scripts fire secondary calls to google-analytics.com.
Measurement Protocol Purchases Without session_id
Cause:
If purchase events are pushed directly from the client's backend via the GA4 Measurement Protocol, sending a purchase with only client_id creates an unattached event. GA4 requires both a valid client_id and the active session_id (retrieved from the user's _ga_<container-id> cookie at checkout) to bind the purchase to the active session.
If sent >72 hours late or missing timestamp_micros, GA4 drops session correlation, dumping the revenue into (not set).
Fix:
- Capture session_id from the client cookie during checkout and pass it explicitly in the Measurement Protocol payload alongside client_id and engagement_time_msec. If you're using our Google Tag Manager GA4 extension for Magento 2, this is natively handled by the extension.
Cross-Domain Tracking Breakdown
Cause:
If the checkout spans across domains or subdomains (e.g., store on brand.com and checkout on checkout.brand.com or a hosted platform), cross-domain linking (_gl URL parameter) is missing or broken on the transition link/form submit, GA4 loses the original _ga cookie and session context.
When the user completes the purchase, GA4 starts a brand-new session on the destination domain, marking the source as (direct) or the landing domain.
Fix:
- Configure cross-domain domains under GA4 Data Stream > Configure Tag Settings > Configure Your Domains. Ensure links and forms passing users to checkout maintain the _gl URL query string.
Gooogle Tag Manager Tag Sequencing
Cause:
Tags firing before the core Google Tag (the base configuration tag) is one of the single most common reasons e-commerce stores and websites see transactions or events end up as (not set), (direct), or Unassigned.
The Google Tag is the Initializer - when a user visits a page, the Google Tag is responsible for reading the incoming URL query parameters (utm_*, gclid, gbraid), inspecting the browser's HTTP Referer header, writing/updating the GA4 session cookie (_ga_<CONTAINER_ID>), and generating the session_id parameter.
It binds all that marketing source context (e.g., google / cpc or newsletter / email) to that specific session_id. If a custom GTM event tag such as a purchase, add_to_cart, or custom dataLayer event, fires before the Google Tag has executed:
Missing Session Context: The event arrives at Google Analytics servers without an active session_id or session attribution context because the cookie and parameters haven't been processed yet.
- Orphaned Hits: GA4 receives the purchase payload (items, value, transaction_id), but it has no session container to attach it to.
- Data Loss / Unassigned: GA4 registers the event, but because it lacks the campaign details that the Google Tag was supposed to extract from the landing URL or referrer, it falls back to:
Session source / medium = (not set)
Default channel group = Unassigned
Fix:
- Set your Google Tag trigger to Consent Initialization - All Pages or Initialization - All Pages.
- Never trigger page-load events on Initialization. Trigger event tags on Container Loaded (Page View), DOM Ready, or custom dataLayer events.
- In the purchase tag's Advanced Settings > Tag Sequencing, check "Fire a tag before this tag fires" and select your Google Tag.
Inconsistent server_container_url for sGTM implementations
Cause:
If you're using sGTM (Server-Side GTM), usually Google Tag receives a parameter called server_container_url, this tells the tag where to send data to. By default, all other tags should inherit this setting, but we have observed that on few occasions tags are not automatically using the same server_container_url and this results in some events being sent directly to GA4 causing the (not set) issue. This can also happen if you have hard-coded GA4 implementation on the site or another GTM snippet running in parallel that sends data directly to GA4.
Fix:
- Create a resusable configiration variable in GTM and set server_container_url explicitly in evey tag
Google Analytics 4 Audiences
Cause:
GA4 Audiences specifically "Audience Triggers" can cause Unassigned traffic and (not set) attribution in your reports. Unlike a standard GTM event triggered directly by a user clicking a button or loading a page, Audience Trigger events are evaluated and generated on Google’s backend processing servers.
When a user meets the criteria for an audience, Google's backend fires the generated event asynchronously.
Because this event is generated on the server side rather than directly within the active web session's page context, it often lacks a live session_id or page_view binding at the exact millisecond of creation.
Fix:
- Avoid using these at all costs
AI traffic
Traffic originating from AI suggestions, LLM answers, and AI search engines (like ChatGPT, Perplexity, Claude, Gemini, and Google AI Overviews) is one of the biggest drivers of unassigned and misclassified traffic in GA4 today.
While real users click links embedded in AI answers, GA4 frequently measures this traffic inaccurately or strips its attribution entirely.
Why AI Suggestions can potentially cause traffic measurement Issues?
1. Stripped Referrer Headers (App-to-Web Transitions)
When users click a link inside mobile apps (e.g., ChatGPT app, Copilot app, or embedded webviews inside Perplexity), the application often strips the HTTP Referer header for privacy or technical reasons.
The Result: GA4 receives the hit with zero source context, dumping the session straight into (direct) / (none) or (not set).
2. Lack of Dynamic UTM Tagging
Unlike email newsletters or paid ads, links cited dynamically inside generative AI outputs do not append utm_source, utm_medium, or campaign parameters. Without UTM parameters, GA4 is forced to rely solely on browser referrer strings.
3. Rule Mismatches in GA4 Channel Grouping
When AI referral domains do pass through cleanly (e.g., chatgpt.com, perplexity.ai, or claude.ai), GA4’s default channel definitions historically didn't have explicit rules for AI platforms. Depending on the property configuration:
They land in generic Referral.
If combined with custom parameters or non-standard protocols, they get dropped into Unassigned.
4. Masked Google AI Overview Traffic
When users click links inside Google’s AI Overviews (SGE) directly on the Search Results Page:
Google sends the traffic under standard google / organic referral headers.
GA4 blends this traffic into standard organic search, making it impossible to separate traditional "blue link" clicks from AI-driven answer clicks without explicit parameter tracking.
How to Fix and Accurately Track AI Traffic in GA4
You can reclaim visibility by configuring a Custom Channel Group in GA4 specifically for AI referral traffic.
Step-by-step Setup:
- Go to GA4 Admin > Data Display > Channel Groups.
- Select Copy to Create New (based on your Default Channel Group).
- Click Add New Channel and name it AI Search / Assistants.
- Set the condition rule to Source matches Regex: .*(chatgpt|openai|perplexity|claude|gemini|copilot|poe|phind).*
- Reorder the channel list: Drag your new AI Search channel above the generic Referral and Unassigned rules so GA4 matches AI traffic first.