Реализация автоматических маркетинговых воронок на сайте
Маркетинговая воронка на сайте — это не просто последовательность страниц. Это управляемый поток: каждый посетитель двигается по сценарию, который адаптируется к его поведению в реальном времени. Пришёл с контекстной рекламы — видит один набор офферов. Вернулся повторно через неделю — видит другой. Положил в корзину, но не купил — получает триггерное письмо через 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 дня.







