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.
Your campaign management system generates this URL:
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.
Table of contents
- What "null" Means to GA4
- Why "null" Appears in Campaign URLs
- Cause 1: Database Default Values
- Cause 2: Programming Placeholders
- Cause 3: API Default Responses
- Cause 4: Incomplete Template Population
- Real Example: 89,000 Sessions Invisible for 6 Months
- How to Identify utmsource=null Problem
- Test 1: GA4 Source Search (30 seconds)
- Test 2: Direct Traffic Landing Page Analysis (2 minutes)
- Test 3: Campaign System Audit (5 minutes)
- Test 4: Database Query (for developers)
- The 5-Minute Fix
- Fix 1: Replace "null" with Descriptive Names
- Fix 2: Update Database Defaults (for developers)
- Fix 3: Add Validation (for developers)
- Fix 4: Template Engine Configuration
- Other Reserved Keywords to Avoid
- FAQ
- Can I use "NULL" in uppercase?
- What if I already sent campaigns with utmsource=null?
- Why doesn't GA4 show an error?
- Does this affect utmmedium and utmcampaign too?
- How do I prevent this in third-party tools?
- Can this affect paid advertising too?
- Prevention Checklist
- Conclusion
🚨 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:
utm_source: [NO VALUE PROVIDED]
utm_medium: email
utm_campaign: summer-promo
GA4's logic:
- Check utm_source → Value is "null" (treated as missing)
- Check utm_medium → "email" present but utm_source missing
- utm_medium without utm_source = orphaned parameter
- Ignore both UTM parameters
- Check HTTP referrer → Email has no referrer
- 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:
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=nullliterally
The bug: System converts database NULL to string "null" instead of preventing URL generation.
Cause 2: Programming Placeholders
Developer creates UTM builder:
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=nullThe bug: URL generation happens before null values are replaced with actual campaign data.
Cause 3: API Default Responses
Marketing automation API returns:
{
"campaign_id": 12345,
"utm_source": null,
"utm_medium": null,
"utm_campaign": "launch"
}System concatenates these directly into URL:
?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:
?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:
?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
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:
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:
- System created database row with utm_source = "null"
- Marketer filled in campaign name, subject line
- Marketer forgot to update utm_source and utm_medium
- System generated URLs with literal "null" values
- 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:
ALTER TABLE email_campaigns
MODIFY utm_source VARCHAR(100) NOT NULL, -- REQUIRE value
MODIFY utm_medium VARCHAR(100) NOT NULL; -- REQUIRE valueAdded validation:
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):
utm_source VARCHAR(100) DEFAULT '' NOT NULLResult 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)
- GA4 → Reports → Traffic Acquisition
- Search bar → Type "null"
- 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)
- GA4 → Reports → Traffic Acquisition
- Click "(direct) / (none)"
- Add secondary dimension: "Landing page"
- 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:
- Create new test campaign
- Don't fill in any UTM fields
- Generate URL
- 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:
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):
?utm_source=null&utm_medium=email&utm_campaign=summer-sale
After (fixed):
?utm_source=newsletter&utm_medium=email&utm_campaign=summer-sale
Before (broken):
?utm_source=null&utm_medium=null&utm_campaign=product-launch
After (fixed):
?utm_source=newsletter&utm_medium=email&utm_campaign=product-launch
Fix 2: Update Database Defaults (for developers)
Current (problem):
CREATE TABLE campaigns (
utm_source VARCHAR(100) DEFAULT 'null',
utm_medium VARCHAR(100) DEFAULT 'null'
);Fixed:
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:
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:
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:
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):
// 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
Join 2,847 marketers fixing their tracking daily
Other Reserved Keywords to Avoid
"null" isn't the only problematic value. Also avoid:
Programming keywords:
undefinednilnonenaNaN
GA4 system values:
(not set)(not provided)(direct)(none)
Ambiguous terms:
testplaceholderdefaultexampletemp
Empty values:
- `` (empty string)
(whitespace)%20(URL-encoded space)
FAQ
Can I use "NULL" in uppercase?
Avoid it. While GA4 is case-sensitive (NULL ≠ null), 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:
- Check default UTM settings
- Verify no fields use "null" as default
- Configure platform to require utm_source and utm_medium
- 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:
- Replace
utm_source=nullwith descriptive name (newsletter, social, etc.) - Update database defaults (remove "null", require NOT NULL)
- Add validation (block "null" values before URL generation)
- 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