GA4 12 min read

(not set) in GA4: Every Cause Explained and How to Fix Each One

Seeing (not set) in your GA4 reports is frustrating but fixable. This guide covers every reason it appears — in session source, landing page, item name, and other dimensions — and the specific fix for each.

A
Aumlytics Team
·

(not set) is the value GA4 displays when a dimension was expected but no value was captured. It’s not a single problem — it’s a symptom that appears for different reasons depending on which dimension you’re looking at.

Seeing (not set) in your session source report means something different from seeing it in your landing page report or your item name report. Each location has specific causes and specific fixes.

This guide covers every major context where (not set) appears in GA4 and what to do about it.


(not set) in Session Default Channel Grouping / Source / Medium

This is the most common complaint. A significant percentage of sessions show as (not set) in your traffic acquisition reports.

Cause 1: Direct traffic with no session source

If a user visits your site directly (types your URL, uses a bookmark, or comes from a dark social share like WhatsApp or Slack), GA4 captures no campaign source. These sessions appear as Direct in source and (none) in medium — not (not set).

(not set) in source/medium specifically indicates that GA4 didn’t capture session-level data at all — usually because the session source wasn’t set properly during session initialisation.

Cause 2: Cross-domain tracking not configured

When a user crosses from one domain to another (e.g., from your main site to your checkout on a subdomain, or from a third-party checkout back to your store), GA4 starts a new session. If cross-domain tracking isn’t configured, the original session source is lost and the new session may show (not set).

Fix: Configure cross-domain measurement in GTM:

  1. GTM → GA4 Configuration tag → Fields to Set → add:
    • Field name: linker
    • Value: {"domains": ["yourdomain.com", "checkout.yourdomain.com", "yourstorename.myshopify.com"]}

Or in GA4 Admin → Data StreamsConfigure tag settingsConfigure your domains → add all domains users cross.

Cause 3: GA4 tag fires before it’s fully initialised

If an event fires while GA4 is still setting up the session (e.g., a tag fired by another trigger fires before the GA4 configuration tag), the session parameters may not be attached.

Fix: In GTM, ensure your GA4 Configuration tag has priority higher than any GA4 Event tags. Set the Configuration tag priority to 10 and event tags to 0.

Cause 4: Conflicting GA4 tags

If you have both a GA4 tag managed by GTM AND a gtag.js snippet in your HTML, two separate instances of GA4 may initialise, causing session data conflicts.

Fix: Use only one GA4 implementation method. Either GTM or gtag.js in the HTML — not both.


(not set) in Landing Page / Page Path

Cause 1: Events fired with no page_location parameter

If an event fires without a page_location parameter (which GA4 normally captures automatically from the page URL), the landing page dimension will be (not set).

This commonly happens with server-side events sent via the Measurement Protocol that don’t include a page_location in the event parameters.

Fix: Always include page_location and page_referrer in Measurement Protocol events:

payload = {
    "client_id": client_id,
    "events": [{
        "name": "page_view",
        "params": {
            "page_location": "https://yoursite.com/product/widget",
            "page_referrer": "https://yoursite.com/category/widgets",
            "page_title": "Widget Product Page"
        }
    }]
}

Cause 2: Single-page application (SPA) not firing page_view events

In React, Vue, or Angular apps where the URL changes without a full page reload, GA4 only gets the initial page_view event. Subsequent “page views” (route changes) don’t fire page_view events unless you explicitly implement them.

Fix: Fire a page_view event on every route change:

// React Router example
import { useEffect } from 'react';
import { useLocation } from 'react-router-dom';

function Analytics() {
  const location = useLocation();

  useEffect(() => {
    gtag('event', 'page_view', {
      page_title: document.title,
      page_location: window.location.href
    });
  }, [location]);

  return null;
}

Cause 3: GA4 configured for a SPA with enhanced measurement

In GA4’s enhanced measurement settings, the “Page changes based on browser history events” option handles SPA navigation. If this is enabled but your SPA uses a non-standard routing mechanism, it may not fire correctly.

Fix: Check GA4 Admin → Data StreamsEnhanced Measurement → verify the history-based page view setting matches how your SPA handles routing.


(not set) in Item Name / Item ID (Ecommerce Reports)

This is particularly damaging — if your purchase or view_item events have (not set) for item names, your product revenue attribution is meaningless.

Cause 1: items array not populated

The most common cause: the purchase event fires but the items array is empty or missing item properties.

Fix: Always include a properly structured items array:

gtag('event', 'purchase', {
  transaction_id: 'T-12345',
  value: 59.99,
  currency: 'GBP',
  items: [
    {
      item_id: 'SKU-001',        // Required for item_id dimension
      item_name: 'Blue Widget',   // Required for item_name dimension
      item_category: 'Widgets',
      price: 29.99,
      quantity: 2
    }
  ]
});

Cause 2: Items populated but with wrong property names

GA4’s ecommerce events expect specific property names. Common mistakes:

// ❌ Wrong — GA4 won't recognise these
items: [{
  name: 'Blue Widget',    // Should be item_name
  id: 'SKU-001',          // Should be item_id
  category: 'Widgets'     // Should be item_category
}]

// ✅ Correct — standard GA4 ecommerce schema
items: [{
  item_name: 'Blue Widget',
  item_id: 'SKU-001',
  item_category: 'Widgets',
  price: 29.99,
  quantity: 1
}]

Cause 3: Shopify’s default GA4 integration

Shopify’s built-in Google & YouTube channel integration uses its own ecommerce event structure that doesn’t always match GA4’s expected schema. This can result in item_name being (not set) if the variant title isn’t mapped correctly.

Fix: Use a GTM-based implementation with explicit items array construction that maps from Shopify’s product data:

// In your GTM datalayer push (in Shopify liquid)
dataLayer.push({
  event: 'purchase',
  ecommerce: {
    transaction_id: '{{ order.name }}',
    value: {{ order.total_price | divided_by: 100.0 }},
    currency: '{{ order.currency }}',
    items: [
      {% for line_item in order.line_items %}
      {
        item_id: '{{ line_item.variant.sku }}',
        item_name: '{{ line_item.product.title | escape }}',
        item_variant: '{{ line_item.variant.title | escape }}',
        price: {{ line_item.price | divided_by: 100.0 }},
        quantity: {{ line_item.quantity }}
      }{% unless forloop.last %},{% endunless %}
      {% endfor %}
    ]
  }
});

(not set) in User Properties / Custom Dimensions

Cause 1: Custom dimension registered in GA4 but not being sent

If you register a custom dimension in GA4 Admin → Custom Definitions but your events don’t include that parameter, (not set) fills the column.

Fix: Check your event implementation against your custom dimension registrations. Every registered custom dimension must have a corresponding parameter in your event code.

Cause 2: Scope mismatch

GA4 custom dimensions have three scopes: Event, User, and Item. If you register a dimension as User scope but only set it as an Event parameter, it won’t populate.

Fix: Match scope in registration to scope in implementation:

// User-scoped custom dimension (set on the user, persists across sessions)
gtag('set', 'user_properties', {
  customer_tier: 'gold'   // matches user-scoped dimension registered as 'customer_tier'
});

// Event-scoped custom dimension (set per event)
gtag('event', 'page_view', {
  content_type: 'blog_post'   // matches event-scoped dimension
});

Cause 3: Data processing delay

Custom dimension data can take 24–48 hours to appear in reports. If you recently added a new custom dimension and are seeing (not set) for it, wait for the data to process before concluding there’s a problem.


(not set) in Device / Browser Reports

Very rarely, device or browser reports show (not set). This occurs when:

  • Events are sent via the Measurement Protocol without user agent information
  • A headless browser or bot triggers events

Fix: Include the user_agent parameter in Measurement Protocol requests if sending from a user-facing context:

headers = {
    'User-Agent': 'Mozilla/5.0 ...',  # include user's actual UA
    'Content-Type': 'application/json'
}

(not set) in Audience Reports

Cause 1: Audience configured with conditions not met

If an audience requires a specific dimension (e.g., “users who purchased category = Widgets”) but no events with that dimension have fired, the audience shows (not set) for that dimension.

Cause 2: Audience export to Google Ads not connected

If you’re viewing audience data in a Google Ads context and the GA4 → Google Ads link isn’t configured, audience names appear as (not set) in Ads reports.

Fix: GA4 Admin → Product LinksGoogle Ads Links → link your Google Ads account.


How to Diagnose (not set) Systematically

Step 1: Identify which dimension is (not set) Different dimensions have different causes. Narrow down exactly which dimension shows (not set) before investigating.

Step 2: Check real-time in DebugView GA4 → AdminDebugView → trigger the affected events on your test device → inspect the event parameters. Missing parameters = (not set) in reports.

Step 3: Check BigQuery if connected Query the raw events table to see exactly what parameters were or weren’t included:

SELECT
  event_name,
  (SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'page_location') AS page_location,
  (SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'session_campaign') AS campaign
FROM `project.analytics_XXXXXXXXXX.events_*`
WHERE event_name = 'purchase'
AND _TABLE_SUFFIX = FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE(), INTERVAL 1 DAY))
LIMIT 20;

NULL values in the query result = (not set) in GA4 reports.

Step 4: Use the GA4 Event Validator Google’s GA4 Event Validator lets you test event payloads before sending them to confirm they contain all required parameters.


(not set) is always fixable once you identify which dimension is affected and why. If you’re seeing persistent (not set) values in your GA4 reports and need help diagnosing the root cause, our team does GA4 implementation audits that identify exactly what’s missing and how to fix it. Book a free consultation.

#ga4#google-analytics#not-set#dimensions#debugging#traffic-sources#ecommerce

Want This Implemented Correctly?

Let our team apply these concepts to your specific setup — with QA validation and 30 days of support.