Fix Plus Sign UTM Error: Replace + with %2B or Alternative
Your UTM has a + sign. GA4 shows inconsistent values across sessions.
Here's the 3-step fix to encode + correctly and restore consistent tracking.
🚨 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
The Problem
❌ INCONSISTENT:
?utm_campaign=google+ads
GA4 shows randomly:
- "google ads" (+ decoded as space)
- "google+ads" (+ kept as +)
One URL, two different campaign values
Quick Fix (3 Steps)
Step 1: Decide on Approach (30 seconds)
Choose one:
Option A: Encode + as %2B
→ Preserves + symbol in GA4
Option B: Replace with hyphen
→ Simpler, no encoding
Option C: Remove +
→ Shortest option
Step 2: Apply Fix (60 seconds)
Option A: Encode as %2B
❌ BEFORE:
?utm_campaign=google+ads
✅ AFTER:
?utm_campaign=google%2Bads
GA4 shows: "google+ads"
Option B: Replace with Hyphen
❌ BEFORE:
?utm_campaign=google+ads
✅ AFTER:
?utm_campaign=google-ads
GA4 shows: "google-ads"
Option C: Remove +
❌ BEFORE:
?utm_campaign=google+ads
✅ AFTER:
?utm_campaign=googleads
GA4 shows: "googleads"
Step 3: Test (30 seconds)
1. Visit fixed URL
2. Check browser console:
new URL(location.href).searchParams.get('utm_campaign')
3. Verify consistent value
4. Check GA4 Real-Time
Done.
😰 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
Automated Fix Script
function fixPlusSign(url, method = 'encode') {
const urlObj = new URL(url);
['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term'].forEach(key => {
let value = urlObj.searchParams.get(key);
if (value && value.includes('+')) {
switch(method) {
case 'encode':
// Encode + as %2B
value = value.replace(/\+/g, '%2B');
break;
case 'hyphen':
// Replace + with -
value = value.replace(/\+/g, '-');
break;
case 'remove':
// Remove + entirely
value = value.replace(/\+/g, '');
break;
}
urlObj.searchParams.set(key, value);
}
});
return urlObj.toString();
}
// Usage
const broken = 'site.com?utm_campaign=google+ads';
console.log(fixPlusSign(broken, 'encode'));
// site.com?utm_campaign=google%2Bads
console.log(fixPlusSign(broken, 'hyphen'));
// site.com?utm_campaign=google-ads
console.log(fixPlusSign(broken, 'remove'));
// site.com?utm_campaign=googleadsCommon Scenarios & Fixes
Scenario 1: Product Names
Product: C++ Programming
❌ INCONSISTENT:
utm_content=C++
✅ FIX Option 1:
utm_content=C%2B%2B
→ GA4: "C++"
✅ FIX Option 2:
utm_content=cpp
→ GA4: "cpp"
Scenario 2: Brand Names
Brand: Google+
❌ INCONSISTENT:
utm_source=google+
✅ FIX Option 1:
utm_source=google%2B
→ GA4: "google+"
✅ FIX Option 2:
utm_source=googleplus
→ GA4: "googleplus"
Scenario 3: Multiple + Symbols
Campaign: C++ for C# Developers
❌ INCONSISTENT:
utm_campaign=c++for-c#-devs
✅ FIX:
utm_campaign=cpp-for-csharp-devs
→ Simple, readable, no encoding
Bulk Fix Script
// Fix multiple URLs at once
function bulkFixPlusSign(urls, method = 'encode') {
return urls.map(url => {
try {
return fixPlusSign(url, method);
} catch (error) {
console.error(`Failed to fix: ${"{"}{"{"}url{"}"}{"}"}}`, error);
return url;
}
});
}
// Usage
const urls = [
'site.com?utm_campaign=google+ads',
'site.com?utm_source=bing+search',
'site.com?utm_content=c++'
];
const fixed = bulkFixPlusSign(urls, 'encode');
console.log(fixed);
// All + encoded as %2BPlatform-Specific Application
Google Ads
Tracking Template:
`{"{"}{"{"}lpurl{"}"}{"}"}}`?utm_campaign=google%2Bads&gclid=`{"{"}{"{"}gclid{"}"}{"}"}}`
↑
Encode + as %2B
Facebook Ads
URL Parameters:
utm_source=facebook&utm_campaign=product%2Bads
↑
Encode + as %2B
Email HTML
<a href="site.com?utm_campaign=product%2Bpromo&utm_source=email">
Shop Now
</a>Validation After Fix
function validatePlusFix(url) {
const urlObj = new URL(url);
const rawQuery = url.split('?')[1] || '';
// Check if any unencoded + remains in UTM values
const utmParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term'];
const issues = utmParams
.filter(param => {
const paramPattern = new RegExp(`${"{"}{"{"}param{"}"}{"}"}}=([^&]*)`);
const match = rawQuery.match(paramPattern);
return match && match[1].includes('+') && !match[1].includes('%2B');
})
.map(param => ({
parameter: param,
issue: 'Contains unencoded +'
}));
return {
valid: issues.length === 0,
issues
};
}
// Usage
const url = 'site.com?utm_campaign=google%2Bads';
const result = validatePlusFix(url);
if (result.valid) {
console.log('✅ All + signs properly encoded');
} else {
console.log('❌ Issues found:', result.issues);
}Decision Matrix
| Original Value | Method | Result | When to Use |
|---|---|---|---|
google+ads | Encode | google%2Bads | Need to preserve + |
google+ads | Hyphen | google-ads | Don't need + |
google+ads | Remove | googleads | Short URLs needed |
C++ | Encode | C%2B%2B | Brand/product name |
C++ | Replace | cpp | Abbreviation OK |
Testing Checklist
After fixing:
✅ Visual check
URL contains %2B (or alternative), not raw +
✅ Browser test
new URL('url').searchParams.get('utm_campaign')
Shows consistent value
✅ Cross-browser test
Chrome, Firefox, Safari, Mobile
All show same value
✅ GA4 Real-Time test
Campaign appears with expected value
No data fragmentation
✅ 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
FAQ
Should I always encode + as %2B?
If you need literal + in GA4, yes. Otherwise, consider simpler alternatives (hyphen, remove).
What if + appears multiple times?
Encode or replace ALL occurrences:
value.replace(/\+/g, '%2B') // All + → %2BWill this break existing campaigns?
If changing mid-campaign, you'll create new campaign value in GA4. Better to fix before launch.
Can I use + for spaces?
Not recommended. Use %20 or underscores for better reliability.
Conclusion
Fix + in UTM parameters in 3 steps:
- Choose approach: encode, replace, or remove
- Apply fix using script or manual edit
- Test in browser and GA4
❌ utm_campaign=google+ads (inconsistent)
✅ utm_campaign=google%2Bads (encoded)
✅ utm_campaign=google-ads (alternative)
Encode + as %2B for consistent tracking across all platforms.
Technical Reference: Plus Sign in Value Validation Rule