Lorsqu’un formulaire est directement présent dans une page web, le suivi d’une soumission avec Google Tag Manager (GTM) est relativement simple.
La situation devient plus complexe lorsque le formulaire est intégré dans un iframe provenant d’un autre domaine. Dans ce cas, le conteneur Google Tag Manager installé sur le site principal ne peut généralement pas accéder directement au DOM du formulaire à cause de la politique de sécurité Same-Origin Policy.
Heureusement, il existe une solution propre et relativement simple : utiliser la fonctionnalité JavaScript postMessage() pour faire communiquer l’iframe avec la page parente.
Cet article explique comment mettre en place cette solution afin de déclencher une conversion Google Ads lorsqu'un formulaire est réellement envoyé avec succès.
1. Le problème avec un formulaire dans un iframe
Imaginons que notre site principal soit :
https://www.monsite.be/contact
et que le formulaire soit fourni par un service externe :
https://formulaire.exemple.com/contact
La page principale contient simplement :
<iframe
src="https://formulaire.exemple.com/contact"
width="100%"
height="600"
frameborder="0">
</iframe>
Le problème est que le JavaScript exécuté sur
www.monsite.be ne peut pas simplement faire :
document.querySelector('iframe')
.contentWindow.document.querySelector('form');
si l’iframe provient d’un autre domaine.
Le navigateur bloque cet accès pour des raisons de sécurité.
2. La solution : utiliser postMessage()
Les navigateurs proposent une API spécialement prévue pour permettre à deux fenêtres provenant de domaines différents de communiquer : window.postMessage().
Le principe est le suivant :
- L’utilisateur remplit le formulaire.
- Le formulaire est envoyé.
- Le serveur traite la demande.
- La page de confirmation est affichée dans l’iframe.
- Cette page de confirmation envoie un message à la page parente.
- La page parente récupère le message.
- Le JavaScript de la page parente envoie un événement dans le
dataLayer. - Google Tag Manager détecte cet événement.
- GTM déclenche la conversion Google Ads.
3. Faire envoyer un message par l’iframe
La première partie de la solution doit être mise en place dans le formulaire ou dans sa page de confirmation.
Par exemple, après une soumission réussie, la page de confirmation peut contenir :
<script>
window.parent.postMessage(
{
source: 'external-form',
event: 'form_submitted',
form: 'contact',
lang: 'fr'
},
'https://www.monsite.be'
);
</script>
Le deuxième paramètre de postMessage() est important :
il permet de préciser quelle origine est autorisée à recevoir le message.
Il est préférable d'indiquer explicitement le domaine parent plutôt que d'utiliser
*.
4. Vérifier que le message est envoyé uniquement après un succès
Il est important de ne pas déclencher la conversion simplement lorsque l’utilisateur clique sur le bouton « Envoyer ».
Un clic ne signifie pas nécessairement que le formulaire a été correctement traité.
Le meilleur endroit pour envoyer le message est donc généralement la page de confirmation affichée après une soumission réussie.
Par exemple :
<body data-success="1">
<h1>Merci, votre demande a été envoyée.</h1>
<script>
if (document.body.dataset.success === '1') {
window.parent.postMessage(
{
source: 'external-form',
event: 'form_submitted',
form: 'contact'
},
'https://www.monsite.be'
);
}
</script>
</body>
De cette manière, le message n’est envoyé que lorsque le serveur considère réellement le formulaire comme envoyé.
5. Écouter le message dans la page principale
Nous devons maintenant récupérer le message dans la page contenant l’iframe.
On peut utiliser l'événement JavaScript message :
window.addEventListener('message', function(event) {
console.log('Message reçu :', event.origin, event.data);
});
Pour des raisons de sécurité, il est fortement recommandé de vérifier
event.origin.
Par exemple :
window.addEventListener('message', function(event) {
if (event.origin !== 'https://formulaire.exemple.com') {
return;
}
console.log('Message reçu :', event.data);
});
6. Vérifier le contenu du message
Nous pouvons également vérifier que le message correspond bien à notre formulaire.
window.addEventListener('message', function(event) {
if (event.origin !== 'https://formulaire.exemple.com') {
return;
}
if (
event.data &&
event.data.source === 'external-form' &&
event.data.event === 'form_submitted'
) {
console.log('Formulaire envoyé avec succès');
}
});
Cette vérification évite de traiter n'importe quel message provenant de l’iframe comme une conversion.
7. Envoyer l’événement dans le dataLayer
Google Tag Manager utilise le dataLayer pour recevoir des événements
et des données provenant du site.
Nous allons donc transformer le message reçu en événement GTM :
window.addEventListener('message', function(event) {
if (event.origin !== 'https://formulaire.exemple.com') {
return;
}
if (
event.data &&
event.data.source === 'external-form' &&
event.data.event === 'form_submitted'
) {
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
event: 'form_submitted',
form: event.data.form,
lang: event.data.lang
});
}
});
C’est cette instruction qui est essentielle :
window.dataLayer.push({
event: 'form_submitted'
});
Elle crée un événement personnalisé que Google Tag Manager peut ensuite utiliser comme déclencheur.
8. Installer ce code avec Google Tag Manager
Si l’on ne peut pas modifier directement le code du site principal, le listener peut être installé avec une balise HTML personnalisé dans Google Tag Manager.
Dans GTM :
- Ouvrir le conteneur Google Tag Manager.
- Aller dans Balises.
- Cliquer sur Nouvelle.
- Choisir HTML personnalisé.
- Ajouter le code JavaScript.
- Déclencher la balise sur Initialization - All Pages.
Exemple complet :
<script>
window.addEventListener('message', function(event) {
if (event.origin !== 'https://formulaire.exemple.com') {
return;
}
if (
event.data &&
event.data.source === 'external-form' &&
event.data.event === 'form_submitted'
) {
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
event: 'form_submitted',
form: event.data.form,
lang: event.data.lang
});
console.log('GTM : formulaire envoyé', event.data);
}
});
</script>
9. Pourquoi utiliser Initialization - All Pages ?
Le listener doit être installé suffisamment tôt dans le chargement de la page.
Si le formulaire peut être utilisé rapidement après l’ouverture de la page, il est préférable que le code d’écoute soit déjà actif.
Le déclencheur :
Initialization - All Pages
permet donc d’installer le listener dès que possible.
10. Créer le déclencheur personnalisé dans GTM
Nous avons maintenant un événement appelé :
form_submitted
Il faut créer un déclencheur correspondant.
Dans Google Tag Manager :
- Aller dans Déclencheurs.
- Cliquer sur Nouveau.
- Choisir Événement personnalisé.
- Indiquer
form_submittedcomme nom de l'événement. - Enregistrer.
On peut par exemple appeler le déclencheur :
Event - Formulaire iframe envoyé
11. Configurer la conversion Google Ads
Il faut maintenant utiliser ce nouveau déclencheur sur la balise de conversion Google Ads.
La balise Google Ads doit être configurée avec l’identifiant et le libellé de conversion fournis par Google Ads.
Surtout, la conversion ne doit pas être déclenchée simplement lorsque l’utilisateur visite la page contenant le formulaire.
12. Tester avec Google Tag Assistant
Avant de publier les modifications dans Google Tag Manager, il faut impérativement utiliser le mode Prévisualiser.
- Dans Google Tag Manager, cliquer sur Prévisualiser.
- Entrer l’URL de la page contenant l’iframe.
- Connecter Tag Assistant.
- Vérifier que le conteneur GTM est correctement chargé.
- Remplir le formulaire.
- Envoyer le formulaire.
Dans la timeline de Google Tag Assistant, on doit normalement voir les événements classiques tels que :
Initialisation
Conteneur chargé
DOM prêt
Fenêtre chargée
Après l’envoi réussi du formulaire, un nouvel événement doit apparaître :
form_submitted
C’est le signe que le message provenant de l’iframe a bien été transformé en événement
dans le dataLayer.
13. Vérifier les balises déclenchées
Cliquer sur l’événement form_submitted dans Tag Assistant.
Dans la section Balises déclenchées, la balise de conversion Google Ads doit apparaître.
Le résultat attendu est donc :
Événement : form_submitted
Balises déclenchées :
- Conversion Linker
- Conversion Google Ads
La balise de conversion ne doit pas être déclenchée simplement sur l'événement Page View de la page Contact.
14. Tester également un simple chargement de la page
Il est important de réaliser le test inverse.
Rechargez simplement la page Contact sans envoyer le formulaire.
La conversion Google Ads ne doit pas apparaître parmi les balises déclenchées.
Cela permet de vérifier que l'on mesure bien un lead et non une simple visite.
15. Tester le message directement dans la console
En cas de problème, la console JavaScript du navigateur permet de vérifier si le message envoyé par l’iframe arrive bien dans la page principale.
Sur la page contenant l’iframe, ouvrir les outils de développement du navigateur puis la console et exécuter :
window.addEventListener('message', function(event) {
console.log('MESSAGE REÇU', {
origin: event.origin,
data: event.data
});
});
Puis envoyer le formulaire.
Si tout fonctionne, on doit obtenir un résultat similaire à :
MESSAGE REÇU
origin: https://formulaire.exemple.com
data:
{
source: "external-form",
event: "form_submitted",
form: "contact",
lang: "fr"
}
Si ce message apparaît dans la console mais pas dans Google Tag Assistant,
le problème se situe probablement dans le code qui pousse l'événement dans le
dataLayer ou dans le chargement de la balise GTM.
Si aucun message n'apparaît dans la console, il faut alors vérifier le code
postMessage() côté iframe.
16. Vérifier le dataLayer
Une autre vérification utile consiste à regarder directement le contenu du
dataLayer.
Dans la console :
dataLayer
Après l'envoi du formulaire, on doit retrouver un objet contenant notamment :
{
event: "form_submitted",
form: "contact",
lang: "fr"
}
17. Attention au domaine de l’iframe
Une erreur fréquente consiste à oublier que event.origin correspond
au domaine qui envoie le message, et non au domaine de la page principale.
Par exemple, si l’iframe est chargée depuis :
https://formulaire.exemple.com
alors la vérification doit être :
if (event.origin !== 'https://formulaire.exemple.com') {
return;
}
et non :
if (event.origin !== 'https://www.monsite.be') {
return;
}
18. Pourquoi éviter postMessage avec *
On rencontre souvent cette syntaxe :
window.parent.postMessage(message, '*');
Elle fonctionne techniquement, mais elle est moins restrictive.
Lorsque le domaine parent est connu, il est préférable d'utiliser :
window.parent.postMessage(
message,
'https://www.monsite.be'
);
De la même manière, le listener côté parent doit vérifier l'origine du message.
19. Checklist finale
Avant de publier la configuration, vérifiez les points suivants :
- Le formulaire est bien contenu dans un iframe.
- L’iframe envoie un
postMessage()après une soumission réussie. - Le domaine de destination du
postMessage()est correct. - Le listener GTM est chargé sur la page principale.
- Le listener vérifie correctement
event.origin. - Le message contient bien
event: 'form_submitted'. - Le code effectue un
dataLayer.push(). - L'événement
form_submittedapparaît dans Google Tag Assistant. - Le déclencheur GTM utilise l'événement personnalisé
form_submitted. - La conversion Google Ads utilise ce déclencheur.
- La conversion ne se déclenche pas lors d'une simple visite de la page Contact.
- La conversion se déclenche après une soumission réussie.
Conclusion
Le fait qu’un formulaire soit placé dans un iframe externe ne signifie donc pas qu’il est impossible de suivre ses conversions avec Google Tag Manager.
La solution consiste à faire communiquer l’iframe et la page principale avec
postMessage(), puis à transformer ce message en événement
dataLayer.
Google Tag Manager peut alors utiliser cet événement comme déclencheur pour Google Ads.
L'avantage principal de cette méthode est que la conversion est liée à une soumission réussie du formulaire, plutôt qu'à un simple clic ou à une visite de la page.