Inherit Incoming URL Query Parameters Onto an Off-Site Link URL
Julius Fedorovicius wrote the definitive technique for carrying incoming campaign URL query parameters onto links elsewhere on a page — read his original post, "Transfer UTM Parameters From One Page To Another with GTM," first. This recipe takes that same idea and shifts the timing: rather than decorating links the moment a visitor lands, it stores the incoming campaign values to session storage on arrival, then rewrites an off-site link's URL three or four pageviews later — whenever the visitor finally reaches the page containing that link.
This builds on an earlier technique of mine, "Pass UTM URL Query Marketing Parameters to Contact / Lead Form."
Step 1: Capture the Incoming UTMs to Session Storage
The first tag loops through the landing page's URL looking for UTM codes and writes each one it finds to sessionStorage. If there are other URL query parameters beyond the standard UTM set that you want to track, simply add them to the array.
<script type="text/javascript">
// Parse the URL
function getParameterByName(name) {
name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
results = regex.exec(location.search.toLowerCase());
return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
}
var queryArray = ['utm_medium', 'utm_source', 'utm_campaign', 'utm_content', 'utm_term'];
queryArray.forEach(function(item) {
var itemValue = '';
try {
itemValue = getParameterByName(item);
} catch (err) {
itemValue = '';
}
if (typeof(itemValue) == 'undefined' || itemValue == null) { }
if (itemValue.search(/[0-9A-Za-z]+/) >= 0) {
sessionStorage.setItem(item, itemValue);
}
});
</script>
The trigger for this tag is any pageview where the URL contains a question mark — the tell-tale sign that URL query parameters are present to capture.
Step 2: Rewrite the Off-Site Link From Session Storage
The second piece is a variation on Julius' original technique. The structure of the decoration logic is unchanged; what's different is the small helper function at the bottom, which now reads from sessionStorage instead of pulling straight off the current URL — because by the time this tag fires, the UTM values are no longer on the address bar at all. They were captured pages ago in Step 1.
<script>
// Inherit UTMs by Julius Fedorovicius
(function() {
var domainsToDecorate = [
'abcd1234.com', //add or remove domains (without https or trailing slash)
'zyxw9876.com'
],
queryParams = [
'utm_medium', //add or remove query parameters you want to transfer
'utm_source',
'utm_campaign',
'utm_content',
'utm_term'
]
// do not edit anything below this line
var links = document.querySelectorAll('a');
// check if links contain domain from the domainsToDecorate array and then decorates
for (var linkIndex = 0; linkIndex < links.length; linkIndex++) {
for (var domainIndex = 0; domainIndex < domainsToDecorate.length; domainIndex++) {
if (links[linkIndex].href.indexOf(domainsToDecorate[domainIndex]) > -1 && links[linkIndex].href.indexOf("#") === -1) {
links[linkIndex].href = decorateUrl(links[linkIndex].href);
}
}
}
// decorates the URL with query params
function decorateUrl(urlToDecorate) {
urlToDecorate = (urlToDecorate.indexOf('?') === -1) ? urlToDecorate + '?' : urlToDecorate + '&';
var collectedQueryParams = [];
for (var queryIndex = 0; queryIndex < queryParams.length; queryIndex++) {
if (getQueryParam(queryParams[queryIndex])) {
collectedQueryParams.push(queryParams[queryIndex] + '=' + getQueryParam(queryParams[queryIndex]))
}
}
return urlToDecorate + collectedQueryParams.join('&');
}
// function retrieves the values from session storage
function getQueryParam(name) {
if (name in sessionStorage) {
var whichParam = sessionStorage.getItem(name);
if (whichParam.search(/[0-9A-Za-z]+/) >= 0) {
return whichParam;
}
}
}
})();
</script>
A few implementation notes:
domainsToDecoratelists the off-site hostnames (without the protocol or a trailing slash) whose links should be rewritten when found anywhere on the page.queryParamslists the parameter names to append — by default the five standard UTM fields, but freely extensible to anything else you stored in Step 1.- The script skips any link that already contains a fragment identifier (
#), since appending query parameters after a hash fragment wouldn't behave as expected. - The trigger for this tag is DOM Ready, so the rewrite happens as soon as the page's links exist, well before the visitor has a chance to click one.
Why the Two-Step Approach Matters
Decorating a link with the current URL's query parameters only works if those parameters are still present on the current URL — which they won't be, three or four pageviews into a session. By separating capture (Step 1, on landing) from decoration (Step 2, wherever the off-site link happens to live), the UTM values survive however many pages the visitor navigates through in between, and still end up correctly appended the moment they're about to leave the site through that link.
This post is a Blogger rewrite of an earlier piece originally published on Weebly.
Comments
Post a Comment