iFrame & Cross-domain Conversion Tracking – 4 Methods

In the last few years I’ve done iFrame conversion tracking for hundreds of websites. So Let’s dive into this boring but absolutely crucial subject. You must always track your conversions. Otherwise you’re leaving a lot of money on the table.


Start

1) Do you have an iFrame on your website?

2) Do you want to run paid ads like Google Ads, Meta Ads etc and measure a conversion that happens inside an iFrame embedded in your website?

If you answered yes, keep reading.
If you answered no – not sure what you’re doing here!

iFrames?

Most popular website “widgets” like Typeform, Calendly, Acuity Scheduling, Jotform, Paperform, Hubspot form etc are added inside our websites as something called and iFrame.

You can think of it like a box inside your website, which shows a window to another website.

For visitors the iFrame may look like a seamless part of your website, but its in not. If your website is example.com, inside it you may have an iFrame which shows the website typeform.com/form/eag432.

Visitors can’t tell. But from a technical point of view, whenever the mouse of a visitor is inside the iFrame box, it’s the same as if they were browsing another website on another browser tab.

What makes iFrame conversion tracking difficult?

The challenge is that our website doesn’t know what happens inside the iFrame.

iFrame is a different website

So, someone booked, converted, paid, scheduled, purchased?

Our website does not know. So if we try to do something like Google Tag Manager form submission trigger, it will not work because we have Google Tag Manger running on our own example.com, but we cannot add Google Tag Manager to Typeform.com. Or, maybe we can if we pay a crazy price, but that still doesn’t let our website know about the form submissions, as it happens outside our website in another URL.

Tracking cookies are (usually) not shared between our website and the iFrame.

Some iFrames, like Typeform may let us install custom code or conversion tracking tools like Google Tag Manager inside them – inside the iFrame. But this does solve the problem. Why? Because conversion tracking relies on cookies (or in some advanced scenarios, local storage but basically the same thing) which is a thing the browser will remember.

An example of this is the ‘gclid’ - Google Click ID which is added to a URL of a Google Ad click like

example.com/nike-air-jordan?gclid=Cj0KCQjw9vqyBhCKARIsAIIcLMFH8tzRiZaBMAIwep6YztkQ1N0gCTCnjdybLyRB-nIhWUKVZkyIQoAaAlHAEALw_wcB

And from there, a Google Tag Manager Conversion Linker tag saves gclid as a cookie (called _gcl_aw), so the browser will remember the click.

When a conversion happens, we basically tell Google Ads:
”Hey Google Ads, we got a conversion! It’s worth 100 USD and it resulted from this ad click Cj0KCQjw9vqyBhCKARIsAIIcLMFH8tzRiZaBMAIwep6YztkQ1N0gCTCnjdybLyRB-nIhWUKVZkyIQoAaAlHAEALw_wcB.“

The problem is that the click cookie is tied to our website example.com, and is not shared to our iFrame, e.g. typeform.com. So even if we try to send the conversion from Google Tag Manager inside our iFrame, we basically tell Google Ads:

”Hey Google Ads, we got a conversion! It’s worth 100 USD and we have no idea if the visitor clicked on any Google Ads, or if they did which one.”

So.
We can’t know what happens inside the iFrame because it’s another website.
And we can’t send conversions from the iFrame because the cookies are not shared.

How to do iFrame conversion tracking?

We have four methods

1) listen for JavaScript messages coming from the iFrame to our website

This is my second favourite method.

<script>
// Step 1: Add an event listener to handle messages from the iframe.
window.addEventListener('message', function(event) {
// Step 2: Filter or check origin if necessary. For demo, we're allowing all origins.
      // console.log('Message origin:', event.origin);
      // Step 3: Log the data sent by the iframe.
      console.log('Message received from iframe:', event.data);
      // Step 4 (Optional): Respond back to the iframe if needed.
      // event.source.postMessage('Hello from parent!', event.origin);
    });
  </script>

This is usually the base I do my iFrame conversion tracking on.

It’s a good base as it doesn’t require redirects, and we can send the conversion from our website where our tracking cookies lie. Yay!

For this you will need to add a “listener” script that listens for JavaScript messages the iFrame sends the parent window (our website).

The challenge is, every iFrame is different.

Some iFrames send all the information we’d ever want. Examples of the best iFrames to track

  • 😍 Tally.so forms

  • 😍 Hubspot forms

  • 😍 Lemon Squeezy embeds

Then we have those in between

  • 🙂 GoHighLevel - sends the field values like email and phone number we need for Enhanced Conversion Tracking but in a separate message making the code required a total mess. What were they thinking. Also changing the message format has broken iFrame tracking and required updates

  • 🙂Acuity Scheduling, where we must custom code not just our message listener but our message sender. We can get the purchase value and appointment ID which are great! But Acuity iFrame has annoying limitations like not having a variable for phone number which we definitely need. After recent update it can also take multiple emails which must be handled with more custom JavaScript or out Enhanced tracking and advanced matching breaks.

Then we have annoying ones like which tell us about the conversion but skip all the good stuff like form field values

  • 😓 Calendly

  • 😓 Typeform

  • 😓 Jotform (also has in the past sent multiple matching events for one conversion! Requiring us to have a JavaScript counter logic to just send the first one. What were they thinking)

And then we have iFrames which do not send any messages

  • ☹️ Google Forms

The process to track iFrame conversions with JavaScript message listeners goes like this

  1. Add a generic JavaScript listener to the browser console of your website (parent website, example.com)

  2. Fire a conversion inside the iFrame

  3. See what the console says, if we get messages. Figure out what’s the one we get for conversion, make sure there’s only one. Figure out how to get field values. For example Tally iFrames require us to JSON parse the message, many do not. Hubspot iFrame has multiple messages for the conversion. Make a Javascript function inside our listener that stores all these and an event inside the data layer

  4. Make a custom event trigger in Google Tag Manager

  5. Make data layer variables for the iFrame form field values

  6. Fire our conversion tags in Google Tag Manager, with the variables as needed, for example our Typeform submission ID would be used as our Meta Pixel conversion “orderID” or Google Ads conversion “Transaction ID”.

  7. Test test test! 99% of the time there’s something wrong so you gotta make sure. Test with Google Tag Assistant, Meta Pixel helper for Google Chrome, Facebook business manager “Test Events” view, Google Analytics debug view, or clicking on your own Google Ads, converting inside the iFrame and checking if 2-5 hours later you see the conversion in Google Ads.

Depending on the platforms, we can give our iFrame message listener conversion tracking a boost by doing a Google Ads Conversion enhancement via the API after our web conversion has been sent from Google Tag Manager.

This is required for Acuity Scheduling iFrames if running Google Ads on a higher budget. And is the best method for iFrames like Calendly, Typeform, Jotform etc.

Meta Pixel can't do Advanced Matching after conversion. So the solution depends on the combo you use. Which iFrame and which platform you wanna send conversions to.

2) Store our clicks in cookies or local storage and pass them to hidden fields in our iFrame
And then send conversion via the backend like Google Ads conversions API or Meta Conversions API CAPI.

This is probably the best method.

Using local storage instead of cookies, and populating our iFrame ourselves fixes tons of issues.

👍 Apple Intelligent Tracking Prevention deletes cookies in as little as 24 hours which is a downside of all other methods. But a custom local storage solution often works 7 times longer and leads to more accurate tracking. We could take it even further and have a custom server we’d fetch just to have it reply with some lovely server cookies that last 2 years – although Apple Intelligent Tracking Prevention does cap them to the same 7 day expiry if we use CNAME cloaking and Safari sees that the IP address of our website and the cookie-endpoint are too different. Requires cloudflare and gets tricky.

It’s also great to know where each conversion came from, to understand our business ourselves not just to tell Google Ads or Meta Ads about the conversions. Imagine using sometihing like Acuity Scheduling for a photo studio, and seeing this level of detail for each iFrame conversion.

iFrame conversion tracking demo - Acuity Scheduling iFrame with prepopulated hidden fields with UTM parameters, gclid, fbclid, user agent and more

Or the same with Typeform - knowing which exact Google Ads campaign and ad resulted in this conversion

Typeform iFrame conversion tracking demo, passing UTM parameters and gclid via hidden fields

The added benefit is the option to do offline conversion tracking. A lot of times when we do iFrame conversion tracking the conversion is actually just a lead that may become a paying customer or not. Sometimes we have something like a paid yoga class in Acuity Scheduling that’s the final conversion with a $ value we know immediately in our browser.

But often we have an iFrame where a curious visitor becomes a lead we gotta sell later. Having our ‘gclid’ – the Google Click ID as well as Facebook click ID’s stored makes it possible for us to calculate our real ROAS, return on ad spend even for conversions that happen offline in the real world outside of browsers and cookies. And see which ad’s bring in money, not just iFrame conversions.

I love it.

3) Pass the cookies to the other website, in the iFrame or via link in a cross-domain funnel.

I hate this method, but still mention it.

Some platforms attempt to share some tracking cookies from our website to the iFrame or the platform. Usually, Google Analytics 4 cookies are attempted to be sent, for example by Acuity Scheduling’s embed.js script.

We may also try and do a cross-domain funnel by ourselves, but having e.g. Google Analytics installed on our website example.com and Google Analytics in our iFrame (although it may not be an iFrame in this case actually but a cross-domain funnel link), then use Google Analytics domains or in the case of Google Ads conversion tracking, add domains to out Google Tag Manager Conversion Linker tag.

The problem why I don’t like this method is because it’s unreliable, does not work for all platforms and sends conversions from the wrong place. in Google Analytics we wanna see someone visits example.com, and converts at example.com/contact – not at typeform.com/something weird.

For iframes were at the mercy of the platform. In my experience they may attempt to share GA4 cookies unreliable. But in my testing, for example Typeform does not share Meta Pixel cookies like _fbp or _fbc with the Typeform iFrame. This is especially bad dealy considering how much Typeform charges for the option to use these integrations.

It’s a pointless waste of time.

4) Redirect to a custom thank you page

I kinda hate this method too, but still mention it.

Also, for some platforms like Stripe Payment button or Shopify But Button we are redirected away from our website anyway, and must get back to be able to track conversions.

A classic way to track iFrames is the redirect to a custom thank you page like example.com/thank-you.

It can work. It is required for some platforms. But it sucks.

Problems with redirects for iFrame conversion tracking:

  • 👎 Refreshing the thank you page or going to a new website and hitting back button will lead to duplicate conversions unless adding a cookie to just send the first one. I wasn’t worried about this before but I’ve seen it happen a lot so data may get messed up.

  • 👎 We often need to get the values of the iFrame. We want things like conversion ID (Acuity Scheduling, Calendly, Typeform, Paperform, Hubspot forms – they all have a unique ID for this submission we want to use to avoid counting duplicates for the same conversion. We may also want conversion value like $100 USD, we want the field values like email, and phone number, but we may also want a form. Like if you have a solar panel lead gen form, you want to track how many leads for houses and how many for corporations you got. Some iFrames like Jotform and Typeform allow sending some of these values over the redirect URL, like example.com/thank-you?value=100&email?mike@gmail.com&id=12345.

    Jotform allows all and is pretty good

    Typeform allows field values but not submission ID which is a huge problem.

    However parsing the URL leads to problems, as Google Analytics and Meta Pixel do not allow personal information like emails in URLS. So we gotta do crazy stuff like Google Tag Manager trim query custom template where we override our Google Analytics page location. And then realised that Meta Pixel does not have this option so we need to use JavaScript to remember iFrame conversion URL parameters from in our URL as variables, then “clean up” our URL with


    window.history.replaceState({}, '', newUrl);


    and what…have a custom trigger for when we have our URL cleaned and fire Meta Pixel here?



    I’ve actually done this URL swapping cleaning PII-legit setup for clients using Typeforms and Jotforms. There are cases where it’s been needed. But I do hate it as it’s such a crazy messy overkill.

  • 👎 For Google Ads we need enhanced conversion tracking and for Meta Pixel we need Advanced matching. For custom thank you page there’s a PII issue which needs to be fixed

  • 👎 Thank you page redirect often messes up traffic sources in Google Analytics. A person that came from e.g. google.com may be “updated” to have form.typeform.com as the referrer / source which is terrible. We can do unwanted referrals in Google Analytics or exclude referrer in Google Tag Manager, but it’s still bad.

  • 👎 We gotta manage our redirects which is a pain in the ass. We gotta make thank you pages, make sure our redirects work. And for a lot of tools (again using Typeform as an example) may may have to pay $500 per year to be able to redirect. Terrible waste of time and money.


iFrame conversion tracking - for ambitious real businesses

Are you after a pro setup? If you’re doing a $200 ad campaign for your brothers yoga studio you can probably do ok with any method, just pick what is easiest.

But if you’re a “real business”, perhaps doing 5,000-25,000 per month in ad spend, you need a real iFrame conversion tracking system.

For ambitious clients, I like to combine both methods 1 and 2. And then see which one tracks more conversions in a 120 day period. No point in trying to forsee the future. Just test and get the numbers in.

Interestingly, the results vary a lot per client.

I’ve seen some clients where a custom hidden field prepopulation method tracks 11% more. And some clients where the JavaScript message method tracks more iFrame conversions.

The reasons I believe are that for some clients the Apple intelligent tracking prevention 24h cap on cookies is a big issue. This depends on target audience and their devices. So the hidden field prepopulation is more effective.

For some clients I belive that the Google Ads enhanced conversion tracking gives a bigger boost in conversions. At the moment we can’t do Google ADs Enhanced Conversion tracking via the API (I hope this changes soon!) so if you do a lot of video ads for example or if the conversion is cumbersome with a lot of data and customers switch devices mid-funnel – the iFrame JavaScript message listener is better.

I’ll aim to update this blog post with more details, examples and some video demo examples. Until then…

Do you want a pro to track your iFrame conversions?

I’d love to help.
Get in touch via the contact page.

Previous
Previous

AI in Conversion Tracking - 3 Practical Examples

Next
Next

Acuity Scheduling Conversion Tracking (2025 Update)