Skip to content
Free Tool Arena

How-To & Life · Guide · Developer Utilities

How to clean tracking URLs

Common tracking params (utm_*, fbclid, gclid, mc_cid), when to strip them, when to keep them, and building a safe cleaner for shared links.

Updated April 2026 · 6 min read

Every link passed around the web today arrives pre-loaded with tracking cruft: fbclid from Facebook, gclid from Google Ads, mc_cid from Mailchimp, _ga from cross-domain Google Analytics, and the five utm_* parameters for good measure. None of these change what page you land on; all of them clutter the URL, leak marketing data to whoever you share the link with, and create duplicate-content headaches on your own analytics. Cleaning them up takes a small rule set and a little care — some parameters are data you control, others are added by third parties downstream. This guide covers the most common tracking parameters and who attaches them, the difference between cleaning URLs you share and canonicalizing URLs on your own site, a safe allow-list vs block-list approach, the privacy case for stripping them, and the corners where cleaning breaks things.

Advertisement

The usual suspects

A non-exhaustive tour of the parameters that accumulate on real-world URLs.

utm_source, utm_medium, utm_campaign, utm_term, utm_content — the Urchin/Google Analytics parameters you or your marketing team attached. Safe to strip after analytics have fired.

gclid, gclsrc, dclid, wbraid, gbraid — Google Ads click IDs. Auto-appended by Google Ads when auto-tagging is on. Needed by GA4 to stitch clicks to Ads, but only on arrival — once captured server-side they are dead weight.

fbclid — Facebook click ID, added by Facebook to any outbound link when the user clicks. Used for attribution back to Facebook Ads.

msclkid — Microsoft/Bing Ads click ID.

ttclid — TikTok click ID.

li_fat_id — LinkedIn click ID.

twclid — X/Twitter click ID.

mc_cid, mc_eid — Mailchimp campaign ID and encoded subscriber ID. The second can identify a real person back to their list record.

_ga, _gl — Google Analytics cross-domain linker parameters. Attached when a user clicks a link decorated by the GA linker across your properties.

yclid — Yandex click ID.

oly_anon_id, oly_enc_id — Omeda identifiers common on publishing sites.

Clean URLs you share vs URLs on your site

Two very different problems sit under the same “cleaning” umbrella.

Shareable URLs. When a user goes to copy the link from their address bar to send to a friend, they should not carry the referring campaign tags or the click ID the ad network added. The fix is client-side: after analytics fires on page load, rewrite the URL with history.replaceState to a clean version.

Canonical URLs on your site. Your pages should have one and only one canonical URL, regardless of which tracking variant brought the user in. Set a <link rel="canonical"> that points at the clean URL and make sure your sitemap, internal links, and OG tags use the same form. This prevents tracking variants from indexing as separate pages.

Strip-after-capture pattern

Let the tracking tools see the parameters exactly once, then remove them.

// Runs after analytics has read location.search
const TRACKING = new Set([
  'utm_source','utm_medium','utm_campaign','utm_term','utm_content',
  'gclid','gclsrc','dclid','wbraid','gbraid',
  'fbclid','msclkid','ttclid','li_fat_id','twclid','yclid',
  'mc_cid','mc_eid','_ga','_gl'
]);

const url = new URL(location.href);
const keep = new URLSearchParams();
for (const [k, v] of url.searchParams) {
  if (!TRACKING.has(k)) keep.append(k, v);
}
url.search = keep.toString();
history.replaceState(null, '', url.toString());

Runs once on load; does not trigger a navigation or break analytics. The address bar now shows the clean URL ready to copy.

Allow-list vs block-list

A block-list (remove these known-bad keys) is what most sites ship. It is forgiving — unknown parameters survive — but it needs maintenance as new platforms invent new click IDs.

An allow-list (keep only these keys) is stricter and self-maintaining. Any parameter not in the allowed set is stripped. Best for sites where the URL carries a small, fixed set of meaningful parameters (search, pagination, a filter or two) and everything else is tracking.

Large content sites tend to use block-lists; focused apps and e-commerce tend to use allow-lists.

Canonical tags do the SEO side

Even if you do not rewrite URLs client-side, a correct <link rel="canonical"> solves most search-engine-side duplication.

<link rel="canonical" href="https://example.com/pricing" />

With this in the head, Google understands that /pricing?utm_source=newsletter and /pricing?fbclid=abc123 are the same page as /pricing, and consolidates ranking signals onto the clean URL.

Referral spam and junk parameters

Beyond legitimate tracking, URLs pick up junk:

Referral spam — bots injecting fake campaigns to appear in your analytics. Symptoms: a UTM source you never set up (“semalt.com”, “buttons-for-website.com”), suddenly driving traffic. Filter at the analytics level, not the URL level.

Copy-paste accidents &amp; where & should be, extra question marks, trailing fragments from a doc paste. A strip-and-rebuild via URL() fixes most of it.

Bookmarking and archival

A URL a user bookmarks today might be reopened in six months. If the bookmark includes a one-time gclid, the ad network may reject it as expired or replay-attack-flag it. Rewriting to a clean URL ensures bookmarks stay valid long-term.

Do not strip everything blindly

Some query parameters carry real application state, and stripping them breaks the page.

Pagination: ?page=3. Needed for the content.

Search queries: ?q=keyboard. The whole point of the URL.

Filters and sort order: ?sort=price_asc&in_stock=1.

Auth/session tokens passed via URL (rare but happens with magic-link flows). Never strip before the receiving code has consumed them.

Privacy case for stripping

Tracking parameters leak across every system that touches the URL: browser history, proxy logs, referer headers, screenshots, shared clipboards. A mc_eid can identify an individual subscriber; an fbclid can be rejoined to a Facebook ad audience. Stripping them once they have served analytics is basic hygiene — Safari, Brave, and Firefox already strip known tracking parameters from outbound links by default, so cleaning proactively puts your URLs in line with where browsers are heading.

Common mistakes

Stripping before analytics fires. Your rewrite runs at page load, but GA4’s pageview hit may still be in flight. Run the strip after a gtag('event') acknowledgement, or with a short setTimeout, or via requestIdleCallback.

Forgetting canonical. Rewriting the address bar only helps humans. Search engines and social crawlers do not run your JavaScript before reading OG tags. Set a canonical link.

Stripping parameters you did not add. If a third-party embed relies on a query parameter your site does not know about, a strict allow-list will break it. Audit embeds before deploying an allow-list.

Breaking deep links. Mobile app deep-link schemes sometimes pass app-specific parameters through the web. An overzealous cleaner can strip the payload the app needs after it launches.

Stripping on every navigation. Run the clean on first load of the page, not on every SPA route change. Internal state you set via router (?tab=billing) is not tracking.

Doing it server-side with a 301. 301-ing ?utm_source=newsletter to the clean URL works but breaks the analytics hit entirely — the redirect happens before the JS that reads UTMs runs. Strip client-side after capture.

Run the numbers

Strip tracking parameters from any URL instantly with the URL cleaner. Pair with the query string parser when you want to see every parameter before deciding which to keep, and the URL parser for a full protocol/host/path breakdown alongside the query.

Advertisement

Found this useful?Email