SCRIPTWEBFLOWJAVASCRIPT

Exit popup

Quand la souris file vers la fermeture de l'onglet, la popin s'affiche. Une fois, puis plus rien avant le délai que tu fixes.

/ ÉTAPE 01

Copie-colle ce script dans le <body> de ta page

Ce script gère l'affichage de la popin quand l'utilisateur sort de la page. Elle a un délai de réapparition d'une minute par défaut, que tu peux modifier à tout moment.

exit-popup.html
<script>
// Exit Popup Script pour Webflow
// À placer dans les Custom Code Settings de Webflow (avant </body>)

(function() {
    'use strict';
    
    // Configuration
    const config = {
        sensitivity: 20,        // Sensibilité de détection (pixels)
        delay: 1000,           // Délai minimum avant déclenchement (ms)
        cookieExpiry: 1,      // Durée du cookie en minutes
        showOnMobile: false    // Afficher sur mobile
    };
    
    let popupShown = false;
    let mouseLeaveTimer = null;
    let isMouseTracking = false;
    let entryTime = Date.now();
    
    // Vérifier si l'utilisateur est sur mobile
    function isMobile() {
        return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) || 
               window.innerWidth <= 768;
    }
    
    // Gestion des cookies
    function setCookie(name, value, minutes) {
        const expires = new Date();
        expires.setTime(expires.getTime() + (minutes * 60 * 1000));
        document.cookie = `${name}=${value};expires=${expires.toUTCString()};path=/`;
    }
    
    function getCookie(name) {
        const nameEQ = name + "=";
        const ca = document.cookie.split(';');
        for(let i = 0; i < ca.length; i++) {
            let c = ca[i];
            while (c.charAt(0) === ' ') c = c.substring(1, c.length);
            if (c.indexOf(nameEQ) === 0) return c.substring(nameEQ.length, c.length);
        }
        return null;
    }
    
    // Afficher la popup
    function showPopup() {
        if (popupShown) return;
        
        const popup = document.querySelector('.popin_overlay');
        if (!popup) {
            console.warn('Exit Popup: Élément .popin_overlay introuvable');
            return;
        }
        
        popupShown = true;
        popup.style.display = 'flex';
        
        // Animation d'apparition
        setTimeout(() => {
            popup.style.opacity = '1';
        }, 10);
        
        // Définir le cookie pour éviter de re-afficher
        setCookie('exitPopupShown', 'true', config.cookieExpiry);
        
        console.log('Exit Popup: Popup affichée');
    }
    
    // Fermer la popup
    function closePopup() {
        const popup = document.querySelector('.popin_overlay');
        if (!popup) return;
        
        popup.style.opacity = '0';
        setTimeout(() => {
            popup.style.display = 'none';
        }, 300);
        
        console.log('Exit Popup: Popup fermée');
    }
    
    // Détecter la sortie de souris
    function handleMouseLeave(e) {
        if (popupShown) return;
        
        // Vérifier si assez de temps s'est écoulé
        if (Date.now() - entryTime < config.delay) return;
        
        const shouldTrigger = 
            e.clientY <= config.sensitivity ||                    
            e.clientX <= config.sensitivity ||                    
            e.clientX >= (window.innerWidth - config.sensitivity);
        
        if (shouldTrigger) {
            mouseLeaveTimer = setTimeout(() => {
                showPopup();
            }, 100);
        }
    }
    
    // Annuler le déclenchement si la souris revient rapidement
    function handleMouseEnter() {
        if (mouseLeaveTimer) {
            clearTimeout(mouseLeaveTimer);
            mouseLeaveTimer = null;
        }
    }
    
    // Initialiser le script
    function init() {
        if (isMobile() && !config.showOnMobile) {
            console.log('Exit Popup: Désactivé sur mobile');
            return;
        }
        
        if (getCookie('exitPopupShown')) {
            console.log('Exit Popup: Déjà affiché récemment');
            return;
        }
        
        const popup = document.querySelector('.popin_overlay');
        if (!popup) {
            console.warn('Exit Popup: Élément .popin_overlay introuvable');
            return;
        }
        
        popup.style.opacity = '0';
        popup.style.display = 'none';
        popup.style.transition = 'opacity 0.3s ease-in-out';
        
        document.addEventListener('mouseleave', handleMouseLeave);
        document.addEventListener('mouseenter', handleMouseEnter);
        
        const closeElements = document.querySelectorAll('.popin_close-overlay, .popin_close-btn');
        closeElements.forEach(element => {
            element.addEventListener('click', closePopup);
        });
        
        document.addEventListener('keydown', (e) => {
            if (e.key === 'Escape' && popupShown) {
                closePopup();
            }
        });
        
        popup.addEventListener('click', (e) => {
            if (e.target === popup) {
                closePopup();
            }
        });
        
        isMouseTracking = true;
        console.log('Exit Popup: Initialisé avec succès');
    }
    
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', init);
    } else {
        init();
    }
    
    window.ExitPopup = {
        show: showPopup,
        close: closePopup,
        reset: () => {
            setCookie('exitPopupShown', '', -1);
            popupShown = false;
            console.log('Exit Popup: Reset effectué');
        }
    };
    
})();
</script>
  1. 01La durée de réapparition : cherche "cookieExpiry" au tout début du code et modifie la valeur en minutes, « 30 », « 120 », « 180 »…

/ ÉTAPE 02

Structure HTML de la popin pour une parfaite accessibilité

Pour avoir une popin accessible et une expérience utilisateur correcte, suis la structure HTML suivante :

La structure HTML de la popin, avec l'overlay, le bouton de fermeture et le contenu

/ OÙ LE COLLER

DansWebflow, Paramètres › Custom code

CUSTOM CODE

PARAMÈTRES DU PROJET

Head code

<!-- vide -->

Footer code

<script> … </script>

Les codes personnalisés ne s'appliquent qu'après publication.

Footer code, jamais Head

Le script doit s'exécuter après le contenu de la page. Dans le Head, il ne trouverait rien à animer.

Une seule fois pour tout le site

Il se pose au niveau du projet, pas page par page. Les blocs le trouvent tout seuls.

Publier pour activer

Tant que le site n'est pas publié, le code personnalisé ne tourne pas, même en aperçu.

/ LES OPTIONS

Tout se pilote par classe et par attribut.

.popin_overlay

classe

Le conteneur de la popin, masqué tant que le script ne l'affiche pas.

.popin_close-btn

classe

Le bouton qui referme la popin.

.popin_close-overlay

classe

La zone hors de la popin, cliquable pour fermer.

cookieExpiry

réglage

Le délai en minutes avant que la popin puisse réapparaître.

sensitivity

réglage

La distance en pixels au-dessus de la fenêtre qui déclenche l'affichage.

showOnMobile

réglage

Affiche ou non la popin sur mobile, où il n'y a pas de sortie de souris.