Keeping a clean Address Bar while campaign tracking

Campaign tracking in Google Analytics using UTM parameters is essential to many online businesses that pay for advertising or run email campaigns. However, the tracking system creates ugly URLs that can get propagated around the internet. Here I show how you can safely clean up those UTM parameters after they have been tracked in Google Analytics.

Here are some guides on different ways to add the code:

By Hand

If you hand code your Google Analytics, then all you need to do is add this at some point after the pageview command:

<script type="text/javascript">
var utmRemoverRun = false;
function utmRemover() {
	if (!utmRemoverRun) { // only run once
	utmRemoverRun = true;
	var cleanSearch = window.location.search
		.replace(/utm_[^&]+&?/g, '') // removes utm_xxx parameters
		.replace(/&$/, '')  // removes & if last character
		.replace(/^\?$/, '')  // removes ? if only remaining character
		;
	// some pass utm_xxxx in the hash	
	var cleanHash = window.location.hash
		.replace(/utm_[^&]+&?/g, '') // removes utm_xxx parameters
		.replace(/&$/, '')  // removes & if last character
		.replace(/^\#$/, '')  // removes # if only remaining character
		;
		
	window.history.replaceState({}, '', window.location.pathname + cleanSearch + cleanHash);
	}
};
setTimeout(utmRemover, 2000); // remove after 2 second
// These need to run after the pageview command 
if (typeof ga !== 'undefined') ga(utmRemover);  // remove after normal Analytics has run
if (typeof __gaTracker !== 'undefined') __gaTracker(utmRemover); // remove after Yoast Analytics has run
</script>

The UTM remover function is added to the ga queue. As long as it is after the pageview command it will remove the parameters after they have been used. I'd recommend adding this code to the end of the page. Just in-case Analytics is not working I also remove the parameters after 2 seconds.

I've also added a command to make it work with the Yoast Analytics plugin.

WordPress

Here's a variation of the code that you can insert into the functions.php file or a plugin.

function utm_remover_script() {
	$output="
<script type=\"text/javascript\">
var utmRemoverRun = false;
function utmRemover() {
	if (!utmRemoverRun) { // only run once
	utmRemoverRun = true;
	var cleanSearch = window.location.search
		.replace(/utm_[^&]+&?/g, '') // removes utm_xxx parameters
		.replace(/&$/, '')  // removes & if last character
		.replace(/^\?$/, '')  // removes ? if only remaining character
		;
	// some pass utm_xxxx in the hash
	var cleanHash = window.location.hash
		.replace(/utm_[^&]+&?/g, '') // removes utm_xxx parameters
		.replace(/&$/, '')  // removes & if last character
		.replace(/^\#$/, '')  // removes # if only remaining character
		;
		
	window.history.replaceState({}, '', window.location.pathname + cleanSearch + cleanHash);
	}
};
setTimeout(utmRemover, 2000); // remove after 2 second
// These need to run after the pageview command 
if (typeof ga !== 'undefined') ga(utmRemover);  // remove after normal Analytics has run
if (typeof __gaTracker !== 'undefined') __gaTracker(utmRemover); // remove after Yoast Analytics has run
</script>
	";
	echo $output;
}
add_action( 'wp_footer', 'utm_remover_script' );

Google Tag Manager

With the Tag Manager we are going to call the function via a hitcallback on the pageview. First we need to define a Custom JavaScript Variable called "Function - Remove UTM Parameters" that will execute our code:

function() {
	// Returns a function to strip out UTM parameters. So can be used as a function based parameter
	// when GA has finished it's pageview
	return function() {
		if (!window.history.replaceState) { return; }; 
		var cleanSearch = window.location.search
			.replace(/utm_[^&]+&?/g, '') // removes utm_xxx parameters
			.replace(/&$/, '')  // removes & if last character
			.replace(/^\?$/, '')  // removes ? if only remaining character
			;
		
		// some pass utm_xxxx in the hash
		var cleanHash = window.location.hash
			.replace(/utm_[^&]+&?/g, '') // removes utm_xxx parameters
			.replace(/&$/, '')  // removes & if last character
			.replace(/^\#$/, '')  // removes # if only remaining character
			;
		window.history.replaceState({}, '', window.location.pathname + cleanSearch + cleanHash);
	}
}

Next, we need to add a call to it from the Google Analytics Tag used to cause the pageview. In that tag add a field called "hitCallback" with the value "{{Function - Remove UTM Parameters}}".

As an extra measure you can add this tag to all pages, which will remove the parameters after 2 seconds.

<script type="text/javascript">
function utmRemover() {
	var cleanSearch = window.location.search
		.replace(/utm_[^&]+&?/g, '') // removes utm_xxx parameters
		.replace(/&$/, '')  // removes & if last character
		.replace(/^\?$/, '')  // removes ? if only remaining character
		;
	// some pass utm_xxxx in the hash
	var cleanHash = window.location.hash
		.replace(/utm_[^&]+&?/g, '') // removes utm_xxx parameters
		.replace(/&$/, '')  // removes & if last character
		.replace(/^\#$/, '')  // removes # if only remaining character
		;
		
	window.history.replaceState({}, '', window.location.pathname + cleanSearch + cleanHash);
};
setTimeout(utmRemover, 2000); // remove after 2 second
</script>