Реалізація автоматичних маркетингових воронок на веб-сайті
Маркетингова воронка на веб-сайті — це не просто послідовність сторінок. Це керований потік: кожний відвідувач рухається по сценарію, який адаптується до його поведінки в реальному часі. Прийшов із контекстної реклами — бачить один набір пропозицій. Повернувся через тиждень — бачить інше. Поклав у кошик, але не купив — отримує тригерне письмо через 30 хвилин.
Архітектура воронки
Воронка складається з кількох шарів, які працюють разом:
- Слой збору даних — события на сайте (просмотры, клики, формы, прокрутка)
- Слой сегментации — класифікація користувачів за поведінкою та джерелом
- Слой контенту — динамічні блоки, які показують різний контент різним сегментам
- Слой нагрівання — email-цепочки, ретаргетинг, пуш-повідомлення
- Слой конверсії — фінальний CTA, адаптований до стадії
Технічно реалізується через комбінацію: аналітична платформа (GA4 / Mixpanel / власна БД), CRM або CDP, email-провайдер та рушій персоналізації контенту на фронтенді.
Трекінг подій як основа воронки
Без надійного трекінгу воронки не існує. Мінімальний набір подій:
// Уніфікований трекер подій воронки
const funnel = {
track(event, props = {}) {
const base = {
session_id: getSessionId(),
user_id: getUserId(), // анонімний fingerprint або авторизований ID
ts: Date.now(),
url: location.href,
referrer: document.referrer,
utm: getUtmParams(),
};
// GA4
window.gtag?.('event', event, { ...base, ...props });
// Власний ендпоінт
navigator.sendBeacon('/api/track', JSON.stringify({ event, ...base, ...props }));
},
};
// Використання
funnel.track('page_view', { page_type: 'product', product_id: '123' });
funnel.track('add_to_cart', { product_id: '123', price: 4900 });
funnel.track('checkout_start');
funnel.track('checkout_complete', { order_id: 'ORD-456', revenue: 4900 });
Зберігайте UTM-параметри в sessionStorage при першому вході та передавайте їх через усі события сесії — інакше вони будуть втрачені при переходах між сторінками.
Стадії воронки і логіка переходів
Типова B2B/SaaS воронка має 5 стадій: Awareness → Interest → Consideration → Intent → Purchase. Кожній стадії відповідає свій контент і свої тригери переходу.
// Визначення стадії користувача
type FunnelStage = 'awareness' | 'interest' | 'consideration' | 'intent' | 'purchase';
function getFunnelStage(profile: UserProfile): FunnelStage {
if (profile.orders > 0) return 'purchase';
if (profile.checkout_started) return 'intent';
if (profile.pages_viewed >= 5 || profile.time_on_site_min >= 10) return 'consideration';
if (profile.pages_viewed >= 2 || profile.return_visit) return 'interest';
return 'awareness';
}
// Профіль з localStorage + серверного API
async function getUserProfile(): Promise<UserProfile> {
const local = JSON.parse(localStorage.getItem('user_profile') ?? '{}');
const remote = await fetch('/api/user/profile').then(r => r.json()).catch(() => ({}));
return { ...local, ...remote };
}
Серверний профіль важливий для повернення користувачів — дані браузера не зберігаються між сесіями без авторизації.
Динамічний контент за стадією воронки
Компоненти фронтенду повинні рендерити різний контент залежно від стадії:
// React-компонент: Hero-блок з варіантами для кожної стадії
const heroContent: Record<FunnelStage, { headline: string; cta: string; cta_url: string }> = {
awareness: {
headline: 'Автоматизуйте рутину — зосередьтеся на зростанні',
cta: 'Дізнатися докладніше',
cta_url: '/how-it-works',
},
interest: {
headline: 'Як це працює для вашого бізнесу',
cta: 'Перегляньте кейси',
cta_url: '/cases',
},
consideration: {
headline: 'Порівняйте нас з конкурентами',
cta: 'Отримати порівняльний аналіз',
cta_url: '/compare',
},
intent: {
headline: 'Готові почати? Перші 14 днів безплатно',
cta: 'Почати безплатно',
cta_url: '/signup',
},
purchase: {
headline: 'Ласкаво просимо назад',
cta: 'Перейти в кабінет',
cta_url: '/dashboard',
},
};
function HeroSection() {
const [stage, setStage] = useState<FunnelStage>('awareness');
useEffect(() => {
getUserProfile().then(profile => setStage(getFunnelStage(profile)));
}, []);
const content = heroContent[stage];
return (
<section className="hero">
<h1>{content.headline}</h1>
<a href={content.cta_url} className="btn-primary"
onClick={() => funnel.track('cta_click', { stage, cta: content.cta })}>
{content.cta}
</a>
</section>
);
}
Автоматичні email-цепочки
Email-автоматизація — продовження воронки за межами сайту. Схема через API ESP (SendGrid, Postmark, Unisender):
// app/Services/FunnelEmailService.php
class FunnelEmailService
{
public function enrollUser(User $user, string $stage): void
{
match ($stage) {
'interest' => $this->sendSequence($user, 'interest_nurture', delayHours: 0),
'consideration' => $this->sendSequence($user, 'comparison_guide', delayHours: 1),
'intent' => $this->sendSequence($user, 'trial_push', delayHours: 0),
default => null,
};
}
private function sendSequence(User $user, string $sequence, int $delayHours): void
{
// Використовуємо черги Laravel — листи іть асинхронно
$emails = config("funnel.sequences.{$sequence}");
foreach ($emails as $index => $template) {
$totalDelay = $delayHours + $template['delay_hours'];
SendFunnelEmail::dispatch($user, $template)
->delay(now()->addHours($totalDelay));
}
}
}
Конфіг цепочки в config/funnel.php:
return [
'sequences' => [
'trial_push' => [
['template' => 'trial_welcome', 'delay_hours' => 0],
['template' => 'trial_day3_tips', 'delay_hours' => 72],
['template' => 'trial_day7_check', 'delay_hours' => 168],
['template' => 'trial_expiry', 'delay_hours' => 312],
],
],
];
Інтеграція з CRM
Переход користувача в стадію intent повинен створювати угоду в CRM без участі менеджера:
// Observer на моделі Lead
class LeadObserver
{
public function created(Lead $lead): void
{
if ($lead->funnel_stage === 'intent') {
CreateCrmDeal::dispatch($lead);
}
}
}
// Job створення угоди
class CreateCrmDeal implements ShouldQueue
{
public function handle(AmoCrmService $crm): void
{
$crm->createDeal([
'name' => "Ліде #{$this->lead->id} ({$this->lead->source})",
'pipeline' => 'main',
'stage' => 'new',
'contact' => [
'email' => $this->lead->email,
'phone' => $this->lead->phone,
],
'custom_fields' => [
'utm_source' => $this->lead->utm_source,
'utm_campaign' => $this->lead->utm_campaign,
'funnel_stage' => $this->lead->funnel_stage,
'pages_viewed' => $this->lead->pages_viewed,
],
]);
}
}
Аналітика воронки
Основна метрика воронки — коефіцієнт конверсії між стадіями. Користується в розрізі джерел та кампаній:
-- Конверсії між стадіями за останні 30 днів
WITH stage_counts AS (
SELECT
funnel_stage,
utm_source,
COUNT(DISTINCT user_id) AS users
FROM funnel_events
WHERE created_at >= NOW() - INTERVAL '30 days'
GROUP BY funnel_stage, utm_source
)
SELECT
utm_source,
MAX(CASE WHEN funnel_stage = 'awareness' THEN users END) AS awareness,
MAX(CASE WHEN funnel_stage = 'interest' THEN users END) AS interest,
MAX(CASE WHEN funnel_stage = 'consideration' THEN users END) AS consideration,
MAX(CASE WHEN funnel_stage = 'intent' THEN users END) AS intent,
MAX(CASE WHEN funnel_stage = 'purchase' THEN users END) AS purchase
FROM stage_counts
GROUP BY utm_source
ORDER BY awareness DESC;
Показує, де воронка «протікає» по кожному джерелу трафіку.
Графік
Базова воронка з трекінгом подій та динамічним Hero-блоком: 3-5 днів. Добавлення email-цепочок через ESP з чергами: ще 2-3 дні. Інтеграція з CRM (AmoCRM, Bitrix24) та автостворення угод: 2-4 дні залежно від API конкретної CRM. Аналітичний дашборд з візуалізацією конверсій: 1-2 дні.







