Skip to content

Tout pour WordPress, le développement web — et plus encore

🐛 Contact Form 7 dans une popup Elementor : pourquoi le formulaire recharge la page et comment y remédier

🐛 Contact Form 7 dans une popup Elementor : pourquoi le formulaire recharge la page et comment y remédier

Vous ajoutez un formulaire de contact via Contact Form 7 dans une popup Elementor Pro. L’utilisateur remplit les champs, clique sur «Envoyer» et la page entière se recharge.

Pas de message d’erreur. Pas de confirmation d’envoi. Juste un rechargement et un lead perdu.

Il s’agit d’un conflit connu: CF7 repose sur une soumission AJAX, mais à l’intérieur d’une popup chargée dynamiquement, son JavaScript n’a pas le temps de se lier au formulaire. Résultat: le navigateur exécute une soumission HTML classique, celle-là même qui provoque le rechargement.

Le problème existe depuis des années, pourtant il se corrige avec seulement deux lignes de code. Voici deux solutions fonctionnelles: une approche moderne (plus propre et plus fiable) et une alternative issue de GitHub, ainsi que des améliorations optionnelles et une checklist de débogage.

💡 Aperçu rapide:

  • Cause racine: CF7 s’initialise au chargement de la page, mais la popup contenant le formulaire apparaît plus tard, donc le script ignore tout de son contenu
  • Solution 1: réinitialiser CF7 lorsque l’événement elementor/popup/show se déclenche; le JavaScript attend l’ouverture de la popup et prend en charge le formulaire
  • Solution 2: suivre les clics sur le bouton qui ouvre la popup avec un délai pour l’animation; cette méthode provient d’une discussion GitHub sur Elementor
  • Optionnel: réinitialiser le formulaire à la réouverture et fermer automatiquement la popup après un envoi réussi
  • Checklist de débogage: console du navigateur, conflits jQuery, plugins de cache

Pourquoi CF7 se casse spécifiquement dans une popup

Développeur corrigeant un bug de Contact Form 7 dans WordPress

Contact Form 7 est conçu sur AJAX: le formulaire s’envoie sans rechargement, la validation des champs se fait à la volée et les messages d’erreur ou de succès apparaissent instantanément. Cependant, tout ce mécanisme se lie au DOM au chargement de la page via un appel à wpcf7.init().

Elementor Pro charge le contenu des popups dynamiquement, après l’événement DOMContentLoaded. Lorsqu’un utilisateur clique sur un bouton et que la popup s’ouvre, son HTML est inséré dans le document, mais CF7 n’en sait rien. Le formulaire à l’intérieur de la popup reste non initialisé.

Ce qui se passe ensuite: sans gestionnaire AJAX actif, le navigateur effectue une soumission HTML standard. L’attribut action se déclenche et la page se recharge. La popup se ferme naturellement (son état est réinitialisé à la navigation). L’utilisateur voit un rechargement et quitte la page.

Beaucoup de développeurs essaient de traiter les symptômes: ils empêchent la fermeture de la popup avec event.stopPropagation(), surchargent les fonctions internes d’Elementor ou bloquent la soumission du formulaire avec e.preventDefault(). Aucune de ces méthodes ne traite la cause racine (l’absence d’initialisation de CF7). Certaines cassent même les animations de popup ou Elementor lui-même sur l’ensemble du site.

Il n’existe qu’une seule solution fiable: attendre l’ouverture de la popup et appeler explicitement wpcf7.init() pour chaque formulaire à l’intérieur.

Solution 1: réinitialisation à l’ouverture de la popup (approche moderne)

Cette méthode utilise l’événement natif elementor/popup/show d’Elementor. Placez le code dans le fichier functions.php de votre thème actif ou ajoutez-le via un plugin de snippets comme Code Snippets.

Faites une sauvegarde de functions.php avant toute modification.

1/**
2 * Reinitialize Contact Form 7 when opening an Elementor popup.
3 * Fixes page reload after form submission.
4 */
5function sdstudio_cf7_reinit_in_popup() {
6 ?>
7 <script>
8 jQuery( document ).on( 'elementor/popup/show', function() {
9 document.querySelectorAll( '.wpcf7 form' ).forEach( function( form ) {
10 if ( typeof wpcf7 !== 'undefined' ) {
11 wpcf7.init( form );
12 }
13 });
14 });
15 </script>
16 <?php
17}
18add_action( 'wp_footer', 'sdstudio_cf7_reinit_in_popup' );

Après avoir sauvegardé, ouvrez la popup contenant le formulaire et testez-la: remplissez les champs obligatoires de manière incorrecte et cliquez sur «Envoyer». Les messages de validation doivent apparaître instantanément, sans rechargement. Ensuite, soumettez le formulaire correctement et confirmez que le message de succès s’affiche également dans la popup.

Le code attend l’événement elementor/popup/show, qui est garanti de se déclencher après le rendu du contenu de la popup. Ensuite, querySelectorAll trouve tous les formulaires CF7 dans le DOM actuel et wpcf7.init() leur attache de force la validation et la soumission AJAX. La vérification typeof wpcf7 !== 'undefined' protège contre les erreurs si CF7 ne s’est pas chargé pour une raison quelconque.

Solution 2: suivi des clics sur le bouton de la popup (méthode alternative)

Cette approche est publiée dans la discussion GitHub #7798 d’Elementor par l’utilisateur @drinkmaker. Au lieu de suivre l’ouverture de la popup, elle surveille les clics sur un bouton ou un lien avec href='#elementor-action', ce qui est exactement la manière dont Elementor déclenche les popups.

Le délai setTimeout(..., 800) laisse le temps à l’animation d’apparition de la popup avant que le code ne trouve et n’initialise le formulaire. Le marqueur .elementor empêche de réinitialiser deux fois le même formulaire.

1/**
2 * Alternative initialization of CF7 in Elementor popups.
3 * Source: https://github.com/elementor/elementor/issues/7798 (drinkmaker)
4 */
5function sdstudio_elementor_cf7_alt_init() {
6 ?>
7 <script type='text/javascript'>
8 jQuery( document ).ready( function() {
9
10 jQuery( document ).on( 'click', "a[href='#elementor-action']", function() {
11
12 setTimeout( function() {
13
14 jQuery( '.elementor-popup-modal form.wpcf7-form:not(.elementor)' ).each( function( index ) {
15 wpcf7.initForm( jQuery( this ) );
16 jQuery( this ).addClass( 'elementor' );
17 });
18
19 }, 800 );
20
21 });
22
23 });
24 </script>
25 <?php
26}
27add_action( 'wp_footer', 'sdstudio_elementor_cf7_alt_init' );

Quelle méthode choisir: la première (utilisant l’événement elementor/popup/show) est préférable car elle s’appuie sur l’API documentée d’Elementor, est plus propre et ne dépend pas de timeouts. La seconde a été éprouvée en production pendant des années et sert de plan B fiable si la première ne fonctionne pas pour une raison quelconque.

Optionnel: réinitialiser le formulaire à la réouverture

Lorsqu’un utilisateur ferme la popup et la rouvre, les champs du formulaire restent remplis. C’est déroutant: on ne sait pas si le formulaire a été envoyé ou non. Un petit ajout à la première solution corrige cela:

1/**
2 * Reset CF7 form each time an Elementor popup opens.
3 */
4function sdstudio_cf7_reset_on_popup_open() {
5 ?>
6 <script>
7 jQuery( document ).on( 'elementor/popup/show', function() {
8 jQuery( '.wpcf7 form' ).each( function() {
9 this.reset();
10 jQuery( this ).find( '.wpcf7-not-valid' ).removeClass( 'wpcf7-not-valid' );
11 jQuery( this ).find( '.wpcf7-response-output' ).hide();
12 jQuery( this ).find( '.wpcf7-not-valid-tip' ).remove();
13 });
14 });
15 </script>
16 <?php
17}
18add_action( 'wp_footer', 'sdstudio_cf7_reset_on_popup_open' );

La fonction réinitialise les valeurs des champs avec reset(), supprime les classes CSS des champs invalides, masque les messages de soumission et retire les infobulles de validation. L’utilisateur voit toujours un formulaire vierge.

Optionnel: fermer la popup après un envoi réussi

Après un envoi réussi, il est logique de fermer automatiquement la popup après 1,5 seconde pour que l’utilisateur ait le temps de lire la confirmation sans avoir à chercher le bouton de fermeture:

1/**
2 * Auto-close Elementor popup after successful CF7 submission.
3 */
4function sdstudio_close_popup_on_cf7_success() {
5 ?>
6 <script>
7 document.addEventListener( 'wpcf7mailsent', function() {
8 setTimeout( function() {
9 jQuery( '.dialog-close-button' ).trigger( 'click' );
10 }, 1500 );
11 }, false );
12 </script>
13 <?php
14}
15add_action( 'wp_footer', 'sdstudio_close_popup_on_cf7_success' );

L’événement wpcf7mailsent se déclenche lorsque le serveur confirme que l’email a été envoyé. Le délai de 1500 ms donne à l’utilisateur le temps de lire le message de succès. Le clic sur .dialog-close-button utilise le bouton de fermeture standard d’Elementor. Contrairement aux tentatives d’appel direct de l’API de popup, cette méthode est stable sur toutes les versions.

Checklist de débogage

Si le formulaire recharge encore la page après avoir ajouté le code, passez en revue ces étapes:

  • Console du navigateur. Ouvrez les DevTools (F12 → Console) et cherchez les erreurs JavaScript en rouge. Une cause fréquente est jQuery qui ne se charge pas ou qui entre en conflit avec un autre plugin.

  • Cache. Des plugins comme WP Rocket, Autoptimize ou un cache au niveau de l’hébergement peuvent minifier et combiner les scripts. Désactivez temporairement l’optimisation JS agressive et testez à nouveau.

  • jQuery en mode noConflict. Si un thème ou un plugin enveloppe jQuery dans noConflict, remplacez jQuery par $ en utilisant un wrapper approprié, ou utilisez la forme complète jQuery.

  • ID de la popup. Assurez-vous que le formulaire se trouve bien dans la popup exacte déclenchée par un bouton avec href='#elementor-action'. Pour les popups ouvertes via d’autres types de déclencheurs (par exemple, sur minuterie), la première méthode avec elementor/popup/show est plus fiable.

  • Conflit de plugins. Désactivez les autres plugins un par un et testez, en particulier ceux qui ajoutent leurs propres scripts de validation ou modifient le comportement des formulaires.

  • Version de CF7. Ces solutions ont été testées sur Contact Form 7 version 5.7+ et Elementor Pro 3.5+. Si votre version de CF7 est inférieure à 5.7, la fonction wpcf7.init() peut porter un nom différent; mettez le plugin à jour.

⁉️🤔 Foire aux questions

Pourquoi CF7 fonctionne sur une page normale mais se casse dans une popup?

Lorsqu’une page normale se charge, le DOM est déjà construit et CF7 a le temps d’initialiser tous les formulaires. La popup d’Elementor charge son contenu de manière asynchrone, après que CF7 a terminé son travail. Le formulaire se retrouve dans le DOM mais sans gestionnaire JavaScript lié. C’est pourquoi vérifier que «ça marche sur une page séparée» n’aide pas: les conditions de chargement sont fondamentalement différentes. La solution est toujours la réinitialisation forcée à l’ouverture de la popup, que le formulaire fonctionne ailleurs ou non.

Puis-je m’en sortir sans code, avec un plugin ou un réglage?

Il n’existe pas de plugin prêt à l’emploi qui permette de «cocher une case et ça marche» pour ce bug. Le problème se situe à l’intersection de deux produits indépendants (Elementor et CF7), et chacun fonctionne correctement de son côté. Les extensions tierces comme WPB Popup for Contact Form 7 résolvent le problème différemment: elles créent leurs propres popups au lieu de corriger Elementor. Le code ci-dessus est l’intervention minimale nécessaire. Vous l’ajoutez une fois à functions.php et il ne nécessite pas de mises à jour lors des nouvelles versions de CF7 ou d’Elementor.

La première méthode n’a pas fonctionné. Que dois-je vérifier avant de passer à la seconde?

Vérifiez trois choses. Premièrement: l’événement elementor/popup/show est disponible à partir d’Elementor Pro 2.7; si votre version est inférieure, utilisez directement la seconde méthode. Deuxièmement: ouvrez la console et tapez typeof wpcf7; si c’est undefined, le plugin CF7 n’a pas chargé son JavaScript (cherchez des erreurs ou des conflits). Troisièmement: assurez-vous que le formulaire dans la popup possède la classe .wpcf7; sans elle, le sélecteur querySelectorAll('.wpcf7 form') ne trouvera rien. Dans la grande majorité des cas, la première méthode fonctionne immédiatement. Sinon, utilisez la seconde: elle a fait ses preuves sur des centaines de sites au fil des ans.

Dois-je ajouter les trois snippets ou un seul suffit?

Le premier snippet (réinitialisation) est le minimum indispensable. Le deuxième est une alternative; ajoutez-le uniquement si le premier n’a pas résolu le problème. La réinitialisation du formulaire et la fermeture automatique de la popup sont des améliorations optionnelles que vous pouvez ajouter selon vos besoins: la réinitialisation est utile si la popup s’ouvre plusieurs fois au cours d’une même visite; la fermeture automatique est pratique si la popup sert à des demandes de renseignements et ne contient pas un long texte de confirmation. Les trois snippets sont indépendants et peuvent fonctionner simultanément. Il n’y a aucun conflit entre eux.

Après la correction, le formulaire s’envoie, mais les emails n’arrivent pas. Est-ce lié?

Non, les problèmes de délivrabilité des emails sont un sujet distinct, sans rapport avec le fonctionnement de CF7 dans une popup. Si après avoir appliqué la correction le formulaire affiche un message de succès (bordure verte), la soumission AJAX fonctionne correctement. Emails non reçus: vérifiez les paramètres SMTP, les filtres anti-spam de l’hébergement et l’adresse du destinataire dans les réglages du formulaire CF7. Pour une délivrabilité fiable, utilisez un plugin SMTP comme Post SMTP ou FluentSMTP plutôt que la fonction standard wp_mail(), car les hébergeurs bloquent souvent le courrier PHP sortant.

Cette solution affecte-t-elle les autres formulaires CF7 du site?

Non. Les deux méthodes sont isolées: la première attend l’ouverture d’une popup Elementor, la seconde ne suit que les liens avec href='#elementor-action'. Les formulaires CF7 classiques placés sur des pages et dans des widgets continuent de fonctionner normalement; ils sont initialisés au chargement de la page et ne sont pas affectés. Seule mise en garde: si votre site utilise une mise en cache agressive avec concaténation des scripts, ajoutez le code de la popup aux exclusions de minification pour éviter une double exécution.

Est-ce que cela vaut la peine de s’embêter avec du code personnalisé en 2026

Les deux plugins, Contact Form 7 et Elementor Pro, sont activement développés et mis à jour. CF7 conserve sa position de plugin de formulaire WordPress le plus populaire avec plus de 5 millions d’installations actives. Elementor Pro est utilisé sur un site WordPress sur quatre.

Pourtant, le bug décrit ici n’a pas été corrigé au niveau du cœur de l’un ou l’autre plugin et ne le sera probablement jamais. La raison est architecturale: CF7 est responsable des formulaires, Elementor est responsable du contenu dynamique, et l’initialisation des scripts dans un DOM chargé dynamiquement reste de la responsabilité du développeur.

La bonne nouvelle: la correction est triviale, le code s’ajoute une fois et ne nécessite aucune maintenance. Choisissez la première méthode (l’événement elementor/popup/show): c’est la plus propre et vous pouvez oublier le problème. Si le formulaire dans la popup est utilisé pour des scénarios critiques de génération de leads, ajoutez également la réinitialisation des champs et la fermeture automatique: l’expérience utilisateur s’améliorera sensiblement.

Regardez la vidéo ci-dessus: elle montre le processus complet de mise en place d’une popup avec Contact Form 7 dans Elementor. Ce guide visuel étape par étape complète les snippets fournis ici et vous aide à éviter les erreurs lors de l’assemblage.