UNITED KINGDOM
How to track iframes with Google Tag Manager
Read Time: 8 Minutes

How to track iframes with Google Tag Manager

01 Dec, 2021 Read Time: 8 Minutes
LiveClass
Published by
Max Yodgee
Senior Data & Analytics Director
LinkedIn
Inspire Inform Ignite

If you have worked with a website that uses iframes then it's likely you have felt the tracking pain points that arise. Generally, you will encounter one or all of the following:

  • Campaign/Referral attribution loss
  • Session restarts/dropouts
  • Double page views
  • Inaccurate bounce rate
  • Cookie/Browser storage access

The issues you encounter depend on how your iframes are set up, for instance, are they on the same domain, sub-domain or perhaps hosted on a completely different domain. What does the user do at the end of the process? Does a 3rd party service even allow you to add tracking?

The solution is postMessage. This supported browser functionality allows you to send messages between both the iframe and parent window/main website, in most cases circumventing all the problems you would face traditionally with tracking iframes. 

While in essence, it sounds fairly straightforward, there are intricacies with the setup and it is development heavy, so put on your coding cap, ready your copy and paste as it's time to fix your iframe tracking.

Please note, this solution assumes that coding changes can be made to your iframe. While the setup is implemented via Google Tag Manager, the general concept and JavaScript can still be applied directly.

The Concept

  1. Tracking in the iframe will use postMessage to send data to the main website.
  2. The main website will be listening for messages posted from the iframe
  3. The main website will convert these received messages into analytics tracking calls.

The great aspect of this solution is that the iframe simply sends messages to the main website, no tracking scripts are called within the iframe. The main website, where the tracking takes place, will not encounter session, attribution or access issues while providing more control of when to fire specific tracking calls for the iframe content.

The Setup

  • Google Tag Manager implemented on the main website
  • Google Analytics is implemented on the main website
  • A separate Google Tag Manager container is implemented in the iframe.

The Solution

iFrame setup

  1. Create a Custom HTML Tag
    1. Worksapce > Tags > New > Choose tag type > Custom HTML
  2. Copy & paste the below code snippet into the Custom HTML Tag
  3. Add the All Pages Trigger
    1. Tag > Triggering > All Pages
  4. Save & Name the Tag
    1. cHTML - postMessage - Send - Page View

Code snippet:

<script>
(function(){
    try {
        if(typeof parent != "undefined" && parent != window) {
            if(typeof parent.postMessage != "undefined") {
                var message = {};
                message["origin"] = {
                    "type" : "iframe",
                    "host" : {{Page Hostname}},
                };
                var event = "custom.postMessage";
                // Add description of the event
                event += ".page";
                message["event"] = event;
                // Add custom data
                message["url"] = {{Page URL}};
                // Convent message into a string
                var messageJSON = JSON.stringify(message);
                //Send message to parent
                parent.postMessage(messageJSON, "*");
            }
        }
    } catch(err){if({{Debug Mode}}) console.log(err);};
})();
</script>

The above code snippet is designed to run within the iframe. It first checks to see if a parent exists (parent reference indicates the document is a child and/or iframe). Then the functionality of postMessage is confirmed to be available.

Next a message is created, in this example we are creating a simple page view. The message object is then converted into a string to allow complex data to be passed across and the message is sent.

Main website setup

  1. Create a Custom HTML Tag
    1. Worksapce > Tags > New > Choose tag type > Custom HTML
  2. Copy & paste the below code snippet into the Custom HTML Tag
  3. Add the All Pages Trigger
    1. Tag > Triggering > All Pages
  4. Save & Name the Tag
    1. cHTML - postMessage - Receive

Code snippet:

<script>
(function(){
  try {
    var receiveMessage = function(event) {
      try {
        if(event && typeof event.data != 'undefined') {
          var message = JSON.parse(event.data);
          if(message && typeof message.event != 'undefined' && message.event.indexOf('custom.postMessage') >= 0) {
            if(dataLayer) {
              dataLayer.push(message);
            }
          }
        }
      } catch(err) {};
    };
    if(typeof window.addEventListener !== 'undefined') {
      window.addEventListener('message', function(e) {
        receiveMessage(e);
      });
    } else if (typeof window.attachEvent !== 'undefined') {
      window.attachEvent('on' + 'message', function(e) {
        receiveMessage(e);
      });
    }
  } catch(err){if({{Debug Mode}}) console.log(err);};
  })();
</script>

This snippet is setup to receive message events. It is important to note the the event listener functionality is not specifically targeted to the iframe events only. It is possible that these listeners will pick up other message events from existing website functionality. 

To counter this potential impact, you can see within the receive function conditional checks are used to validate the message received and only react if it is indeed the event we specified from the iframe.

Upon validating the message, the message data is converted back into an Object and is then pushed into the main website dataLayer.

Completing and Tracking the Setup


Now that we have the message entering the dataLayer, we simply need to create the required variables, trigger and tag.

Create the Variables

Workspace > Variables >  User-Defined Variables > New

DLV - url

This is used to extract the URL in the dataLayer from the posted message.

Configuration

Value

Choose variable type

Data Layer Variable

Name/Title

DLV - url

Data Layer Variable Name

url


URL - dataLayer - Path

This is used to extract the page path only from the DLV - url variable.

Configuration

Value

Choose variable type

URL

Name/Title

URL - dataLayer - Path

Component Type

Path

More Settings > URL Source

{{DLV - url}}

 

Create the  Trigger

Workspace > Triggers > New

Custom - postMessage - Page

This trigger will fire when the dataLayer receives the postMessage.

Configuration

Value

Choose trigger type

Custom Event

Name/Title

Custom - postMessage - Page

Event name

custom.postMessage.page

Use regex matching

True

This trigger fires on

All Custom Events

 

Create the Google Analytics Tag

Workspace > Tags > New

GA - Pageview - Virtual - postMessage

Configuration

Value

Choose tag type

Google Analytics - Universal Analytics

Name/Title

GA - Pageview - Virtual - postMessage

Track Type

Pageview

Google Analytics settings

Select your Google Analytics settings variable

Enable overriding settings in this tag

True

More Settings > Fields to Set > Field Name

page

More Settings > Fields to Set > Field Value

{{URL - dataLayer - Path}}

Triggering > Choose a trigger

Custom - postMessage - Page

 

Final Thoughts

It is worth noting that postMessage is a two-way street, it's actually possible to pass messages from the main website back to the iframe. You can then think of this setup in reverse. For example, an iframe sends a message to the main website declaring it's ready. The main website reacts to this message, sending a message back containing information such as the user's client id (cross-domain tracking), instructions to trigger specific events or other information that needs to be persisted. However, it’s worth mentioning that this approach is still not desired mainly due to restrictions in IOS that prevent the setting of 3rd party cookies when using iframes with different domains.

While this solution is fairly robust it does assume that the main website will be loaded and have called the listener scripts before the child iframe loads and sends its message. This should be the case for the majority of setups, if you do notice missing pages then it might be worthwhile adding in logic to ensure both the main website and iframe are loaded before attempting to send messages.

This setup is only scratching the surface of postMessage. In this example, we have only passed a Pageview from the iframe to the main website. It is possible to use the same methodology to track events and other key calls to actions that occur within the iframe. An ultimate solution would be to monitor every dataLayer event within the iframe and pass the messages across to the main website. 

While this setup is advanced, it will drastically improve the data quality and collection when implemented correctly, it will circumvent many of the issues presented with iframes and provide greater control of how and when tracking occurs.

So, there we have it. Some how to track iframes with Google Tag Manager. If you're new to GTM, or want to up your data analysis game, check out our Google Tag Manager training course.

This post first appeared on the Data Runs Deep blog. Data Runs Deep joined the Jellyfish global family in 2020 and the knowledge-sharing continues under the Jellyfish banner in Australia and around the world. 

Share this article
Further learning
blog1
Blog Posts
24 Dec, 2021
In the many years we have been setting up tracking for our clients, the standout and one of the most requested tasks has to be form submits or, as we like to...
Read More
blog1
Blog Posts
25 Nov, 2021
If there’s been one good thing to come out of the last couple of years of Covid, it’s that the restrictions imposed on all our lives have been a boon for...
Read More
blog1
Blog Posts
25 Nov, 2021
Lately, I’ve found myself using a number of window functions in BigQuery. They are really handy functions but can be difficult to wrap your head around. In...
Read More
blog1
Blog Posts
23 Nov, 2021
I’m the biggest advocate for Google Data Studio you’ll likely meet, yet I can acknowledge that visualising page paths in Data Studio is a fiddly task. At...
Read More
We have trained thousands of people all over the world. Helping them to learn more and achieve more.
GoogleBrand
AdidasBrand
AirBanbBrand
SonyBrand
LorealBrand