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

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:




(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="//"></script>
<form id="mktoForm_9999"></form>
 formXDPath : "/rs/123-ABC-456/images/marketo-xdframe-relative.html"
 MktoForms2.loadForm("//", "123-ABC-456", 9999);



  • 123-ABC-456 represents your Munchkin ID
  • 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.

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 for TP to get all paranoid about.



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.

Level 10 - Community Moderator

Path in your code is 

That page doesn't exist on your Marketo instance, so it's redirected to your main site (fallback page).

Level 2

It does exist. See the screenshot. FormMKTO2.JPG

I changed the code back to "marketo-xdframe" and then cleared my cache and it's working now. 

Thanks for the write up. If I had cleared my cache I would have resolved this yesterday. 

Level 2

I spoke tooooooooo soon. I tried to resubmit the form and it's not submitting. 

Level 10 - Community Moderator

Open the XDFrame URL, by itself, in your browser. As it redirects to your fallback page, it cannot work.

Level 2

Hey Sanford Whiteman

Thanks for the post and all of your responses to everyone. It's very helpful and greatly appreciated!  

Do you have any suggested resources/readings for how to setup a CDN to avoid the Marketo SSL solution? I'm interested in exploring this route before ponying up for the Marketo SSL. 

Level 10 - Community Moderator

I have not yet blogged about it... might be easier for me to send you a few screenshots. It's literally a 10m setup + test with AWS CloudFront.

Level 2

Sure, I'm happy to work with whatever you're willing to send! 

Level 8

@SanfordWhiteman ,

that worked like a treat first time!  Great instructions.

It even plays nicely with your equally awesome form pre-fill code 🙂

Cheers and thank you so much.


Level 10 - Community Moderator

Sure thing.

Level 4

Hi Sanford,

This is great, thanks so much.

When this approach is used, the Referrer is lost as well as the Querystring. Any ideas on preserving this data? I was going to work on this but thought I'd ask your thoughts first, since you really know this stuff inside an out. I'm thinking Querystring could be read from the parent frame or passed in to the child fame as a querystring on the html file, but the Referrer I think is not programmatically changeable so that seems like it would have to be passed down somehow and passed in as another field if we wanted it. Again, just looking for your thoughts on this.