Skip to content
ceaksan

Tracking iFrame Form Events with GTM

Learn how to track form events inside iframes using GTM with window.postMessage to capture conversion data across cross-domain boundaries.

Sep 14, 2025 3 min read

Many form platforms (Typeform, Tally, Paperform, JotForm, etc.) integrate forms into websites via iframes or embed scripts. This creates a conversion tracking challenge: since the iframe runs on a different domain, the GTM container on the parent page cannot directly capture events inside the iframe.

This guide covers how to capture iframe form events using the window.postMessage API and push them to GTM. The approach is platform-agnostic and works with any iframe form.

The Problem: iframe and Cross-domain Boundaries

When a form is embedded via iframe:

  • The iframe runs on a different origin (e.g., tally.so, typeform.com, paperform.co)
  • The parent page cannot access the iframe’s DOM (same-origin policy)
  • Cookies inside the iframe are subject to third-party cookie restrictions (Safari, Firefox)
  • The GTM container only runs on the parent page and cannot see events inside the iframe

The Solution: window.postMessage

The window.postMessage API enables secure message passing between window objects on different origins. When a form platform triggers an event inside the iframe (form submission, page change, etc.), it sends a message to the parent page. A listener on the parent page captures this message and pushes it to GTM via dataLayer.push().

General Flow

iframe (form platform)
  ↓ form submitted
  ↓ window.parent.postMessage({ event: "formSubmitted" }, "*")

parent page
  ↓ window.addEventListener("message", handler)
  ↓ origin check
  ↓ dataLayer.push({ event: "form_submitted" })

GTM
  ↓ Custom Event trigger: "form_submitted"
  ↓ GA4 Event / Google Ads Conversion / other tags

Platform-specific postMessage Support

Some form platforms automatically send postMessage events:

Tally: Automatically sends Tally.FormSubmitted, Tally.FormLoaded, Tally.FormPageView events. See the Tally Conversion Tracking Guide for details.

Typeform: Sends TypeformSubmit and TypeformQuestionPassed events via dataLayer. See the Typeform Conversion Tracking Guide for details.

Paperform: Sends SubmittedForm on form submission, StartedCheckout on payment initiation, StartedSubmission when the user starts filling out the form.

For platforms without automatic postMessage support, you need to manually send messages from inside the iframe.

Method 1: Parent Page Access Available

If you have access to the parent page’s code, you can add a listener directly.

Step 1: Sending Messages from Inside the iframe

Add this code to the form platform’s “post-submission script” field (if available):

<script>
  window.parent.postMessage(
    {
      message: "form_submitted",
    },
    "<parent-page-hostname>",
  );
</script>

<parent-page-hostname> is the origin of the site where the form is embedded (e.g., https://example.com).

Step 2: Listener on the Parent Page

On the parent page, listen for messages from the iframe and push to GTM:

window.addEventListener("message", function (event) {
  // Origin check: only accept messages from trusted sources
  if (
    event.origin === "https://form-platform.com" &&
    event.data.message === "form_submitted"
  ) {
    window.dataLayer = window.dataLayer || [];
    window.dataLayer.push({
      event: "iframe_form_submitted",
    });
  }
});
note

Origin checking is critical for security. Always verify event.origin. Accepting messages from any origin creates an XSS risk.

Step 3: GTM Trigger and Tag

In GTM:

  1. Trigger: Custom Event with event name iframe_form_submitted
  2. Tag: GA4 Event, Google Ads Conversion, or your desired platform tag
GTM iframe Event Trigger
GTM iframe Event Trigger

Method 2: GTM Access Only

If you don’t have direct access to the parent page’s code, you can run the same listener inside a GTM Custom HTML tag.

Create a new Custom HTML tag in your GTM container:

<script>
  (function () {
    try {
      if (typeof window.addEventListener !== "undefined") {
        window.addEventListener("message", function (event) {
          // Specify trusted form platform origins
          var trustedOrigins = [
            "https://tally.so",
            "https://form.typeform.com",
            "https://your-form-id.paperform.co",
          ];

          if (trustedOrigins.indexOf(event.origin) !== -1) {
            // Platform-specific event detection
            var eventName = null;

            // Tally
            if (event.data && event.data.event === "Tally.FormSubmitted") {
              eventName = "tally_form_submitted";
            }
            // Typeform
            else if (event.data && event.data.event === "TypeformSubmit") {
              eventName = "typeform_form_submitted";
            }
            // Generic postMessage
            else if (event.data && event.data.message === "form_submitted") {
              eventName = "iframe_form_submitted";
            }

            if (eventName) {
              window.dataLayer.push({ event: eventName });
            }
          }
        });
      }
    } catch (err) {
      console.log(err);
    }
  })();
</script>

Fire this tag with an All Pages trigger. This keeps the listener active on every page, capturing form events from any iframe.

Paperform Specific Case

Paperform uses the following structure for embedded forms:

<div data-paperform-id="<form-id>"></div>
<script>
  (function () {
    var script = document.createElement("script");
    script.src = "https://paperform.co/__embed";
    document.body.appendChild(script);
  })();
</script>

Paperform provides Google Analytics ID and Facebook Pixel ID fields under Configure > Analytics. However, no direct dataLayer push is made for GTM. The postMessage method is therefore required.

Add this code to the Successful submission scripts field:

<script>
  window.parent.postMessage(
    {
      message: "form_submitted",
    },
    "https://your-site.com",
  );
</script>
Paperform Analytics Settings
Paperform Analytics Settings

Cross-domain Considerations

Key points when tracking iframe forms:

  1. Origin checking: Always verify event.origin
  2. Third-party cookies: Safari and Firefox may block cookies inside iframes. In this case, GA4/GTM won’t work inside the iframe, making the postMessage approach more reliable
  3. Referral exclusion: Add the form platform’s domain to your GA4 referral exclusion list
  4. Consent: Consider GDPR/ePrivacy requirements. Don’t fire tracking code without proper consent

For cross-domain tracking details, see Google Analytics and Google Tag Manager Domain Management.

Testing and Verification

  1. In the browser console, use window.addEventListener('message', (e) => console.log(e.origin, e.data)) to monitor incoming messages
  2. Submit a form in GTM Preview mode and verify the event appears in the dataLayer
  3. Confirm that associated tags fire correctly