Comment Tracker une Iframe avec Google Tag Manager
Comment tracker une iframe avec GTM malgré la same-origin policy : la méthode postMessage, les cas Calendly et Typeform, et le choix entre un ou deux conteneurs GTM.
Dans ce guide
Tracker ce qui se passe à l'intérieur d'une iframe (formulaire embarqué, prise de rendez-vous, simulateur tiers) est un cas classique mal documenté, parce que la vraie contrainte n'est pas dans GTM, elle est dans le navigateur lui-même.
La vraie limite : la same-origin policy
Confirmé par la documentation MDN : l'accès aux propriétés d'une fenêtre chargée depuis une autre origine est bloqué par le navigateur, y compris pour un script à l'intérieur d'une iframe qui voudrait accéder à sa page parente. Via contentWindow ou contentDocument, la page parente peut accéder au DOM de l'iframe seulement si elles partagent la même origine (même protocole, domaine et port). En cross-origin, cet accès est très restreint. Ce n'est pas une limitation de GTM, c'est une protection de sécurité du navigateur, aucun tag ni aucune configuration GTM ne la contourne.
postMessage, la méthode standard
Le seul canal de communication documenté entre deux origines différentes est Window.postMessage(). Le principe : l'iframe émet un message, la page parente l'écoute et relaie l'information dans le dataLayer.
Côté iframe (si vous contrôlez son code) :
window.parent.postMessage({
event: "form_submitted",
data: { formName: "contact" }
}, "https://votre-domaine-parent.com");
Côté page parente, dans une balise HTML personnalisée GTM :
window.addEventListener("message", function(e) {
if (e.origin !== "https://domaine-iframe.com") return;
if (e.data && e.data.event === "form_submitted") {
window.dataLayer.push({
event: "form_submitted",
formData: e.data.data
});
}
});
Deux points de sécurité documentés à respecter systématiquement : ne jamais émettre avec postMessage(payload, '*'), qui envoie le message à n'importe quel parent sur n'importe quel domaine, et toujours vérifier e.origin côté réception avant de traiter le message, sous peine d'accepter des données injectées par une page tierce malveillante.
Quand vous ne contrôlez pas le code de l'iframe
Pour une iframe tierce (widget de prise de rendez-vous, formulaire externe), tout dépend de si le fournisseur envoie déjà des postMessage documentés.
Calendly : confirmé par sa documentation développeur officielle. L'embed standard Calendly envoie des événements avec le préfixe calendly., dont calendly.profile_page_viewed, calendly.event_type_viewed, calendly.date_and_time_selected et calendly.event_scheduled :
function isCalendlyEvent(e) {
return e.origin === "https://calendly.com" && e.data.event && e.data.event.indexOf("calendly.") === 0;
}
window.addEventListener("message", function(e) {
if (isCalendlyEvent(e)) {
window.dataLayer.push({ event: e.data.event, calendlyPayload: e.data.payload });
}
});
Point à vérifier avant de copier ce code tel quel : ça ne fonctionne que via l'embed JS standard de Calendly, pas via une iframe brute sans son script d'intégration.
Typeform : la documentation officielle met surtout en avant un système de callbacks (onSubmit) via son SDK d'embed, plus que du postMessage brut à écouter soi-même. Un événement form-submit observable en écoute passive existe et est utilisé par des implémentations tierces, mais il est moins formellement documenté par Typeform elle-même que ne l'est le système Calendly, à traiter avec cette réserve avant de bâtir un tracking dessus.
Un conteneur GTM dans l'iframe, ou un seul sur la page parente ?
Aucune position officielle Google ne tranche ce choix, mais la pratique convergente des consultants tracking donne une règle simple : quand vous contrôlez le code de l'iframe, un seul conteneur sur la page parente avec la méthode postMessage ci-dessus reste préférable, ça garde un Client ID et un Session ID unifiés côté domaine parent et évite la duplication de mesure. Un second conteneur GTM installé directement dans l'iframe se justifie quand l'iframe vit sur un domaine distinct avec son propre besoin de mesure autonome, ou quand vous n'avez aucune main sur le code de la page parente. Le risque documenté dans ce second cas : les déclencheurs standards ("Toutes les pages", clics) du conteneur de l'iframe se déclenchent aussi dans son propre contexte et peuvent générer des données dupliquées ou incorrectes si les tags ne sont pas contraints par des exceptions vérifiant le nom d'hôte.
Une implémentation plus complexe à discuter ?
Discuter de votre trackingBesoin d'un accompagnement sur ce sujet ?
Freelance google tag managerArticles liés
Pour aller plus loin sur votre projet
GTM & dataLayer
GTM & dataLayer
Un conteneur mal structuré suffit à fausser vos conversions, votre ROAS et vos arbitrages marketing.
Voir l'expertiseQuestions fréquemment posées
Pourquoi ne peut-on pas simplement lire le contenu d'une iframe depuis GTM ?
À cause de la same-origin policy du navigateur : l'accès au DOM d'une iframe depuis la page parente (ou l'inverse) n'est possible que si les deux partagent la même origine. C'est une protection de sécurité du navigateur, pas une limitation de GTM.
Comment faire remonter un événement depuis une iframe vers le dataLayer ?
Via window.postMessage() côté iframe et un écouteur window.addEventListener('message', ...) côté page parente qui relaie les données reçues vers dataLayer.push(). Il faut toujours vérifier e.origin en réception et ne jamais émettre avec un destinataire '*'.
Calendly envoie-t-il des événements exploitables pour le tracking ?
Oui, confirmé par sa documentation officielle : l'embed JS standard Calendly envoie des postMessage préfixés calendly. (profile_page_viewed, event_type_viewed, date_and_time_selected, event_scheduled), à condition d'utiliser l'embed standard et pas une iframe brute sans son script.
Faut-il installer un second conteneur GTM à l'intérieur d'une iframe ?
Seulement si l'iframe est sur un domaine distinct avec un besoin de mesure autonome, ou si vous n'avez pas accès au code de la page parente. Sinon, un seul conteneur sur la page parente avec la méthode postMessage évite la duplication de mesure et garde une identité de session unifiée.