Appending the referrer’s query string to the current URL

Friend-of-the-blog JD asked a question on Marketo Nation that I thought was worth a quick writeup here as well.

I'm looking to keep URL query string parameters when passed from my 3rd party (https) page to my Marketo LP (also https) before Munchkin loads so I can trigger off the “Visits Web Page” trigger.

Getting a little more detail from JD offline, I learned there was some multi-page internal navigation he couldn’t get rid of. Google Ads are pointed to https:‍//www.example.com/product1?utm_campaign=campaign01 but there’s no form on /product1 itself. Instead, /product1 has a big-button link to https:‍//pages.example.com/product1.html where the form lives.

Thus the desire to transplant the query string from the first page to the second.

Oh, and the first page couldn’t be readily changed (owned by another team — with change requests, code freezes, etc. sitting in the way). Only the second page could be modified.

It’s also good that he mentioned both pages are running over SSL (https), because otherwise there could be old-school browser security measures getting in the way.[1]

The goal is particularly easy to meet ’cuz you don’t need to parse the query string — that is, parse its inner key=value pairs — at all! Just isolate one whole query string and plop it onto the end of the other query string, as-is.

For that we use a by-now typical pattern:

  1. create a couple of built-in Location objects
  2. set one Location to the referrer URL (document.referrer), the other to the current page URL (document.location.href)
  3. append the referrer’s search property — that's the query string, guaranteed to be correctly isolated by the browser’s built-in code — to the current search, just removing the leading question mark
  4. replace the current URL without refreshing

Just make sure you run the below code before loading Munchkin. On a Marketo LP, putting it in the <head> will suffice, since Munchkin loads at the end of the <body>.

(function () {
  let referrerLoc = document.createElement("a"),
      docLoc = document.createElement("a");

  referrerLoc.href = document.referrer;

  // if referrer has a non-empty qs, transplant it to current doc
  if (referrerLoc.search.length > 1) {
    docLoc.href = document.location.href;
    docLoc.search += (docLoc.search ? "&" : "") + referrerLoc.search.substring(1);
    history.replaceState({}, undefined, docLoc.href);
  }
})();
Notes

[1] By default, the referrer is not passed from secure site A (https) to an insecure site B (http), in order to preserve the security of site A. This default behavior can be changed by adding the newish <meta name="referrer"> tag to site A; that same <meta> tag could also be tweaked to strip the query string from the referrer. This post assumes there’s no technical barrier to reading the document.referrer on site B, the LP.