Skip to main content
Data Runs Deep Menu

Main navigation

  • Home
  • Who We Are
    • Careers
    • What We're Up To
    • What We Believe In
    • Ethical Policy
  • What We Do
  • Google Marketing Platform
    • Analytics 360
    • Tag Manager 360
    • Salesforce and GA360
    • Google Analytics App+Web
    • Data Studio
    • Optimize
  • Google Cloud Platform
    • Google BigQuery
      • Google BigQuery Training
      • Google Analytics Integration
  • Consulting
    • Strategy
    • Implementation
      • Google Analytics Audit
      • Google Tag Manager Audit
      • Enhanced Ecommerce Implementation
      • Google Tag Manager
    • Analysis
      • Google Data Studio
        • Google Data Studio Case Study - Mona
      • UX Analysis
  • Training
    • Five Day Google Analytics Online Workshop
    • Advanced Google Analytics Training
    • Google Tag Manager Training
    • Google Analytics 360 Training
    • Advanced Analytics Bootcamp
  • Partnerships
    • Conductrics
  • Blog
  • The Flying Beagle
  • Merch
  • Contact

How to track iframes with Google Tag Manager

By: Max Yodgee
Posted in
  • Google Tag Manager
  • iFrame
  • JavaScript
Article Date
September 26, 2018

If you have worked with a website that uses iframes then its 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 setup, 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 its 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 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 websites 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, a iframe sends a message to the main website declaring its ready. The main website reacts to this message, sending a message back containing information such as the users 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 worth while 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 call 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.  

Get in touch

To find out more, email us on hello@datarunsdeep.com.au or complete a quick contact form.

Get in touch

Talk to us: 1300 737 885

08:30 - 16:30, Monday to Friday. We love to chat

Visit us, we’re at:

Level 8, 313 Little Collins Street Melbourne, VIC 3000

Footer

  • Home
    • Who We Are
      • What We Do
      • What We're Up To
      • Careers
      • Contact
  • Training
    • Google Analytics Training Courses
    • Advanced Google Analytics Training
    • Google Tag Manager Training
  • Consulting
    • Analysis
    • Implementation
    • Strategy
    • Google Analytics Audit
    • Google Tag Manager Audit
  • Google Cloud Partner
  • Google Marketing Platform Sales Partner
  • Bitcoin accepted here
  • Registered Looker Consulting Partner Melbourne
  • Twitter
  • LinkedIn
  • Google Plus
  • Blog RSS feed
Copyright © 2009-2021 Data Runs Deep Pty Ltd. All Rights Reserved. Google Analytics is a trademark of Google Inc.
Website by Marin Sekesan