Custom de-duplication: Create new cookie on form submit | Community
Skip to main content
New Participant
May 27, 2018
Solved

Custom de-duplication: Create new cookie on form submit

  • May 27, 2018
  • 1 reply
  • 6159 views

A customer is using a custom de-duplication logic (email address and an additional field). When a person is submitting a form, Marketo is only using this custom de-duplication check if the person is unknown. For known people, the cookie will "trump" the field values, when it comes to the dedupe logic. In most cases that's desirable and therefore the expected result.

However, in this specific case, we always want to use the custom de-duplication logic rather than the cookie. So, I tried to delete the existing cookie when a person submits the form and create a new cookie before the form is submitted (in the hope that Marketo would "connect" that newly created cookie with the person that was updated in the database (for tracking/pre-fill reasons)):

function deleteCookie(key, path, domain) {

  document.cookie =

    encodeURIComponent(key) +

    '=; expires=Thu, 01 Jan 1970 00:00:00 GMT' +

    (domain ? '; domain=' + domain : '') +

    (path ? '; path=' + path : '');

}

MktoForms2.whenReady(function(form) {

  form.onValidate(function(isValid) {

    if (!isValid) {

      return false;

    }

    deleteCookie('_mkto_trk', '/', 'DOMAIN');

    setTimeout(function() {

      Munchkin.createTrackingCookie(true);

    }, 10);

  });

});

The above code is quite simple, still has a couple of flaws but was just a proof of concept. It deletes the cookie but although I'm using createTrackingCookie() it's not creating a new cookie before the form is submitted (even if I prevent submitting the form with e.g. form.submittable(false);). While this code now forces Marketo to always use the custom dedupe logic (rather than the cookie) it prevents the tracking and pre-filling functionality (assumably because I'm unable to create a new cookie before the form is submitted)!?

Does anyone know how to create or force create a new tracking cookie before the form us submitted or why createTrackingCookie() is not working in this case? Maybe @Sanford Whiteman​?

Any help is greatly appreciated.

— Markus

This post is no longer active and is closed to new replies. Need help? Start a new post to ask your question.
Best answer by SanfordWhiteman

pre-filling functionality

First of all, you will break pre-fill if a page loads without an associated cookie.  The only way pre-fill works is if the page is requested with an already-associated cookie sent in the HTTP headers (or with mkt_tok in the query string). 

If you delete the cookie using JS in the page itself, that's by definition after the page loads. It doesn't disable pre-fill because the pre-fill JS object (mktoPreFillFields) is already in the page. You can manually clear the form values, of course. But if you don't do that, you'd get the pre-fill data from the initial page load (including hidden fields) re-posted with the form, regardless of whether there's an old cookie, new cookie, or no cookie at all.

 setTimeout(function() {  Munchkin.createTrackingCookie(true);   }, 10);  });

While this code wouldn't work anyway, using setTimeout here is undermining your goals. setTimeout means the function won't run until another turn of the event loop. That's the opposite of what you want, assuming you're trying to create a new cookie immediately. Setting a cookie is a blocking, synchronous process (the cookie is guaranteed to exist on the next line). Using setTimeout makes it asynchronous, which is only going to add confusion and unpredictable behavior.

Even without setTimeout, createTrackingCookie isn't going to work, because it's aware that Munchkin has already been initialized with a cookie and exits immediately (like other Marketo libraries, the Munchkin library has guards against functions being called reentrantly, which can be surprising at times).  Doesn't matter if you delete the cookie from the cookie store directly, it's looking at the Munchkin JS object.

What you can do is add _mkt_trk as an empty hidden field whenReady:

form.addHiddenFields({"_mkt_trk":""});

Then onSubmit, create a cookie directly in the cookie store. Make sure it conforms to the Marketo cookie format, which is pretty self-evident. Then set the hidden field to that value:

var newCookie = ...;

document.cookie = "_mkto_trk=" + newCookie ...

form.setValues({"_mkt_trk" : newCookie });

1 reply

SanfordWhiteman
SanfordWhitemanAccepted solution
New Participant
May 27, 2018

pre-filling functionality

First of all, you will break pre-fill if a page loads without an associated cookie.  The only way pre-fill works is if the page is requested with an already-associated cookie sent in the HTTP headers (or with mkt_tok in the query string). 

If you delete the cookie using JS in the page itself, that's by definition after the page loads. It doesn't disable pre-fill because the pre-fill JS object (mktoPreFillFields) is already in the page. You can manually clear the form values, of course. But if you don't do that, you'd get the pre-fill data from the initial page load (including hidden fields) re-posted with the form, regardless of whether there's an old cookie, new cookie, or no cookie at all.

 setTimeout(function() {  Munchkin.createTrackingCookie(true);   }, 10);  });

While this code wouldn't work anyway, using setTimeout here is undermining your goals. setTimeout means the function won't run until another turn of the event loop. That's the opposite of what you want, assuming you're trying to create a new cookie immediately. Setting a cookie is a blocking, synchronous process (the cookie is guaranteed to exist on the next line). Using setTimeout makes it asynchronous, which is only going to add confusion and unpredictable behavior.

Even without setTimeout, createTrackingCookie isn't going to work, because it's aware that Munchkin has already been initialized with a cookie and exits immediately (like other Marketo libraries, the Munchkin library has guards against functions being called reentrantly, which can be surprising at times).  Doesn't matter if you delete the cookie from the cookie store directly, it's looking at the Munchkin JS object.

What you can do is add _mkt_trk as an empty hidden field whenReady:

form.addHiddenFields({"_mkt_trk":""});

Then onSubmit, create a cookie directly in the cookie store. Make sure it conforms to the Marketo cookie format, which is pretty self-evident. Then set the hidden field to that value:

var newCookie = ...;

document.cookie = "_mkto_trk=" + newCookie ...

form.setValues({"_mkt_trk" : newCookie });

MarkusBiAuthor
New Participant
May 28, 2018

First of all, you will break pre-fill if a page loads without an associated cookie.  The only way pre-fill works is if the page is requested with an already-associated cookie sent in the HTTP headers (or with mkt_tok in the query string).

I described it badly in my original question but meant to say that the pre-fill broke (after a page reload) due to the new cookie not being associated with the person.

While this code wouldn't work anyway, using setTimeout here is undermining your goals. setTimeout means the function won't run until another turn of the event loop. That's the opposite of what you want, assuming you're trying to create a new cookie immediately. Setting a cookie is a blocking, synchronous process (the cookie is guaranteed to exist on the next line). Using setTimeout makes it asynchronous, which is only going to add confusion and unpredictable behavior.

Sorry, that shouldn't have been in there originally but I forgot to remove it before posting this question. I used it in my last try after all my previous attempts to set the cookie and associate it failed .

Even without setTimeout, createTrackingCookie isn't going to work, because it's aware that Munchkin has already been initialized with a cookie and exits immediately (like other Marketo libraries, the Munchkin library has guards against functions being called reentrantly, which can be surprising at times).  Doesn't matter if you delete the cookie from the cookie store directly, it's looking at the Munchkin JS object.

What you can do is add _mkt_trk as an empty hidden field whenReady:

I probably should have looked in the Munchkin code to figure out why createTrackingCookie wasn't working. Thanks a lot for pointing that out and mentioning that _mkt_trk needs to be set as a hidden field.

Anyway it seems to be working now. I used the following function to create a Marketo cookie myself:

function getRootHostname(domainLevel) {

  var hostnameSplit = window.location.hostname.split('.');

  return hostnameSplit

    .slice(hostnameSplit.length - domainLevel)

    .join('.');

}

function getMarketoCookieValue(munchkinId, domainLevel) {

  var rootHostname = getRootHostname(domainLevel);

  var timestamp = (new Date).getTime();

  var randomInt = Math.floor(9E4 * Math.random()) + 1E4;

  return 'id:' + munchkinId +

    '&token:_mch-' + rootHostname + '-' + timestamp + '-' + randomInt;

}

(Just a word of caution for everyone reading this: I'm aware that the getRootHostname has a very limited use case and will not work for all hostnames. I might need to use some library to get that right. There's also a hidden field "munchkinId" in the form which I could use instead of using a function parameter.)

SanfordWhiteman
New Participant
May 28, 2018

On this note, see the findPrivateSuffix() function in this post: https://blog.teknkl.com/munchkin-2-letter-tlds-broken/. I use it religiously.