Fix Unencoded Ampersand in UTM: 3-Step Quick Guide
Your UTM campaign name has an &. GA4 shows truncated data.
Here's the 3-step fix to encode ampersands and restore complete 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
❌ BROKEN:
?utm_campaign=save&win
Parsed as:
utm_campaign = "save"
win = "" (interpreted as separate parameter)
GA4 shows: "save"
Missing: "&win"
Quick Fix (3 Steps - Under 2 Minutes)
Step 1: Find the Ampersand (30 seconds)
Look at your URL and find the & that's INSIDE a parameter value:
?utm_campaign=save&win&utm_medium=cpc
↑ ↑ ↑
Part of Should be
value separator
Find this & (in value) → needs encoding
Step 2: Replace with %26 (60 seconds)
❌ BEFORE:
?utm_campaign=save&win&utm_medium=cpc
✅ AFTER:
?utm_campaign=save%26win&utm_medium=cpc
↑ ↑
Encoded as %26
Rule: Replace & INSIDE parameter values with %26. Leave & BETWEEN parameters.
Step 3: Test (30 seconds)
1. Visit fixed URL
2. Open browser console
3. Run: new URL(location.href).searchParams.get('utm_campaign')
4. Should output: "save&win" (decoded)
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
JavaScript One-Liner
// Fix unencoded & in UTM parameters
function fixAmpersands(url) {
const urlObj = new URL(url);
// Re-encode all parameter values
['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term'].forEach(key => {
const value = urlObj.searchParams.get(key);
if (value) {
urlObj.searchParams.set(key, value); // .set() with plain value auto-encodes
}
});
return urlObj.toString();
}
// Usage
const broken = 'https://site.com?utm_campaign=save&win';
const fixed = fixAmpersands(broken);
console.log(fixed);
// https://site.com?utm_campaign=save%26winBrowser Console Quick Fix
// Paste this in console when on the broken URL
(function() {
const url = new URL(window.location.href);
const campaign = prompt('Enter correct campaign value (with &):', 'save&win');
if (campaign) {
url.searchParams.set('utm_campaign', campaign); // Auto-encodes
window.location.href = url.toString();
}
})();Bulk Fix Script
// Fix multiple URLs at once
function bulkFixAmpersands(urls) {
return urls.map(url => {
try {
const urlObj = new URL(url);
const params = new URLSearchParams();
// Re-encode all parameters
for (const [key, value] of urlObj.searchParams.entries()) {
params.set(key, value); // Properly encodes
}
urlObj.search = params.toString();
return urlObj.toString();
} catch (error) {
console.error(`Failed to fix: ${"{"}{"{"}url{"}"}{"}"}}`, error);
return url;
}
});
}
// Usage
const broken = [
'site.com?utm_campaign=save&win',
'site.com?utm_source=johnson&johnson',
'site.com?utm_content=shoes&boots'
];
const fixed = bulkFixAmpersands(broken);
console.log(fixed);
// All & in values encoded as %26Common Patterns & Fixes
Pattern 1: Company Name
❌ WRONG:
utm_source=procter&gamble
✅ RIGHT:
utm_source=procter%26gamble
GA4 shows: "procter&gamble"
Pattern 2: Promotional Text
❌ WRONG:
utm_campaign=buy-now&save
✅ RIGHT:
utm_campaign=buy-now%26save
GA4 shows: "buy-now&save"
Pattern 3: Product Lists
❌ WRONG:
utm_content=shoes&boots&sandals
✅ RIGHT:
utm_content=shoes%26boots%26sandals
GA4 shows: "shoes&boots&sandals"
Pattern 4: Multiple Words with &
❌ WRONG:
utm_campaign=rock&roll&music
✅ RIGHT:
utm_campaign=rock%26roll%26music
GA4 shows: "rock&roll&music"
Visual Guide: Which & to Encode
URL: ?utm_source=facebook&utm_campaign=buy&save&utm_medium=cpc
↑ ↑ ↑ ↑
Separator In value Separator Separator
Encode this one only: ↑
Result: ?utm_source=facebook&utm_campaign=buy%26save&utm_medium=cpc
Rule: Encode & when it's part of a parameter VALUE. Leave & between parameters.
Platform-Specific Application
Google Ads
Tracking Template:
`{"{"}{"{"}lpurl{"}"}{"}"}}`?utm_campaign=buy%26save&gclid=`{"{"}{"{"}gclid{"}"}{"}"}}`
↑
Pre-encoded in template
Facebook Ads
URL Parameters:
utm_source=facebook&utm_campaign=save%26win
↑
Encoded & in value
Email HTML
<a href="https://site.com?utm_campaign=buy%26save&utm_source=email">
Click Here
</a>
<!-- Encoded & in HTML is preserved -->Validation Script
function validateAmpersands(url) {
const errors = [];
try {
const urlObj = new URL(url);
const rawQuery = url.split('?')[1] || '';
// Check each UTM parameter
['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term'].forEach(key => {
const value = urlObj.searchParams.get(key);
if (value) {
// Check if raw query has unencoded & in this parameter's value
const paramPattern = new RegExp(`${"{"}{"{"}key{"}"}{"}"}}=([^&]*)`);
const match = rawQuery.match(paramPattern);
if (match) {
const rawValue = match[1];
// If contains & but not %26, it's unencoded
if (rawValue.includes('&') && !rawValue.includes('%26')) {
errors.push({
parameter: key,
issue: 'Contains unencoded &',
current: value,
fix: encodeURIComponent(value)
});
}
}
}
});
} catch (error) {
errors.push({ issue: 'Invalid URL', message: error.message });
}
return {
valid: errors.length === 0,
errors
};
}
// Usage
const url = 'site.com?utm_campaign=save&win';
const result = validateAmpersands(url);
if (!result.valid) {
console.log('❌ Issues found:');
result.errors.forEach(err => {
console.log(` ${err.parameter}: "${err.current}" → "${err.fix}"`);
});
}Alternative Solutions
Option 1: Replace with "and"
Instead of encoding, replace & with word "and":
❌ BEFORE:
utm_campaign=buy&save
✅ AFTER:
utm_campaign=buy-and-save
Easier to read, no encoding needed
Option 2: Remove Ampersand
❌ BEFORE:
utm_campaign=buy&save
✅ AFTER:
utm_campaign=buysave
Shortest option, but less readable
Option 3: Use Different Separator
❌ BEFORE:
utm_campaign=shoes&boots
✅ AFTER:
utm_campaign=shoes-boots
utm_campaign=shoes_boots
utm_campaign=shoes.boots
All valid, no encoding needed
Testing Checklist
After fixing:
✅ Visual check
Look at URL - & in values should be %26
✅ Browser console test
new URL('your-url').searchParams.get('utm_campaign')
Should show decoded value with &
✅ GA4 Real-Time test
Visit URL → Check GA4 Realtime
Campaign should show complete value
✅ Cross-platform test
Test on desktop & mobile
Different browsers
Verify consistent results
✅ 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
When should I encode & and when should I leave it?
Encode & when it's PART OF a parameter value. Leave & between parameters as-is.
What if I have multiple & symbols in one value?
Encode all of them:
buy&save&win → buy%26save%26win
Does encodeURIComponent() handle this automatically?
Yes. encodeURIComponent('save&win') returns 'save%26win'.
What if my platform shows %26 literally in ads?
The platform displays encoded URL. Users will see decoded version after clicking. Test by actually clicking the link.
Conclusion
Fix unencoded & in UTM parameters in 3 steps:
- Find & INSIDE parameter values
- Replace with %26
- Test in browser and GA4
❌ utm_campaign=save&win
✅ utm_campaign=save%26win
Use encodeURIComponent() to automatically encode all special characters.
Technical Reference: Ampersand Not Encoded Validation Rule