Fix Plus Sign UTM Error: Replace + with %2B or Alternative
+ in UTM causing inconsistent tracking? Quick fix guide to encode plus signs correctly or use alternatives for reliable campaign data.
Your UTM has a + sign. GA4 shows inconsistent values across sessions.
Here's the 3-step fix to encode + correctly and restore consistent tracking.
Table of contents
- The Problem
- Quick Fix (3 Steps)
- Step 1: Decide on Approach (30 seconds)
- Step 2: Apply Fix (60 seconds)
- Step 3: Test (30 seconds)
- Why + Causes Inconsistency
- Automated Fix Script
- Common Scenarios & Fixes
- Scenario 1: Product Names
- Scenario 2: Brand Names
- Scenario 3: Multiple + Symbols
- Scenario 4: Mathematical Operators
- Bulk Fix Script
- Platform-Specific Application
- Google Ads
- Facebook Ads
- Microsoft Ads
- Email HTML
- Validation After Fix
- Decision Matrix
- Testing Checklist
- Real-World Example: Tech Product Launch
- FAQ
- Should I always encode + as %2B?
- What if + appears multiple times?
- Will this break existing campaigns?
- Can I use + for spaces?
- How do I find all URLs with unencoded + signs?
- Does this affect URL shorteners?
- What about + in the domain or path?
- Can email platforms handle + signs correctly?
- How does this interact with server-side tracking?
- What if my CMS or marketing platform adds + automatically?
- 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
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
Why + Causes Inconsistency
The + symbol has dual meaning in URLs:
Historical usage: + represented spaces in early URL encoding (before %20 became standard)
Modern ambiguity: Some systems decode + as space, others keep it as literal +
Result: Same URL produces different GA4 values depending on:
- Browser version
- Platform click redirects
- Server-side URL processing
- Client-side JavaScript parsing
This creates data fragmentation where identical campaign URLs report under multiple campaign names.
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
Scenario 4: Mathematical Operators
Campaign: 1+1 Sale
❌ INCONSISTENT:
utm_campaign=1+1_sale
✅ FIX Option 1:
utm_campaign=1%2B1_sale
→ GA4: "1+1_sale"
✅ FIX Option 2:
utm_campaign=bogo_sale
→ More descriptive anyway
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
Microsoft Ads
Tracking Template:
{lpurl}?utm_campaign=bing%2Bsearch&msclkid={msclkid}
↑
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 |
1+1 sale | Encode | 1%2B1_sale | Math expression |
1+1 sale | Replace | bogo_sale | Clearer meaning |
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
✅ Historical comparison
Compare to past campaign names
Ensure no duplicates created
Real-World Example: Tech Product Launch
Company: Online learning platform Product: "C++ Mastery Course" Campaign: Google Ads + Facebook Ads Budget: $12,000
Broken URLs:
Google: site.com/cpp?utm_campaign=c++_mastery&utm_source=google
Facebook: site.com/cpp?utm_campaign=c++_mastery&utm_source=facebook
Result in GA4:
- Campaign variations showing as:
- "c _mastery" (+ decoded as spaces)
- "c++_mastery" (+ preserved)
- Data split across 2 campaign names
- Unable to calculate true ROI
Fixed URLs (2 minutes):
Google: site.com/cpp?utm_campaign=cpp_mastery&utm_source=google
Facebook: site.com/cpp?utm_campaign=cpp_mastery&utm_source=facebook
Result:
- Single unified campaign: "cpp_mastery"
- Accurate ROI calculation
- Clear attribution across platforms
✅ 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). For brand names like Google+ or product names like C++, encoding preserves the original branding.
What if + appears multiple times?
Encode or replace ALL occurrences:
value.replace(/\+/g, '%2B') // All + → %2BNever partially encode—this creates even more fragmentation.
Will this break existing campaigns?
If changing mid-campaign, you'll create new campaign value in GA4. Historical data remains under old value. Better to fix before launch. For active campaigns, consider finishing the campaign with existing URLs and fixing for next campaign.
Can I use + for spaces?
Not recommended. Use %20 or underscores for better reliability. The + symbol's dual meaning (space vs literal plus) causes too much inconsistency across platforms.
How do I find all URLs with unencoded + signs?
Export campaign URLs, use this regex pattern:
const hasUnencodedPlus = url.match(/[?&]utm_[^=]+=([^&]*\+[^&]*)/);Or in Google Sheets:
=IF(ISNUMBER(SEARCH("+",A1)),"Contains +","OK")
Does this affect URL shorteners?
Most URL shorteners (Bitly, TinyURL) handle encoding automatically, but it's safer to encode before shortening to ensure consistency.
What about + in the domain or path?
Domain names cannot contain +. In URL paths, + should be avoided or encoded as %2B for consistency.
Can email platforms handle + signs correctly?
Email platforms vary. Some auto-encode, others don't. Always manually encode to ensure consistency across Mailchimp, Klaviyo, SendGrid, etc.
How does this interact with server-side tracking?
Server-side tracking (via Measurement Protocol) requires consistent encoding. If your server decodes + as space but GA4 keeps it literal, you'll have duplicate sessions. Always encode as %2B for server-side implementations.
What if my CMS or marketing platform adds + automatically?
Check your platform's URL encoding settings. Disable automatic + insertion if possible. If not, use the JavaScript fix script to clean URLs before they reach GA4.
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
✅ 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