Реализация Time-delayed Popup на сайте
Представьте: вы запускаете рекламную кампанию, лиды нужны уже вчера, но всплывающее окно появляется через 2 секунды после загрузки — пользователь ещё не увидел контент и закрывает его. Конверсия падает, бюджет слит. Time-delayed popup решает эту проблему: показываем предложение ровно в тот момент, когда посетитель готов воспринять его. При этом не раздражаем пользователя — кулдаун и A/B-тестирование позволяют найти идеальный баланс.
Исследования показывают: правильно настроенный time-delayed popup увеличивает конверсию в среднем на 15–30% по сравнению с мгновенным показом. Частота закрытий снижается в два раза. Дополнительно вы экономите до 30% рекламного бюджета за счёт более точного таргетинга на заинтересованных пользователей. Мы поможем вам настроить такой инструмент и провести A/B-тестирование для максимального эффекта.
Мы внедряем такие попапы под ключ: с A/B-тестированием, умным кулдауном и трекингом каждого показа. Ниже — техническая реализация, которую мы используем в продакшене, и советы по настройке.
Базовая реализация
// time-popup.ts interface TimePopupConfig { delayMs: number; cooldownKey: string; // ключ в localStorage cooldownMs?: number; // 0 = показать один раз навсегда onShow: () => void; } export function schedulePopup(config: TimePopupConfig): () => void { const { delayMs, cooldownKey, cooldownMs, onShow } = config; // Проверяем, нужно ли показывать const lastShown = localStorage.getItem(cooldownKey); if (lastShown) { if (!cooldownMs) return () => {}; // показали один раз, больше не надо if (Date.now() - Number(lastShown) < cooldownMs) return () => {}; } const timer = setTimeout(() => { // Дополнительная проверка: пользователь всё ещё на странице if (document.hidden) return; localStorage.setItem(cooldownKey, String(Date.now())); onShow(); }, delayMs); return () => clearTimeout(timer); } Попап с несколькими вариантами контента (A/B)
// DelayedPopup.tsx import { useEffect, useRef, useState } from 'react'; import { schedulePopup } from './time-popup'; type PopupVariant = 'discount' | 'lead-magnet' | 'callback'; const VARIANTS: Record<PopupVariant, { headline: string; body: string; cta: string; }> = { discount: { headline: 'Скидка 10% на первый заказ', body: 'Введите email — пришлём промокод немедленно.', cta: 'Получить скидку', }, 'lead-magnet': { headline: 'Бесплатный чеклист', body: '15 пунктов, которые мы проверяем на каждом проекте.', cta: 'Скачать PDF', }, callback: { headline: 'Остались вопросы?', body: 'Оставьте номер — перезвоним в течение 15 минут.', cta: 'Жду звонка', }, }; // Простой детерминированный A/B: делим по последней цифре даты function pickVariant(): PopupVariant { const bucket = new Date().getDate() % 3; return (['discount', 'lead-magnet', 'callback'] as PopupVariant[])[bucket]; } export function DelayedPopup() { const [open, setOpen] = useState(false); const [variant] = useState<PopupVariant>(pickVariant); const [value, setValue] = useState(''); const [submitted, setSubmitted] = useState(false); const dialogRef = useRef<HTMLDialogElement>(null); useEffect(() => { const cleanup = schedulePopup({ delayMs: 7000, cooldownKey: 'delayed_popup_v2', cooldownMs: 3 * 24 * 60 * 60 * 1000, // раз в 3 дня onShow: () => { setOpen(true); // трекинг показа window.gtag?.('event', 'popup_shown', { popup_variant: variant, page_path: location.pathname, }); }, }); return cleanup; }, [variant]); useEffect(() => { if (open) { dialogRef.current?.showModal(); } else { dialogRef.current?.close(); } }, [open]); async function handleSubmit() { if (!value.trim()) return; await fetch('/api/popup-lead', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ value, variant, source: 'time_delayed_popup', pageUrl: location.href, }), }); window.gtag?.('event', 'popup_converted', { popup_variant: variant }); setSubmitted(true); setTimeout(() => setOpen(false), 2500); } const content = VARIANTS[variant]; const inputType = variant === 'callback' ? 'tel' : 'email'; const placeholder = variant === 'callback' ? '+7 (999) 000-00-00' : '[email protected]'; return ( <dialog ref={dialogRef} onClose={() => setOpen(false)} className="max-w-sm w-full rounded-2xl p-0 shadow-2xl backdrop:bg-black/50 animate-in fade-in slide-in-from-bottom-4" > <div className="relative p-7"> <button onClick={() => setOpen(false)} aria-label="Закрыть" className="absolute top-3 right-3 w-7 h-7 flex items-center justify-center rounded-full hover:bg-gray-100 text-gray-400" > ✕ </button> {submitted ? ( <div className="py-4 text-center"> <div className="text-3xl mb-2">✅</div> <p className="font-semibold text-gray-800">Готово, ждите!</p> </div> ) : ( <> <h2 className="text-xl font-bold text-gray-900 mb-1">{content.headline}</h2> <p className="text-sm text-gray-500 mb-5">{content.body}</p> <div className="flex gap-2"> <input type={inputType} value={value} onChange={e => setValue(e.target.value)} onKeyDown={e => e.key === 'Enter' && handleSubmit()} placeholder={placeholder} autoFocus className="flex-1 border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500" /> <button onClick={handleSubmit} className="px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white text-sm font-medium rounded-lg whitespace-nowrap" > {content.cta} </button> </div> <p className="mt-3 text-xs text-gray-400"> Не будем беспокоить чаще одного раза в неделю </p> </> )} </div> </dialog> ); } A/B-тестирование для максимальной эффективности popup
A/B-тестирование позволяет сравнить несколько вариантов контента — скидка, лид-магнит, обратный звонок — и выбрать тот, который приносит больше конверсий. В нашей реализации варианты чередуются детерминированно: каждый день показывается один из трёх вариантов. Это упрощает анализ и исключает влияние дня недели. Результаты теста оцениваются по метрикам: показы, конверсии, CTR. Оптимальная длительность теста — 7–14 дней.
Почему time-delayed popup лучше exit-intent?
Exit-intent срабатывает, когда пользователь собирается покинуть страницу. Это перехватывает уходящих, но часто раздражает тех, кто случайно задел мышь. Time-delayed popup появляется в момент максимальной вовлечённости — через несколько секунд после загрузки. Пользователь уже ознакомился с контентом и готов к предложению. Исследования показывают, что время задержки 7–10 секунд даёт наилучший баланс между конверсией и пользовательским опытом.
Как выбрать оптимальную задержку?
Задержка напрямую влияет на конверсию и пользовательский опыт. Для страниц с длинным контентом (блоги, статьи) мы рекомендуем 5–7 секунд: достаточно времени, чтобы посетитель начал читать. Для коммерческих страниц (лендинги, карточки товаров) — 10–12 секунд, чтобы пользователь успел оценить предложение. Мы подбираем задержку под ваш сценарий на основе данных Google Analytics 4 и карт кликов.
Как мы реализуем time-delayed popup: пошагово
- Аналитика — изучаем текущее поведение пользователей через Google Analytics 4 и карты кликов.
- Проектирование — выбираем задержку, варианты контента, кулдаун. Делаем прототип в Figma.
- Реализация — используем нативные
<dialog>(поддержка IE не требуется), код на TypeScript + React. Интегрируем трекинг. Подробнее о<dialog>читайте в MDN. - A/B-тест — запускаем тест на 7–14 дней, сравниваем конверсию.
- Деплой и оптимизация — фиксируем лучший вариант, донастраиваем под Core Web Vitals.
Детали версионирования localStorage
Ключи кулдауна автоматически включают версию попапа (например, `popup_v2_lead_magnet`). Это позволяет сбросить показы при обновлении контента, просто изменив номер версии в конфиге.Что входит в работу
| Компонент | Описание |
|---|---|
| Исходный код | TypeScript/React компонент с конфигурацией |
| Документация | Инструкция по изменению контента и задержки |
| Интеграция трекинга | События в Google Analytics 4 |
| Настройка кулдауна | localStorage с версионированием |
| A/B-тестирование | Детерминированное распределение по дням |
| Поддержка | 1 месяц базовой поддержки после деплоя |
Сравнение типов popup
| Тип | Конверсия | Риск отказа | Сложность реализации |
|---|---|---|---|
| Time-delayed | 15–30% | Средний | Низкая |
| Exit-intent | 20–40% | Низкий | Средняя |
| Scroll-based | 10–20% | Высокий | Средняя |
| Immediate | 5–10% | Очень высокий | Низкая |
Time-delayed popup — золотая середина: простая реализация и хорошая конверсия без раздражения пользователей.
Сроки и стоимость
Срок реализации — от 1 до 3 дней в зависимости от сложности дизайна и необходимости A/B-теста. Средняя стоимость внедрения находится в диапазоне от 15 000 до 30 000 ₽ (точная сумма рассчитывается после аудита). Свяжитесь с нами для обсуждения вашего сценария — оценим проект за 1 день. Получите консультацию по настройке time-delayed popup.
Опыт компании
Более 15 лет на рынке веб-разработки. Реализовали 200+ проектов для e-commerce, SaaS и корпоративных сайтов. Гарантируем чистый код, безопасность (localStorage не хранит чувствительные данные) и полную интеграцию с вашей CRM.
Закажите внедрение time-delayed popup — свяжитесь с нами для оценки вашего проекта.







