SOLVED

Custom de-duplication: Create new cookie on form submit

Go to solution
Markus_Bianchi5
Level 2

Custom de-duplication: Create new cookie on form submit

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

1 ACCEPTED SOLUTION

Accepted Solutions
SanfordWhiteman
Level 10 - Community Moderator

Re: Custom de-duplication: Create new cookie on form submit

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 });

View solution in original post

11 REPLIES 11
SanfordWhiteman
Level 10 - Community Moderator

Re: Custom de-duplication: Create new cookie on form submit

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 });

Markus_Bianchi5
Level 2

Re: Custom de-duplication: Create new cookie on form submit

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
Level 10 - Community Moderator

Re: Custom de-duplication: Create new cookie on form submit

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

Markus_Bianchi5
Level 2

Re: Custom de-duplication: Create new cookie on form submit

One more question actually. Would setting the new cookie in onValidate also work (just to not reset the cookie too early in case the validation fails)? In my tests it still worked the same but I'm wondering why you suggested onSubmit?

SanfordWhiteman
Level 10 - Community Moderator

Re: Custom de-duplication: Create new cookie on form submit

You could do it at the very *end* of a successful onValidate chain, but you won't know when that is (a given onValidate listener doesn't know whether it's last). So you would risk resetting the cookie even though the form never gets submitted because of a later validation exception.

Markus_Bianchi5
Level 2

Re: Custom de-duplication: Create new cookie on form submit

Ok, good, I have control over all onValidate listeners in that specific case. With onSubmit I would risk resetting the cookie all the time.

SanfordWhiteman
Level 10 - Community Moderator

Re: Custom de-duplication: Create new cookie on form submit

Of course you can exit onValidate early if the form isn't currently native-valid (as you're doing in your original code) but I don't see how that's less risky than using onSubmit, where you have access to all the final form fields. Didn't you say "we always want to use the custom de-duplication logic rather than the cookie"?

Markus_Bianchi5
Level 2

Re: Custom de-duplication: Create new cookie on form submit

Yes, custom de-duplication should always be used but I don't want to reset the cookie too early. I could check all the fields manually in onSubmit as you've mentioned but in onValidate I at least know if the form is currently native-valid (without manual checks). But you're right, both options can be risky. I wish we had a little more control over this in the Forms API. Thanks again for your help!

SanfordWhiteman
Level 10 - Community Moderator

Re: Custom de-duplication: Create new cookie on form submit

What I'm saying is onSubmit always runs after the whole onValidate chain, so onSubmit it can't be more risky.

Still not sure what the risk is?