Реализация триггерных pop-up окон по поведению пользователя на сайте

Наша компания занимается разработкой, поддержкой и обслуживанием сайтов любой сложности. От простых одностраничных сайтов до масштабных кластерных систем построенных на микро сервисах. Опыт разработчиков подтвержден сертификатами от вендоров.

Разработка и обслуживание любых видов сайтов:

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

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Предлагаемые услуги
Показано 1 из 1 услугВсе 2065 услуг
Реализация триггерных pop-up окон по поведению пользователя на сайте
Средняя
~2-3 рабочих дня
Часто задаваемые вопросы

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

Этапы разработки

Последние работы

  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    874
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    851

Реализация триггерных pop-up окон по поведению пользователя на сайте

Триггерный поп-ап — это всплывающее окно, которое показывается не по таймеру, а по конкретному действию пользователя: движение мыши к закрытию вкладки, длительная пауза на определённом блоке, прокрутка до нижней части страницы. Правильно настроенный поп-ап поднимает конверсию на 2–5%, неправильный — раздражает и уводит людей.

Типы триггеров

Основные триггеры, которые стоит реализовывать:

  • Exit intent — мышь ускоряется к верхнему краю экрана, пользователь собирается закрыть вкладку
  • Scroll depth — прокрутка достигла N% страницы
  • Time on page — пользователь провёл на странице X секунд
  • Inactivity — нет движения мыши и кликов больше Y секунд
  • Element visibility — конкретный блок попал во viewport
  • Click intent — наведение на определённый элемент без клика

Exit Intent

Самый эффективный триггер для лендингов. Определяется по скорости и направлению движения курсора:

class ExitIntentDetector {
  private threshold = 10; // пикселей от верхнего края
  private sensitivity = 50; // px/ms — минимальная скорость движения вверх
  private triggered = false;
  private lastY = 0;
  private lastTime = 0;

  constructor(private onExit: () => void) {
    document.addEventListener('mousemove', this.handleMouseMove.bind(this));
  }

  private handleMouseMove(e: MouseEvent): void {
    if (this.triggered) return;

    const now = Date.now();
    const deltaY = e.clientY - this.lastY;
    const deltaTime = now - this.lastTime;
    const velocityY = deltaY / deltaTime; // px/ms, отрицательное = движение вверх

    if (e.clientY < this.threshold && velocityY < -this.sensitivity) {
      this.triggered = true;
      this.onExit();
    }

    this.lastY = e.clientY;
    this.lastTime = now;
  }

  reset(): void {
    this.triggered = false;
  }
}

// Использование
const detector = new ExitIntentDetector(() => {
  showPopup('exit_offer');
});

На мобильных устройствах exit intent не работает — там нет события mousemove. Вместо него используйте триггер по нажатию кнопки «Назад» через popstate:

// Мобильный exit: пуш состояния в историю, ловим выход
history.pushState({ popup: true }, '');
window.addEventListener('popstate', (e) => {
  if (!e.state?.popup) {
    showPopup('mobile_exit_offer');
    history.pushState({ popup: true }, '');
  }
});

Scroll Depth триггер

function onScrollDepth(percentage: number, callback: () => void): () => void {
  let fired = false;

  const handler = () => {
    if (fired) return;
    const scrolled = window.scrollY + window.innerHeight;
    const total = document.documentElement.scrollHeight;
    if (scrolled / total >= percentage / 100) {
      fired = true;
      callback();
    }
  };

  window.addEventListener('scroll', handler, { passive: true });
  return () => window.removeEventListener('scroll', handler);
}

// Поп-ап при прокрутке 70% страницы
onScrollDepth(70, () => showPopup('mid_page_offer'));

Element Visibility (Intersection Observer)

Показывать поп-ап когда пользователь доскроллил до блока с ценами:

function onElementVisible(selector: string, callback: () => void): void {
  const el = document.querySelector(selector);
  if (!el) return;

  const observer = new IntersectionObserver(
    (entries) => {
      if (entries[0].isIntersecting) {
        observer.disconnect();
        callback();
      }
    },
    { threshold: 0.5 } // элемент виден на 50%
  );

  observer.observe(el);
}

onElementVisible('#pricing-section', () => showPopup('pricing_helper'));

Менеджер состояния поп-апов

Критически важно не показывать один поп-ап несколько раз и не показывать сразу несколько:

class PopupManager {
  private shown = new Set<string>(
    JSON.parse(localStorage.getItem('shown_popups') ?? '[]')
  );
  private currentPopup: string | null = null;

  canShow(id: string, cooldownDays = 7): boolean {
    if (this.currentPopup) return false; // уже открыт другой

    const key = `popup_shown_${id}`;
    const lastShown = localStorage.getItem(key);
    if (!lastShown) return true;

    const daysSince = (Date.now() - parseInt(lastShown)) / 86400000;
    return daysSince >= cooldownDays;
  }

  show(id: string): void {
    if (!this.canShow(id)) return;

    this.currentPopup = id;
    localStorage.setItem(`popup_shown_${id}`, Date.now().toString());
    this.shown.add(id);
    localStorage.setItem('shown_popups', JSON.stringify([...this.shown]));

    document.getElementById(`popup-${id}`)?.classList.add('popup--visible');
    document.body.classList.add('popup-open');
  }

  close(id: string): void {
    this.currentPopup = null;
    document.getElementById(`popup-${id}`)?.classList.remove('popup--visible');
    document.body.classList.remove('popup-open');
  }
}

const popups = new PopupManager();
function showPopup(id: string) { popups.show(id); }

Трекинг показов и конверсий

Каждый поп-ап должен фиксировать impressions, clicks и closes:

document.querySelectorAll('[data-popup]').forEach(popup => {
  const id = popup.getAttribute('data-popup')!;

  // Impression при открытии
  const observer = new MutationObserver(() => {
    if (popup.classList.contains('popup--visible')) {
      gtag('event', 'popup_impression', { popup_id: id });
    }
  });
  observer.observe(popup, { attributes: true, attributeFilter: ['class'] });

  // Клик по CTA
  popup.querySelector('[data-cta]')?.addEventListener('click', () => {
    gtag('event', 'popup_cta_click', { popup_id: id });
  });

  // Закрытие
  popup.querySelector('[data-close]')?.addEventListener('click', () => {
    gtag('event', 'popup_close', { popup_id: id });
    popups.close(id);
  });
});

Сроки

Реализация одного поп-апа с exit intent и таймером: 3–5 часов. Полный менеджер с 4–6 триггерами, антиспам-логикой и трекингом: 1–2 дня. Интеграция с ESP для захвата email прямо из поп-апа: ещё 2–4 часа.