Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
userscript: Drop the UTM params from a URL when the page loads
// ==UserScript==
// @name UTM param stripper
// @author Paul Irish
// @namespace http://github.com/paulirish
// @version 1.2
// @description Drop the UTM params from a URL when the page loads.
// @extra Cuz you know they're all ugly n shit.
// @include http*://*
// ==/UserScript==
// Update:
// In chrome, it's better to just install the UTM stripper chrome extension:
// https://chrome.google.com/webstore/detail/google-analytics-paramete/jbgedkkfkohoehhkknnmlodlobbhafge
// It is great and open source: github.com/mihaip/utm-stripper
// You can also install this greasemonkey script if you really want.
// download this script. go to about:extensions. Turn on developer mode and drag and drop
// this file onto the window. it'll install it. hopefully.
// lastly, if your site / marketing funnel uses these tracking tokens. you can clean up your users URLs
// look at the comments below on correct installation to integrate with __gaq.push
if (/utm_/.test(location.search) && window.history.replaceState){
// thx @cowboy for the revised hash param magic.
var oldUrl = location.href;
var newUrl = oldUrl.replace(/\?([^#]*)/, function(_, search) {
search = search.split('&').map(function(v) {
return !/^utm_/.test(v) && v;
}).filter(Boolean).join('&'); // omg filter(Boolean) so dope.
return search ? '?' + search : '';
});
if ( newUrl != oldUrl ) {
window.history.replaceState({},'', newUrl);
}
}
@oyvindkinsey

This comment has been minimized.

Copy link

oyvindkinsey commented May 20, 2011

Sure that works?
I'm pretty sure a map(-> return bool).filter(..)) will return an array of .. well, booleans..

Stick with the basics I say,

var newSearch = location.search.replace(/utm_.*?(&|$)/g,""), newSearch = newSearch.length > 1 ? newSearch : "";
newSearch != location.search && window.history.replaceState({},'', location.href.replace(location.search, newSearch));

;)

@paulirish

This comment has been minimized.

Copy link
Owner Author

paulirish commented May 20, 2011

yup that works.

you're right that it does return an array of bools...

and the Boolean constructor is treated as a function with, an undefined argument, returns the false boolean. so it's a quick way to shoot a return false callback into [].filter()

its all quite clever.

@oyvindkinsey

This comment has been minimized.

Copy link

oyvindkinsey commented May 20, 2011

Doh! It was the !/^utm_/.test(v) && v line that fooled me, this of course returns v when the first expression is true, not the composite boolean value of the entire expression...
But

search = search.split('&').filter(function(v) {
    return !/^utm_/.test(v);
}).join('&');

works just as well... no need for map ;)

@Charudatta

This comment has been minimized.

Copy link

Charudatta commented May 21, 2011

Clever piece of code, but we cannot drop this into a webpage (or might also be a bad idea for the extension),

  1. This is not bound to an event, so are you sure GA will actually register the query string parameter to attribute this session to th campaign?
  2. Also, ideally it should not completely remove the params, but replace it with new values after the original params are registered by GA. This will be useful, so that if someone now shares this link or bookmarks it, we can correctly attribute the other visits.

Ideal way of doing this is to use, _gaq.push(function(){removeQueryString();}) //comes after the track page view method is called.

@kurtextrem

This comment has been minimized.

Copy link

kurtextrem commented May 21, 2011

Thank you so much, paul! I hate those utm things

@cowboy

This comment has been minimized.

Copy link

cowboy commented May 21, 2011

@oyvindkinsey lol I got so carried away with .map that I didn't even think, thanks!

@lachezar

This comment has been minimized.

Copy link

lachezar commented Feb 1, 2013

+1 on the statement that window.history.replaceState({},'', newUrl) must appear inside of _gaq.push otherwise the __utm.gif does not carry the correct parameters.

@raulaudelo

This comment has been minimized.

Copy link

raulaudelo commented Mar 15, 2013

script works great in Chrome + FireFox. Anyone have luck in IE 8 and above?

@elidickinson

This comment has been minimized.

Copy link

elidickinson commented Jun 6, 2013

@raulaudelo - IE8 (and 9) do not support the session history API: http://caniuse.com/#search=history

@SamHasler

This comment has been minimized.

Copy link

SamHasler commented Nov 29, 2016

// @include        /^http.*\?.*[?&]utm_.*$/
@timelf123

This comment has been minimized.

Copy link

timelf123 commented Apr 3, 2017

ga('send', 'pageview', { 'hitCallback': removeUtms });

@vilav

This comment has been minimized.

Copy link

vilav commented Dec 12, 2017

@paulirish is this codeblock still valid with the new ga.js

@timelf123: is that line of code a replacement for the script or a add-on to the GA code to better work with this script?

Thanks!

@grand-lotus-iroh

This comment has been minimized.

Copy link

grand-lotus-iroh commented Mar 12, 2019

If you load example website https://mashable.com/ you will still see /article/bla-bla-bla/?utm_campaign=hp-r-2&utm_source=internal&utm_medium=onsite being loaded after each link when you hover article.

Perhaps we can strip / rewrite source code on page load? Any idears?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.