iFrame Form Tracking with Gooogle Tag Manager without iFrame Access!

To track iFrames, you usually need access to them. You’d insert a specific tracking code or a separate GTM onto the iFrame site. This sends a JavaScript message that your main website can listen to, allowing you to track iFrame events. But often, we can’t access the iFrame to add this code. To solve this challenge, here’s a simple solution. In this guide, I’ll demonstrate how to track interactions and form submissions within an iFrame even when you can’t access it directly.

iFrame form Tracking DataLayer Code

/**
* Author: Md Hasanuzzamna
* Linkedin: https://linkedin.com/in/md-h
* Youtube: https://youtube.com/@leomeasure
* Email: info@leomeasure.com
*/

(function() {
    function leoMeasureIframeFormSubmitDataLayer() {
        var iframeSelector = 'iframe'; // Change as your iframe selector example: 'iframe#id-of-iframe'
    
        var iframe = document.querySelector(iframeSelector);
        var isFormSubmitted = false;
        var isInsideIframe = false;
        var isCodeExecuted = false;
        var iframeHeight;
    
        var observer = new MutationObserver(function (_mutationsList, observer) {
            var currentHeight = iframe.offsetHeight;
            var iframeHeightChange = Math.abs(((currentHeight - iframeHeight) / iframeHeight) * 100);
    
            if (!isFormSubmitted && iframeHeightChange > 40) {
                observer.disconnect();
    
                isFormSubmitted = true;
                window.dataLayer = window.dataLayer || [];
                dataLayer.push({
                    event: 'iframe_form_submit',
                    form_location: window.location.href,
                    iframe_id: iframe.getAttribute('id'),
                    iframe_class: iframe.getAttribute('class')
                });
            }
        });
    
        function handleMouseOver(event) {
            if (event.target.closest(iframeSelector)) {
                isInsideIframe = true;
            } else {
                isInsideIframe = false;
            }
        }
    
        function handleFormSubmission() {
            var formInsideIframe = iframe.contentDocument.querySelector('form');
    
            formInsideIframe.addEventListener('submit', function (event) {
                var formData = {};
                var formInputs = formInsideIframe.querySelectorAll('input, select, textarea');
    
                for (var i = 0; i < formInputs.length; i++) {
                    var input = formInputs[i];
                    if (input.type === 'radio') {
    
                        if (input.checked) {
                            formData[input.name] = input.value;
                        }
                    } else if (input.type === 'checkbox') {
                        if (!formData[input.name]) {
                            formData[input.name] = [];
                        }
                        if (input.checked) {
                            formData[input.name].push(input.value);
                        }
                    } else {
                        formData[input.name] = input.value;
                    }
                }
    
                window.dataLayer = window.dataLayer || [];
                window.dataLayer.push({
                    event: 'iframe_form_submit',
                    form_location: window.location.href,
                    iframe_id: iframe.getAttribute('id'),
                    iframe_class: iframe.getAttribute('class'),
                    user_inputs: formData
                });
            });
        }
    
        document.addEventListener('mouseover', handleMouseOver);
        window.addEventListener('blur', function () {
    
            if (isInsideIframe && !isCodeExecuted) {
                isCodeExecuted = true;
                document.removeEventListener('mouseover', handleMouseOver);
    
                window.dataLayer = window.dataLayer || [];
                dataLayer.push({
                    event: 'iframe_form_start',
                    form_location: window.location.href,
                    iframe_id: iframe.getAttribute('id'),
                    iframe_class: iframe.getAttribute('class')
                });
    
                if (iframe.contentDocument) {
                    handleFormSubmission();
                } else {
                    iframeHeight = iframe.offsetHeight;
                    observer.observe(iframe, { attributes: true, childList: true, subtree: true });
                }
            }
        });
    }
    leoMeasureIframeFormSubmitDataLayer();
})()

1 thought on “iFrame Form Tracking with Gooogle Tag Manager without iFrame Access!”

  1. hello. thank you very much for your effort. i’m sure you saw under your video on youtube that only the first trigger works for most people. i think it’s because certain behaviours are different when sending the form. a library with different triggers would be enormously helpful there.

    I have tried several things and they don’t work. but I don’t know my way around either.

    if (!isFormSubmitted && iframe.contentDocument.body.innerHTML.includes(‘Vielen Dank’)) {
    observer.disconnect();

    if (!isFormSubmitted && iframe.contentDocument.querySelector(‘.sc-e2065d79-0.hYcmCS.flex.justify-center.rounded-full.items-center’)) {
    observer.disconnect();
    and like 20 others hahahhaha. If you can look into this, I’d be so happy

Leave a Comment

Your email address will not be published. Required fields are marked *

Contact Us

Please contact us for expert guidance & personalized solutions to maximizing the potential of Google Analytics for your business.

Send Us A Message