troubleshootingUpdated 2025

Fix Duplicate UTM Params: Remove Redundant Parameters in 3 Steps

URL has same UTM parameter twice? Learn how to identify, remove, and prevent duplicate parameters. Includes JavaScript cleanup script.

7 min readtroubleshooting

Your URL has utm_source=facebook appearing twice. GA4 tracking is unpredictable.

Here's the 3-step fix to remove duplicates and restore reliable 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

Code
❌ DUPLICATE:
?utm_source=facebook&utm_medium=cpc&utm_source=instagram
 ↑                                   ↑
 Same parameter twice

Result: GA4 behavior unpredictable

Quick Fix (3 Steps)

Step 1: Find Which Value to Keep (60 seconds)

Code
Look at your URL:
?utm_source=facebook&utm_medium=cpc&utm_source=instagram

Ask: Which value is correct?
- facebook (first occurrence)?
- instagram (last occurrence)?
- Neither (need different value)?

Decision determines which to keep

Step 2: Remove Duplicate (30 seconds)

Code
❌ BEFORE:
?utm_source=facebook&utm_medium=cpc&utm_source=instagram

✅ AFTER (keeping first):
?utm_source=facebook&utm_medium=cpc

✅ AFTER (keeping last):
?utm_source=instagram&utm_medium=cpc

Manual edit: Delete the incorrect parameter occurrence.

Step 3: Verify in GA4 Real-Time (30 seconds)

Code
1. Visit corrected URL
2. Open GA4 → Realtime
3. Check "Traffic acquisition"
4. Verify source shows single correct value

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

Get Your Free Audit Report

Automated Fix (JavaScript)

For Single URL

Javascript
function removeDuplicateUtm(url, keepFirst = true) {
    const urlObj = new URL(url);
    const params = new URLSearchParams();
    const seen = new Set();
 
    for (const [key, value] of urlObj.searchParams.entries()) {
        if (!seen.has(key)) {
            params.append(key, value);
            seen.add(key);
        } else if (!keepFirst) {
            // Update to last value if keepFirst=false
            params.set(key, value);
        }
    }
 
    urlObj.search = params.toString();
    return urlObj.toString();
}
 
// Usage
const broken = 'https://site.com?utm_source=facebook&utm_campaign=spring&utm_source=instagram';
 
// Keep first occurrence
console.log(removeDuplicateUtm(broken, true));
// Output: https://site.com?utm_source=facebook&utm_campaign=spring
 
// Keep last occurrence
console.log(removeDuplicateUtm(broken, false));
// Output: https://site.com?utm_source=instagram&utm_campaign=spring

For Multiple URLs (Batch Processing)

Javascript
function batchFixDuplicates(urls) {
    return urls.map(url => {
        try {
            return removeDuplicateUtm(url, true);
        } catch (error) {
            console.error(`Failed to process: ${"{"}{"{"}url{"}"}{"}"}}`, error);
            return url; // Return original if fix fails
        }
    });
}
 
// Usage
const brokenUrls = [
    'site.com?utm_source=fb&utm_source=ig',
    'site.com?s=email&utm_campaign=a&utm_campaign=b',
    'site.com?utm_medium=cpc&other=x&utm_medium=paid'
];
 
const fixed = batchFixDuplicates(brokenUrls);
console.log(fixed);
// All duplicates removed, first occurrence kept

Browser Console Quick Fix

Javascript
// Paste this in browser console when on the broken URL
(function() {
    const url = new URL(window.location.href);
    const params = new URLSearchParams();
    const seen = new Set();
 
    for (const [key, value] of url.searchParams.entries()) {
        if (!seen.has(key)) {
            params.append(key, value);
            seen.add(key);
        }
    }
 
    url.search = params.toString();
    window.location.href = url.toString();
})();
 
// Automatically redirects to cleaned URL

Platform-Specific Fixes

Code
Problem: Value Tracking template duplicates UTMs

Fix:
1. Final URL: https://site.com?utm_source=google&utm_medium=cpc
2. Tracking template: `{"{"}{"{"}lpurl{"}"}{"}"}}`?gclid=`{"{"}{"{"}gclid{"}"}{"}"}}`
   (Don't add utm_source again in tracking template)

✅ Result: site.com?utm_source=google&utm_medium=cpc&gclid=123

Facebook Ads

Code
Problem: URL Parameters field duplicates existing UTMs

Fix:
1. Destination URL: https://site.com?utm_source=facebook
2. URL Parameters: utm_medium=paid&utm_campaign=spring
   (Don't repeat utm_source)

✅ Result: site.com?utm_source=facebook&utm_medium=paid&utm_campaign=spring

Email Platforms (Mailchimp, Klaviyo)

Code
Problem: Template concatenation duplicates parameters

Fix:
Check if base URL has UTMs before adding:

❌ WRONG:
<a href="{`{"{"}{"{"}landing_page{"}"}{"}"}}`}?utm_source=email&utm_campaign={"{"}{"{"}campaign_name{"}"}{"}"}}">
     If landing_page already has utm_source, you get duplicates

✅ RIGHT:
Use platform's merge tags correctly, or ensure landing_page is clean base URL

Common Patterns

Pattern 1: First Correct, Second Wrong

Code
?utm_source=facebook&utm_campaign=spring&utm_source=social

Fix: Remove second utm_source
Result: ?utm_source=facebook&utm_campaign=spring

Pattern 2: First Wrong, Second Correct

Code
?utm_source=website&utm_campaign=spring&utm_source=facebook

Fix: Remove first utm_source
Result: ?utm_source=facebook&utm_campaign=spring

Or manually reorder:
?utm_source=facebook&utm_campaign=spring

Pattern 3: Both Wrong

Code
?utm_source=abc&utm_campaign=spring&utm_source=xyz

Fix: Remove both, add correct value
Result: ?utm_source=facebook&utm_campaign=spring

Pattern 4: Multiple Duplicates

Code
?utm_source=a&utm_source=b&utm_campaign=x&utm_campaign=y&utm_source=c

Fix: Remove all duplicates systematically
Result: ?utm_source=a&utm_campaign=x
(Keeps first occurrence of each)

Validation After Fix

Javascript
// Verify no duplicates remain
function verifyNoDuplicates(url) {
    const params = new URL(url).searchParams;
    const counts = {};
 
    for (const [key] of params.entries()) {
        counts[key] = (counts[key] || 0) + 1;
    }
 
    const duplicates = Object.entries(counts)
        .filter(([, count]) => count > 1)
        .map(([key]) => key);
 
    if (duplicates.length > 0) {
        console.error('❌ Duplicates still exist:', duplicates);
        return false;
    }
 
    console.log('✅ No duplicates found');
    return true;
}
 
// Usage
const url = 'https://site.com?utm_source=facebook&utm_campaign=spring';
verifyNoDuplicates(url);
// ✅ No duplicates found

Prevention (After Fixing)

1. Use URLSearchParams .set() Method

Javascript
// ✅ CORRECT: .set() replaces instead of duplicating
const url = new URL('https://site.com');
url.searchParams.set('utm_source', 'facebook');
url.searchParams.set('utm_medium', 'cpc');
 
// If you call .set() again with same key, it replaces:
url.searchParams.set('utm_source', 'instagram'); // Replaces 'facebook'
 
console.log(url.toString());
// https://site.com?utm_source=instagram&utm_medium=cpc

2. Check Before Adding

Javascript
// ✅ CORRECT: Check existence before appending
function safeAddUtm(url, key, value) {
    const urlObj = new URL(url);
 
    if (urlObj.searchParams.has(key)) {
        console.warn(`${"{"}{"{"}key{"}"}{"}"}} already exists, replacing...`);
        urlObj.searchParams.set(key, value);
    } else {
        urlObj.searchParams.append(key, value);
    }
 
    return urlObj.toString();
}

3. Validate Before Launch

Javascript
// Add to pre-launch checklist
function preLaunchCheck(url) {
    const checks = [];
 
    // Check for duplicates
    const params = new URL(url).searchParams;
    const utmParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term'];
 
    utmParams.forEach(param => {
        const count = params.getAll(param).length;
        if (count > 1) {
            checks.push(`❌ Duplicate ${"{"}{"{"}param{"}"}{"}"}} (${"{"}{"{"}count{"}"}{"}"}} occurrences)`);
        } else if (count === 1) {
            checks.push(`✅ ${"{"}{"{"}param{"}"}{"}"}} OK`);
        }
    });
 
    return checks;
}

✅ 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

FAQ

Which value should I keep if both are different?

Choose the value that matches your campaign intent. If utm_source=facebook and utm_source=instagram, keep the one matching where the link is actually placed.

Can I use regex to fix duplicates?

URLSearchParams is safer. Regex can break if URL structure varies.

What if the duplicate has the same value?

Code
?utm_source=facebook&utm_campaign=spring&utm_source=facebook

Still remove one. Having duplicates, even with same value, can cause parsing inconsistencies.

How do I prevent this in URL builders?

Use .set() instead of .append() in URLSearchParams. .set() automatically replaces duplicates.

Does GA4 always use the first value or last value?

Inconsistent. Different browsers and GA4 versions may parse duplicates differently. Some use first, some use last, some concatenate. This unpredictability is why duplicates must be removed.

Can duplicates affect other analytics tools besides GA4?

Yes. Most analytics platforms exhibit undefined behavior with duplicate parameters. Some ignore duplicates, some use first value, some use last. For consistent cross-platform tracking, remove all duplicates.

What if my CMS automatically adds UTMs and I manually add them too?

Check your CMS settings. Disable automatic UTM appending if you're manually adding them. Or, use dynamic templates that check for existing UTMs before adding.

How do I fix duplicates in shortened URLs (bit.ly, etc.)?

You can't edit a shortened URL after creation. Create a new shortened URL with cleaned parameters. Update all placements. Most shorteners show analytics, so check which version gets more clicks before deprecating the old one.

Can duplicate parameters cause GA4 to drop sessions entirely?

Rare, but possible. Malformed URLs with many duplicates may cause GA4's measurement protocol to reject the hit. More commonly, you just get inconsistent attribution.

What about duplicate non-UTM parameters?

Same issue. Any duplicate query parameter can cause parsing problems. Clean all duplicates, not just UTMs.

How often should I audit for duplicate parameters?

Monthly. Export your top campaign URLs, run the validation script, fix any duplicates. Add to your monthly tracking health check.

Real-World Example: Email Template Concatenation

Company: E-commerce retailer Platform: Klaviyo email marketing Campaign: Weekly newsletter

Problem: Email template had base URL with existing UTMs, then template added more:

Html
<a href="https://shop.com?utm_source=email&utm_campaign={{campaign.name}}?utm_source=newsletter&utm_medium=email">

Result:

Code
https://shop.com?utm_source=email&utm_campaign=weekly?utm_source=newsletter&utm_medium=email

Issues found:

  • utm_source appears twice (email, newsletter)
  • Invalid ? in middle of query string
  • GA4 showed inconsistent attribution

Fix applied:

Html
<!-- Cleaned template -->
<a href="https://shop.com?utm_source=newsletter&utm_medium=email&utm_campaign={{campaign.name}}">

Result:

  • Single utm_source value
  • Consistent GA4 attribution
  • 4,200 weekly email clicks properly tracked

Conclusion

Fix duplicate UTM parameters in 3 steps:

  1. Identify which value to keep (first, last, or neither)
  2. Remove duplicate parameter
  3. Verify in GA4 Real-Time

Prevention: Use URLSearchParams.set() method, which replaces instead of duplicating.

Javascript
url.searchParams.set('utm_source', 'facebook'); // Never creates duplicates

Technical Reference: Duplicate UTM Parameters Validation Rule

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.