Really, finally winning the Marketo Forms vs. Tracking Protection battle

SanfordWhiteman
Level 10 - Community Moderator
Level 10 - Community Moderator

While you should be loading embedded forms from your Marketo LP domain, it turns out just changing the URL is not enough.

 

Using a non-Marketo-owned domain to load forms2.min.js and call loadForm() seems to avoid collateral damage from Tracking Protection (Firefox’s built-in feature or the equivalent plugin for another browser). The form will at least show up on the page if you do that.

 

But – I’m sure you will be dismayed to learn – the form still won’t post under TP! You also need to upload a file to Design Studio and add a tiny bit of JavaScript. Then and only then are you good to go.

 

First, download this file:

 

marketo-xdframe-relative.html

 

(Note: the Marketo Nation site gates files through an “Offsite Link” popup. So click above, then right-click the link + Save Link As. Make sure you get the .html file itself, and don’t end up with a snapshot of this blog post!)

 

Next, upload the file to your Design Studio. To be clear, you’re not creating an LP, you’re uploading the file as static HTML. This may not be something you’ve done before (you probably upload images, CSS, and PDFs) but Marketo actually supports any kind of file.

 

Screenshot after it’s been uploaded to Design Studio:

 

Then replace your embed code with this ever-so-slightly different version:

<script src="//pages.example.com/js/forms2/js/forms2.min.js"></script>
<form id="mktoForm_9999"></form>
<script>
 MktoForms2.setOptions({
 formXDPath : "/rs/123-ABC-456/images/marketo-xdframe-relative.html"
 });
 MktoForms2.loadForm("//pages.example.com", "123-ABC-456", 9999);
</script>‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Where:

 

  • 123-ABC-456 represents your Munchkin ID
  • pages.example.com represents your Marketo LP domain
  • 9999 is o’course your form ID

 

A live demo (though all the code is above):

 

MktoForms2 :: XDFrame relative path for Tracking Protection

 

The why

Using your LP domain enables forms to show up. But there’s a special asset, only used upon submission, that will still be blocked by default. Naturally, this only reveals itself when you run end-to-end tests.

 

See, embedded forms use an IFRAME message relay (XDFrame) for cross-domain posts (there are other ways to do it, but they’re not as backward-compatible and the IFRAME method works fine + fast in all browsers, even back to IE8).

 

But the IFRAMEd document loads forms2.min.js from an absolute URL with your instance hostname, i.e. app-xxnn.marketo.com:

Oops! Tracking Protection ain’t gonna let that load, for the same reason it doesn’t like a Marketo domain in the main document. (You can’t avoid TP by using an IFRAME, that would be silly.)

 

As you can see, the replacement XDFrame file uses a relative URL (/js/forms2/js/forms2.min.js), so it loads from your Marketo LP domain like the rest of the assets. Presto! No marketo.com for TP to get all paranoid about.

 

NOTES

forms2.min.js inside the IFRAME is only necessary because of its bundled  jQuery library, specifically the MktoForms2.$.ajax wrapper method. While not technically necessary, using jQuery keeps parity with the Forms 2.0 API.

13156
51
51 Comments
SanfordWhiteman
Level 10 - Community Moderator

@Kurt_Koller no reason for anything to be lost. Switching the XDFrame path just sets a different frame source, nothing else is processed differently. There is always a hidden IFRAME used for cross-origin Marketo posts. 

Kurt_Koller
Level 4

@SanfordWhiteman Okay I'll look into it again. It seemed that we were losing Referrer and Querystring/utms. Thanks for the reply.

Kurt_Koller
Level 4

@SanfordWhiteman One quick follow-up question if you don't mind. In the code that comes back from marketo (the default frame):

if(message && message.mktoRequest && message.mktoRequest.ajaxParams){
var p = message.mktoRequest.ajaxParams;
var params = { type:"POST", dataType:"json", url:p.url, data:p.data, crossDomain:false, jsonp:false };
params.success = function (data){

In the code you have posted to use in place of that frame:

if(message && message.mktoRequest && message.mktoRequest.ajaxParams){
var params = message.mktoRequest.ajaxParams;
params.success = function (data){

Do you think there is any possibility that by copying the whole original params object vs setting them individually like Marketo does that we could get different information in the referrer or querystring? I find this is a very difficult architecture to debug in and this isn't an area I normally stumble into. Thanks for entertaining my questions.




SanfordWhiteman
Level 10 - Community Moderator

I'll look into it — but my custom XDFrame only has one customization from the then-current version of the XDFrame, which is the switch to a relative path.

 

This modification would be separate, not something I did.

SanfordWhiteman
Level 10 - Community Moderator

Actually, where are you getting my custom XDFrame from? The custom file does look exactly like the standard file in that section:

 

https://assets-dl.figureone.com/assets/marketo-xdframe-relative.html

 

That's what's linked in this blog post.

 

 

 

SanfordWhiteman
Level 10 - Community Moderator

I do see an older version on the client instance that's linked in the CodePen — though that's not the place to get the code anyway. Will replace it.

Kurt_Koller
Level 4

Ok, it was given to me and I guess they got it from the CodePen. Will switch to the newest version from your blog post and will make a note to do that in the future. Sorry about that.

Kurt_Koller
Level 4

We are starting to use this solution due to the large amount of tracking protection showing up these days, Ghostery, the new Edge default settings etc. Any idea how often Marketo updates their code library? I maybe need to set an alert on this on the instances where we deploy. Thanks for the replies Sanford, really appreciated.

SanfordWhiteman
Level 10 - Community Moderator

Cool!

Radek_Mezulanik
Level 1

I have followed instructions in the first page, but ended up with forms showing, but not submitting.

I have a file uploaded here https://info.productboard.com/rs/128-JHR-871/images/marketo-xdframe-relative.html

 

<script src="//info.productboard.com.com/js/forms2/js/forms2.min.js"></script>
<form id="mktoForm_1296"></form>
<script>
MktoForms2.setOptions({
formXDPath:"/rs/128-JHR-871/images/marketo-xdframe-relative.html"
});
MktoForms2.loadForm("//info.productboard.com", "128-JHR-871", 1296);
</script>

 

Did anyone solved submitting the forms?