attribution-errorsUpdated 2025

Why utm_source=null Makes Your Campaign Data Invisible in GA4

Using 'null' as utm_source tells GA4 'no source exists' instead of 'source is null'. Here's why this destroys attribution and how to fix it.

6 min readattribution-errors

Your campaign management system generates this URL:

Code
https://shop.com/sale?utm_source=null&utm_medium=email&utm_campaign=summer-promo

It looks formatted correctly.

You send it to 35,000 subscribers.

GA4 shows zero sessions from the campaign.

The 3,847 clicks all show as "(direct) / (none)".

The culprit: utm_source=null

This isn't a descriptive campaign name. It's a programming keyword that tells GA4 "this traffic has no source"—and GA4 believes it.

Here's exactly why "null" destroys attribution and how to prevent it.

🚨 Not sure what's breaking your tracking?

Run a free 60-second audit to check all 40+ ways UTM tracking can fail.

Scan Your Campaigns Free

✓ No credit card ✓ See results instantly

What "null" Means to GA4

In programming and databases, null means "no value exists" or "value is absent."

When GA4 sees utm_source=null:

What you meant:

  • Source: Campaign named "null"
  • Medium: email
  • Campaign: summer-promo

What GA4 interprets:

Code
utm_source: [NO VALUE PROVIDED]
utm_medium: email
utm_campaign: summer-promo

GA4's logic:

  1. Check utm_source → Value is "null" (treated as missing)
  2. Check utm_medium → "email" present but utm_source missing
  3. utm_medium without utm_source = orphaned parameter
  4. Ignore both UTM parameters
  5. Check HTTP referrer → Email has no referrer
  6. Default to: "(direct) / (none)"

Your utm_source isn't a name—it's an instruction telling GA4 "no source was provided."

Why "null" Appears in Campaign URLs

Cause 1: Database Default Values

Campaign management systems store UTM parameters in databases:

Sql
CREATE TABLE campaigns (
  id INT,
  name VARCHAR(255),
  utm_source VARCHAR(255) DEFAULT NULL,
  utm_medium VARCHAR(255) DEFAULT NULL,
  utm_campaign VARCHAR(255)
);

When you create a new campaign:

  • utm_source starts as NULL (database null value)
  • System generates URL before you set the value
  • URL contains utm_source=null literally

The bug: System converts database NULL to string "null" instead of preventing URL generation.

Cause 2: Programming Placeholders

Developer creates UTM builder:

Javascript
let campaign = {
  source: null,  // Will be set later
  medium: null,  // Will be set later
  campaign: "summer-sale"
};
 
// Bug: Generate URL before values are set
let url = `${"{"}{"{"}baseUrl{"}"}{"}"}}?utm_source=${campaign.source}&utm_medium=${campaign.medium}`;
// Result: ?utm_source=null&utm_medium=null

The bug: URL generation happens before null values are replaced with actual campaign data.

Cause 3: API Default Responses

Marketing automation API returns:

Json
{
  "campaign_id": 12345,
  "utm_source": null,
  "utm_medium": null,
  "utm_campaign": "launch"
}

System concatenates these directly into URL:

Code
?utm_source=null&utm_medium=null&utm_campaign=launch

The bug: No validation that null values are invalid for URL parameters.

Cause 4: Incomplete Template Population

UTM template:

Code
?utm_source={`{"{"}{"{"}source{"}"}{"}"}}`}&utm_medium={`{"{"}{"{"}medium{"}"}{"}"}}`}&utm_campaign={`{"{"}{"{"}campaign{"}"}{"}"}}`}

Template engine with missing data:

  • source: (not provided)
  • medium: (not provided)
  • campaign: "promotion"

Some template engines output:

Code
?utm_source=null&utm_medium=null&utm_campaign=promotion

The bug: Template engine uses "null" as default for missing variables instead of throwing an error.

😰 Is this your only tracking issue?

This is just 1 of 40+ ways UTM tracking breaks. Most marketing teams have 8-12 critical issues they don't know about.

• 94% of sites have UTM errors

• Average: $8,400/month in wasted ad spend

• Fix time: 15 minutes with our report

✓ Connects directly to GA4 (read-only, secure)

✓ Scans 90 days of data in 2 minutes

✓ Prioritizes issues by revenue impact

✓ Shows exact sessions affected

Get Your Free Audit Report

Real Example: 89,000 Sessions Invisible for 6 Months

Client: E-commerce retailer Problem: Email campaigns showed zero attribution for 6 months Impact: $340,000 in revenue misattributed as "Direct"

What happened:

Their campaign management system (custom-built) had this database schema:

Sql
CREATE TABLE email_campaigns (
  id INT PRIMARY KEY,
  campaign_name VARCHAR(255),
  subject_line VARCHAR(255),
  utm_source VARCHAR(100) DEFAULT 'null',  -- THE PROBLEM
  utm_medium VARCHAR(100) DEFAULT 'null',  -- THE PROBLEM
  utm_campaign VARCHAR(100),
  created_at TIMESTAMP
);

The database default: DEFAULT 'null' (string "null", not database NULL)

What this meant:

Every time they created a new email campaign:

  1. System created database row with utm_source = "null"
  2. Marketer filled in campaign name, subject line
  3. Marketer forgot to update utm_source and utm_medium
  4. System generated URLs with literal "null" values
  5. Campaign launched with broken tracking

GA4 data over 6 months:

  • Email campaigns sent: 24
  • Email sends: 420,000
  • Clicks: 89,000
  • Sessions attributed to email: 0
  • Sessions in "(direct) / (none)": +89,000
  • Revenue attributed to email: $0
  • Revenue attributed to direct: +$340,000

Their conclusion: "Email marketing doesn't work. Direct traffic is incredible."

Reality: Every email click was showing as Direct traffic because of utm_source=null.

The fix:

Changed database schema:

Sql
ALTER TABLE email_campaigns
  MODIFY utm_source VARCHAR(100) NOT NULL,  -- REQUIRE value
  MODIFY utm_medium VARCHAR(100) NOT NULL;  -- REQUIRE value

Added validation:

Javascript
if (campaign.utm_source === null || campaign.utm_source === 'null') {
  throw new Error('utm_source is required and cannot be "null"');
}

Set default to empty string (throws error if not filled):

Sql
utm_source VARCHAR(100) DEFAULT '' NOT NULL

Result after fix:

  • Next campaign: 3,800 sessions properly attributed to email
  • Monthly email attribution recovered
  • Discovered email was actually the #2 revenue driver (not direct)

How to Identify utm_source=null Problem

Test 1: GA4 Source Search (30 seconds)

  1. GA4 → Reports → Traffic Acquisition
  2. Search bar → Type "null"
  3. Look for "null / email" or "null / social" patterns

If you see "null" as a source name → You have this problem.

Test 2: Direct Traffic Landing Page Analysis (2 minutes)

  1. GA4 → Reports → Traffic Acquisition
  2. Click "(direct) / (none)"
  3. Add secondary dimension: "Landing page"
  4. Look for email-specific landing pages

If you see landing pages like:

  • /email-exclusive-offer
  • /newsletter-subscribers-only
  • /welcome-new-subscriber

Under direct traffic → Your email campaigns likely have utm_source=null.

Test 3: Campaign System Audit (5 minutes)

Check your campaign management tool:

  1. Create new test campaign
  2. Don't fill in any UTM fields
  3. Generate URL
  4. Check if URL contains utm_source=null

If it does → Your system uses "null" as default.

Test 4: Database Query (for developers)

Query your campaign database:

Sql
SELECT campaign_name, utm_source, utm_medium, url
FROM campaigns
WHERE utm_source = 'null' OR utm_medium = 'null'
ORDER BY created_at DESC
LIMIT 20;

If query returns rows → You have campaigns with literal "null" values.

The 5-Minute Fix

Fix 1: Replace "null" with Descriptive Names

Before (broken):

Code
?utm_source=null&utm_medium=email&utm_campaign=summer-sale

After (fixed):

Code
?utm_source=newsletter&utm_medium=email&utm_campaign=summer-sale

Before (broken):

Code
?utm_source=null&utm_medium=null&utm_campaign=product-launch

After (fixed):

Code
?utm_source=newsletter&utm_medium=email&utm_campaign=product-launch

Fix 2: Update Database Defaults (for developers)

Current (problem):

Sql
CREATE TABLE campaigns (
  utm_source VARCHAR(100) DEFAULT 'null',
  utm_medium VARCHAR(100) DEFAULT 'null'
);

Fixed:

Sql
CREATE TABLE campaigns (
  utm_source VARCHAR(100) NOT NULL,  -- Require actual value
  utm_medium VARCHAR(100) NOT NULL   -- Require actual value
);

Or use empty string default:

Sql
CREATE TABLE campaigns (
  utm_source VARCHAR(100) DEFAULT '' NOT NULL,
  utm_medium VARCHAR(100) DEFAULT '' NOT NULL
);

Then add validation to prevent saving campaigns with empty utm_source/medium.

Fix 3: Add Validation (for developers)

JavaScript validation:

Javascript
function generateCampaignURL(campaign) {
  // Check for null (actual null)
  if (campaign.utm_source === null || campaign.utm_medium === null) {
    throw new Error('utm_source and utm_medium are required');
  }
 
  // Check for "null" string
  if (campaign.utm_source === 'null' || campaign.utm_medium === 'null') {
    throw new Error('utm_source and utm_medium cannot be "null"');
  }
 
  // Check for empty strings
  if (!campaign.utm_source || !campaign.utm_medium) {
    throw new Error('utm_source and utm_medium cannot be empty');
  }
 
  // Generate URL
  return `${campaign.url}?utm_source=${campaign.utm_source}&utm_medium=${campaign.utm_medium}&utm_campaign=${campaign.utm_campaign}`;
}

Python validation:

Python
def generate_campaign_url(campaign):
    # Check for None
    if campaign['utm_source'] is None or campaign['utm_medium'] is None:
        raise ValueError('utm_source and utm_medium are required')
 
    # Check for "null" string
    if campaign['utm_source'] == 'null' or campaign['utm_medium'] == 'null':
        raise ValueError('utm_source and utm_medium cannot be "null"')
 
    # Check for empty strings
    if not campaign['utm_source'] or not campaign['utm_medium']:
        raise ValueError('utm_source and utm_medium cannot be empty')
 
    # Generate URL
    return f"{campaign['url']}?utm_source={campaign['utm_source']}&utm_medium={campaign['utm_medium']}&utm_campaign={campaign['utm_campaign']}"

Fix 4: Template Engine Configuration

Handlebars/Mustache (prevent "null" output):

Javascript
// Configure to throw error on missing variables
Handlebars.registerHelper('required', function(value, name) {
  if (value === null || value === undefined || value === 'null') {
    throw new Error(`Required parameter ${"{"}{"{"}name{"}"}{"}"}} is missing or null`);
  }
  return value;
});
 
// Template
const template = `?utm_source={{required utm_source "utm_source"}}&utm_medium={{required utm_medium "utm_medium"}}`;

✅ Fixed this issue? Great! Now check the other 39...

You just fixed one tracking issue. But are your Google Ads doubling sessions? Is Facebook attribution broken? Are internal links overwriting campaigns?

Connects to GA4 (read-only, OAuth secured)

Scans 90 days of traffic in 2 minutes

Prioritizes by revenue impact

Free forever for monthly audits

Run Complete UTM Audit (Free Forever)

Join 2,847 marketers fixing their tracking daily

Other Reserved Keywords to Avoid

"null" isn't the only problematic value. Also avoid:

Programming keywords:

  • undefined
  • nil
  • none
  • na
  • NaN

GA4 system values:

  • (not set)
  • (not provided)
  • (direct)
  • (none)

Ambiguous terms:

  • test
  • placeholder
  • default
  • example
  • temp

Empty values:

  • `` (empty string)
  • (whitespace)
  • %20 (URL-encoded space)

FAQ

Can I use "NULL" in uppercase?

Avoid it. While GA4 is case-sensitive (NULLnull), using any variation of "null" creates confusion and risks errors.

What if I already sent campaigns with utm_source=null?

Historical data can't be fixed. Those sessions will remain as "(direct)". Use GA4 annotations to mark when you fixed the issue, so future analysis accounts for it.

Why doesn't GA4 show an error?

GA4 treats "null" as literal text meaning "no value." It silently routes traffic to "(direct)" without warnings. This is why the problem goes unnoticed.

Does this affect utm_medium and utm_campaign too?

Yes. Avoid using "null" (or any reserved keyword) in ANY UTM parameter. While utm_source is most critical, using "null" anywhere creates reporting confusion.

How do I prevent this in third-party tools?

If you use a marketing platform that generates UTM parameters:

  1. Check default UTM settings
  2. Verify no fields use "null" as default
  3. Configure platform to require utm_source and utm_medium
  4. Test a campaign URL before launching

Can this affect paid advertising too?

Usually no—Google Ads and Facebook Ads use auto-tagging (gclid, fbclid), not manual UTM parameters. This problem mainly affects email, social, and partner campaigns with manual UTMs.

Prevention Checklist

✅ For Developers:

  • Remove 'null' as database default for UTM columns
  • Add NOT NULL constraint to utm_source and utm_medium columns
  • Validate utm_source ≠ 'null' before URL generation
  • Throw error if utm_source is null, "null", or empty
  • Configure template engines to error on missing variables

✅ For Marketers:

  • Never use "null" as a campaign source name
  • Check URL preview before launching campaign
  • Test URL in GA4 Realtime (verify source appears correctly)
  • Document: "null is forbidden in UTM parameters"

✅ For QA:

  • Test campaign creation with empty UTM fields
  • Verify system blocks URL generation if utm_source is missing
  • Check generated URLs don't contain "null" literally
  • Test with null, "null", NULL, empty string, and whitespace

Conclusion

Campaign showing as "(direct)" even though you added UTM parameters?

Check if utm_source = "null"

Why this happens:

  • Database defaults to "null" string
  • Programming placeholders not replaced
  • No validation before URL generation

The fix:

  1. Replace utm_source=null with descriptive name (newsletter, social, etc.)
  2. Update database defaults (remove "null", require NOT NULL)
  3. Add validation (block "null" values before URL generation)
  4. Test every URL in GA4 Realtime before launch

Never use "null" in UTM parameters. Use actual, descriptive campaign source names.


Related: Complete Reserved Keywords Guide

UTM

Get Your Free Audit in 60 Seconds

Connect GA4, run the scan, and see exactly where tracking is leaking budget. No credit card required.

Trusted by growth teams and agencies to keep attribution clean.