Реалізація тригерних 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 години.