Restoring the mighty mkt_tok

Update 2023-01-16: Added non-IE-compatible code since some years have gone by.

Ah, the mkt_tok. So wondrous, so little worried over... until you need it.

Until relatively recently, Marketo used to simply read the mkt_tok query parameter — the special lead-asset-campaign identifier that’s added to tracked links by default, or manually added in advanced configs — then leave it be.

But since mid-2019 (IIRC) the mkt_tok is promptly removed from the URL of a Marketo LP, using some automatically-injected JS, as a security measure. This makes it harder — though by no means impossible — to accidentally share a Pre-Fill-enabled form with another person.

(Note this doesn’t affect non-Marketo LPs, where mkt_tok isn’t touched. And remember, you can get Pre-Fill on non-Marketo LPs using my de facto standard method.)

But the mkt_tok value is useful in several ways. One is if you have a “Step 2” form on a follow-up LP, and you want that to have Pre-Fill, too.

Marketo doesn’t actually scrub the value from memory, of course (that would be fruitless). It just archives it in a special global variable window.__mktTokVal. So we can read it out of there and pop it back onto a URL — taking into account, of course, the reason it’s removed in the first place.

Do this

To be safe, only re-add the mkt_tok on the Thank You URL if a form is being submitted, i.e. with the expectation that the current page is about to be replaced. (So there’s no worry about the URL being shared with others.)


Do it in the Forms 2.0 onSuccess[1]:

MktoForms2.whenReady(function(form){
  form.onSuccess(function(vals,tyURL){
    if(window.__mktTokVal && history.replaceState){
      var tyLoc = document.createElement("a");
      
      tyLoc.href = tyURL;
      tyLoc.search += ( tyLoc.search ? "&" : "" ) + "mkt_tok=" + window.__mktTokVal;
      document.location = tyLoc;

      return false;
    }
    return true;
  });
});


If you don’t need to support Internet Explorer anymore:

MktoForms2.whenReady(function(mktoForm){
   mktoForm.onSuccess(function(submittedValues,originalThankYouHref){
      let thankYouUrl = new URL(originalThankYouHref);      
      
      thankYouUrl.searchParams.set("mkt_tok", window.__mktTokVal);
      document.location.href = thankYouUrl.href;
      
      return false;
   })
})

Now, a form on the Thank You page will also be Pre-Filled.

Don’t do this

Let me be clear: I don’t recommend re-adding the mkt_tok immediately on page load, because (a) you bring back the same security concern, and (b) you don’t get anything out of it. But this is how that would be done — just don’t blame me:

window.addEventListener("load",function(e){
  setTimeout(function(){
    if(window.__mktTokVal && history.replaceState){
      var restoredLoc = document.createElement("a");

      restoredLoc.href = document.location.href;
      restoredLoc.search += ( restoredLoc.search ? "&" : "" ) + "mkt_tok=" + window.__mktTokVal;
      history.replaceState({},null,restoredLoc.href);      
  }, 0);
});

About that setTimeout(0)...

Notice the JavaScript setTimeout function is used above but with a timeout of 0 milliseconds. This isn’t an arbitrary guess, as you often see in clown code less-than-professional code, but a deliberate and guaranteed way of running a function after all Load listeners have finished. I’m going to write another post about this soon.

So I remain vehemently opposed to the use of arbitrary timeouts — including Wait step-based guesswork in Marketo — as it cannot solve race conditions. But I’m not guessing here, lest you think you caught me violating my own standards☺


Notes

[1] Remember that this new onSuccess listener must cooperate with other custom onSuccess logic, if any.