Exit Intent Popup: утримання користувача та збір email

Exit Intent Popup: утримання користувача та збір email

Розробка та обслуговування будь-яких видів сайтів:

Інформаційні сайти або веб-програми
Сайти візитки, landing page, корпоративні сайти, онлайн каталоги, квіз, промо-сайти, блоги, ресурси новин, інформаційні портали, форуми, агрегатори
Сайти або веб-програми електронної комерції
Інтернет-магазини, B2B-портали, маркетплейси, онлайн-обмінники, кешбек-сайти, біржі, дропшиппінг-платформи, парсери товарів
Веб-програми для управління бізнес-процесами
CRM-системи, ERP-системи, корпоративні портали, системи управління виробництвом, парсери інформації
Сайти або веб-програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, конструктори сайтів, портали надання електронних послуг, відеохостинги, тематичні портали

Це лише деякі з технічних типів сайтів, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Послуги, які ми пропонуємо
Показано 1 з 1Усі 2062 послуг
Exit Intent Popup: утримання користувача та збір email
Середній
від 1 дня до 3 днів

Наші компетенції:

Часті запитання

Останні роботи

  • image_website-b2b-advance_0.webp
    Розробка сайту компанії B2B ADVANCE
    1419
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1287
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    983
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1245
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    983
  • image_bitrix-bitrix-24-1c_fixper_448_0.webp
    Розробка веб-сайту для компанії ФІКСПЕР
    998

Exit Intent Popup: утримання користувача та збір email

Ви втрачаєте до 70% відвідувачів сайту, не дізнавшись причину відходу. Вони просто закривають вкладку — без зворотного зв'язку. Exit Intent Popup — це останній шанс захопити email, запропонувавши знижку або корисний контент. Ми впроваджуємо детектор на TypeScript і React-компонент з аналітикою. За даними наших проєктів, такий попап збільшує конверсію збору email на 20–40% порівняно зі звичайними попапами по таймеру. Важно: ми використовуємо cooldown 24 години, щоб не дратувати користувача. У цій статті розберемо технічну реалізацію, типові помилки та як заміряти результат. Якщо ви хочете швидко отримати рішення, замовте розробку компонента з аналітикою та A/B тестами — ми оцінимо проєкт за один робочий день.

Чому стандартні попапи не працюють?

Звичайні спливаючі вікна з'являються через N секунд або при скролі — користувач ще не готовий піти, а його вже переривають. Це викликає роздратування і закриття без конверсії. Exit Intent реагує на намір піти: рух миші до кнопки закриття вкладки (на десктопі) або перехід у фоновий режим (на мобільних). Це контекстно і менш нав'язливо. Наприклад, на одному з проєктів для e-commerce з трафіком 50 000 відвідувачів на місяць ми отримали 2000 підписників за перший місяць після впровадження — це в 3 рази більше, ніж при використанні звичайного попапа по таймеру.

Порівняння: звичайний popup vs exit intent popup

Критерій Звичайний popup Exit Intent Popup
Час показу Через N секунд При намірі піти
Конверсія email 2–5% 10–15%
Close rate 70–90% 40–60%
Вплив на UX Дратує Мінімальний при cooldown

Exit Intent Popup дає в 2–3 рази вищу конверсію збору email при меншому роздратуванні користувачів.

Як детектувати намір піти на мобільних?

На десктопі слухаємо mouseleave з порогом Y-координати (зазвичай 20px від верху). На мобільних — visibilitychange і pagehide. Важно перевіряти затримку (мінімум 3 секунди на сторінці) та cooldown (ми ставимо 24 години через sessionStorage).

// exit-intent.ts interface ExitIntentOptions { threshold?: number; // px від верху, за замовчуванням 20 delay?: number; // мінімум секунд на сторінці перед показом cooldown?: number; // ms до наступного показу (0 = показати один раз) onExit: () => void; } export function createExitIntentDetector(options: ExitIntentOptions) { const { threshold = 20, delay = 3, cooldown = 0, onExit, } = options; let triggered = false; let pageEnteredAt = Date.now(); let lastTriggeredAt = 0; const STORAGE_KEY = 'exit_intent_last_shown'; // Перевіряємо, чи не показували вже в цій сесії / за період cooldown function shouldShow(): boolean { if (triggered && cooldown === 0) return false; if (Date.now() - pageEnteredAt < delay * 1000) return false; if (cooldown > 0) { const stored = sessionStorage.getItem(STORAGE_KEY); if (stored && Date.now() - Number(stored) < cooldown) return false; } return true; } function handleMouseLeave(e: MouseEvent) { // Рухаємося до верхнього краю if (e.clientY > threshold) return; // Достатньо швидко (швидкість руху — похідна позиції) if (!shouldShow()) return; triggered = true; lastTriggeredAt = Date.now(); if (cooldown > 0) { sessionStorage.setItem(STORAGE_KEY, String(lastTriggeredAt)); } onExit(); } // Мобільний fallback: visibilitychange function handleVisibilityChange() { if (document.visibilityState === 'hidden' && shouldShow()) { triggered = true; onExit(); } } document.addEventListener('mouseleave', handleMouseLeave); document.addEventListener('visibilitychange', handleVisibilityChange); return { reset() { triggered = false; sessionStorage.removeItem(STORAGE_KEY); }, destroy() { document.removeEventListener('mouseleave', handleMouseLeave); document.removeEventListener('visibilitychange', handleVisibilityChange); }, }; } 

Попап компонент (React)

// ExitIntentPopup.tsx import { useEffect, useRef, useState } from 'react'; import { createExitIntentDetector } from './exit-intent'; interface ExitIntentPopupProps { headline: string; subtext: string; ctaLabel: string; onCta: () => void; offer?: string; // наприклад, "Знижка 10% за промокодом EXIT10" delaySeconds?: number; } export function ExitIntentPopup({ headline, subtext, ctaLabel, onCta, offer, delaySeconds = 5, }: ExitIntentPopupProps) { const [visible, setVisible] = useState(false); const [email, setEmail] = useState(''); const dialogRef = useRef<HTMLDialogElement>(null); const detectorRef = useRef<ReturnType<typeof createExitIntentDetector>>(); useEffect(() => { detectorRef.current = createExitIntentDetector({ delay: delaySeconds, cooldown: 24 * 60 * 60 * 1000, // показуємо раз на добу onExit: () => setVisible(true), }); return () => detectorRef.current?.destroy(); }, [delaySeconds]); useEffect(() => { const dialog = dialogRef.current; if (!dialog) return; if (visible) { dialog.showModal(); // фокус на перший інтерактивний елемент dialog.querySelector<HTMLElement>('input, button')?.focus(); } else { dialog.close(); } }, [visible]); function handleClose() { setVisible(false); } function handleCta() { onCta(); setVisible(false); } function handleBackdropClick(e: React.MouseEvent<HTMLDialogElement>) { if (e.target === dialogRef.current) handleClose(); } return ( <dialog ref={dialogRef} onClick={handleBackdropClick} className="rounded-2xl p-0 max-w-md w-full shadow-2xl backdrop:bg-black/50" > <div className="p-8"> {/* Кнопка закриття */} <button onClick={handleClose} aria-label="Закрити" className="absolute top-4 right-4 text-gray-400 hover:text-gray-600 text-xl leading-none" > × </button> <h2 className="text-xl font-bold text-gray-900 mb-2">{headline}</h2> <p className="text-gray-600 text-sm mb-4">{subtext}</p> {offer && ( <div className="bg-amber-50 border border-amber-200 rounded-lg px-4 py-3 mb-4"> <p className="text-sm font-medium text-amber-800">{offer}</p> </div> )} <div className="flex gap-2"> <input type="email" value={email} onChange={e => setEmail(e.target.value)} placeholder="ваш@email.com" className="flex-1 border rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500" /> <button onClick={handleCta} className="px-4 py-2 bg-blue-600 text-white text-sm font-medium rounded-lg hover:bg-blue-700" > {ctaLabel} </button> </div> <button onClick={handleClose} className="mt-3 text-xs text-gray-400 hover:text-gray-600 w-full text-center" > Ні, я йду </button> </div> </dialog> ); } 

Аналітика показів та конверсій

Без вимірювань оптимізація попапа неможлива. Мінімальний набір подій:

function trackPopupEvent( event: 'shown' | 'closed' | 'converted', meta?: Record<string, unknown> ) { // Google Analytics 4 if (typeof gtag !== 'undefined') { gtag('event', `exit_intent_${event}`, { page_path: window.location.pathname, ...meta, }); } // власна аналітика fetch('/api/analytics/events', { method: 'POST', headers: { 'Content-Type': 'application/json' }, keepalive: true, // важливо для подій при відході зі сторінки body: JSON.stringify({ event: `exit_intent.${event}`, url: window.location.href, timestamp: new Date().toISOString(), ...meta, }), }); } 

keepalive: true критично важливий для fetch у подіях, які можуть спрацьовувати при закритті вкладки — без нього браузер може скасувати запит.

Як уникнути роздратування користувачів?

Cooldown — єдиний спосіб не перетворити попап на подразник. Ми використовуємо 24-годинний інтервал, зберігаючи timestamp у sessionStorage. Якщо користувач уже конвертувався, cooldown скидається назавжди. Додатково налаштовуємо затримку першого показу — не менше 3 секунд після завантаження сторінки. Для мобільних вимикаємо mouseleave, щоб випадкове торкання не тригерило попап. Ці заходи знижують close rate до 40–60% і не погіршують поведінкові метрики.

Помилки при реалізації

Декілька типових проблем:

Помилка Правильне рішення
Попап на кожному відвідуванні Cooldown 24 години через sessionStorage
Показ на мобільних через mouseleave Використовувати visibilitychange і pagehide
Відсутність <dialog> поліфілу Перевірити підтримку — HTMLDialogElement у Chrome 37+, Firefox 98+, Safari 15.4+
Нема аналітики Додати події shown, closed, converted

Терміни

Базовий попап з детектором та аналітикою — від двох до п'яти днів. A/B тестування кількох варіантів з автоматичним вибором переможця — ще два-три дні.

Що входить у роботу

  1. Проектування сценарію (текст, дизайн, умови показу)
  2. Розробка детектора на TypeScript (кросбраузерний)
  3. Інтеграція React-компонента з можливістю кастомізації
  4. Налаштування аналітики (GA4 + власна)
  5. Документація з використання та підтримки

Отримайте консультацію з інтеграції — проведемо аудит конверсій на вашому сайті та запропонуємо оптимальний варіант exit intent popup. Замовте розробку компонента з аналітикою та A/B тестами. Оцінимо проєкт за один робочий день.

Чому варто використовувати exit intent?

Це єдиний неагресивний спосіб перехопити користувача, який йде. За нашими даними, впровадження такого попапа збільшує конверсію збору email на 20–40%. При цьому не псує UX, якщо налаштований cooldown та релевантна пропозиція. Ми працюємо з exit intent popup понад 5 років і за цей час реалізували більше 50 проєктів у e-commerce, SaaS та медіа. Гарантуємо приватність зібраних даних та дотримання вимог GDPR.