Beautifying fields like ‘Last Form URL’ by stripping uninteresting query params

The URL of each Filled Out Form is a key attribution point. You can easily save the full value to a custom field like so:

MktoForms2.whenReady(function(readyForm){
   readyForm.onSubmit(function(submittingForm){      
      submittingForm.addHiddenFields({
         LastFormURL: document.location.href
      });
   });
});

But that code snippet — I’m guilty of suggesting it myself! — has a big flaw.

Form URLs can be very long and cluttered with uninteresting params: Google’s gclid=CjwKCAiArLyuBhA7EiwA-qo80BByTqrQJ3DXT4DiOD7M9LzadNLI-8ChtxbBbfVQmU, Marketo’s own mkt_tok=OTgzLUpWSi0wODgAAAGQm3slWTv-ULsVV8gg899ovY5Qu7GOGoW2rQj7nA1W0zpVBpOQC3J7vmp5mkWMta and so on.[1]

The problem is more than cosmetic. If you’re using a String field instead of a Textarea, that’s limited to 255 characters. So if too many long + uninteresting params come first in the query string, you lose the interesting data completely. And even when the whole thing fits, the URLs look shoddy in reports.

It’s easy to strip the URL down to bare-essential query params before filling the hidden field, thanks to the magic of URLSearchParams.

You can do it one of two ways, either list the params you want, discarding all others:

MktoForms2.whenReady(function(readyForm){
   readyForm.onSubmit(function(submittingForm){
      let reducedLocationURL = new URL(document.location.href);
      let keepParams = ["wanted_param_1","wanted_param_3"];
      Array.from(reducedLocationURL.searchParams.keys()).forEach( key => {
         if( !keepParams.includes(key) ) {
            reducedLocationURL.searchParams.delete(key);
         }
      });

      submittingForm.addHiddenFields({
         LastFormURL: reducedLocationURL.href
      });
   });
});

Or list the specific params you don’t want, keeping all others:

MktoForms2.whenReady(function(readyForm){
   readyForm.onSubmit(function(submittingForm){
      let reducedLocationURL = new URL(document.location.href);
      let discardParams = ["unwanted_param_2","unwanted_param_4"];
      Array.from(reducedLocationURL.searchParams.keys()).forEach( key => {
         if( discardParams.includes(key) ) {
            reducedLocationURL.searchParams.delete(key);
         }
      });

      submittingForm.addHiddenFields({
         LastFormURL: reducedLocationURL.href
      });
   });
});

Why not sort ’em too?

To tidy up even more, add this line to sort the query params alphabetically by name:

reducedLocationURL.searchParams.sort();

That’ll make both utm_source=sourcy&utm_campaign=campy and utm_campaign=campy&utm_source=sourcy normalize to utm_campaign=campy&utm_source=sourcy. Makes sense, since they obviously have the same business meaning.[2]

Notes

[1] gclid is meaningful to Google Ads, of course, but not in the context of “Which URL was someone on when they filled out a form?”

[2] Yes, query params are technically ordered. But that doesn’t mean the order makes any difference on a business level. Apps that consume query strings almost never take order into account, and URLs are easier to compare when there’s a consistent order.