Реалізація Lead Nurturing (прогрів лідів) на сайті

Наша компанія займається розробкою, підтримкою та обслуговуванням сайтів будь-якої складності. Від простих односторінкових сайтів до масштабних кластерних систем, побудованих на мікро сервісах. Досвід розробників підтверджено сертифікатами від вендорів.

Розробка та обслуговування будь-яких видів сайтів:

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

Це лише деякі з технічних типів сайтів, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Пропоновані послуги
Показано 1 з 1 послугУсі 2065 послуг
Реалізація Lead Nurturing (прогрів лідів) на сайті
Складна
~5 робочих днів
Часті питання

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

Етапи розробки

Останні роботи

  • 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

Реалізація lead nurturing на сайті

Lead nurturing — автоматизована серія комунікацій, яка «підігріває» ліда від першого дотику до покупки. Включає email-цепочки, триггерні листи, персоналізований контент та ремаркетинг на основі поведінки користувача.

Архітектура системи

Реєстрація/підписка → Визначення сегмента → Enroll у sequence →
→ Таймер + умови → Відправлення листа → Відстеження відкриттів та кліків →
→ Перехід в іншу sequence при виконанні цільової дії

Модель даних

Schema::create('nurture_sequences', function (Blueprint $table) {
    $table->id();
    $table->string('name');
    $table->string('trigger');            // 'trial_started', 'whitepaper_downloaded', 'pricing_page_3x'
    $table->json('conditions')->nullable(); // {"plan": "free", "source": "organic"}
    $table->boolean('is_active')->default(true);
    $table->timestamps();
});

Schema::create('nurture_emails', function (Blueprint $table) {
    $table->id();
    $table->foreignId('sequence_id')->constrained('nurture_sequences')->cascadeOnDelete();
    $table->integer('delay_hours');       // Відправити через N годин після попередника
    $table->string('subject');
    $table->string('template');           // Ім'я Blade-шаблону
    $table->json('conditions')->nullable(); // Додаткові умови відправлення
    $table->integer('order')->default(0);
});

Schema::create('nurture_enrollments', function (Blueprint $table) {
    $table->id();
    $table->foreignId('sequence_id')->constrained('nurture_sequences');
    $table->foreignId('user_id')->nullable()->constrained()->nullOnDelete();
    $table->string('email');
    $table->integer('current_step')->default(0);
    $table->enum('status', ['active', 'completed', 'exited', 'converted'])->default('active');
    $table->timestamp('next_email_at')->nullable();
    $table->timestamp('converted_at')->nullable();
    $table->timestamps();
});

Сервіс управління послідовностями

class NurtureService
{
    public function enroll(string $email, string $trigger, array $context = [], ?int $userId = null): void
    {
        // Знаходимо підходящі послідовності для триггеру
        $sequences = NurtureSequence::active()
            ->where('trigger', $trigger)
            ->get()
            ->filter(fn($seq) => $this->matchesConditions($seq->conditions, $context));

        foreach ($sequences as $sequence) {
            // Не записуємо якщо вже в активній послідовності
            $existing = NurtureEnrollment::where('sequence_id', $sequence->id)
                ->where('email', $email)
                ->whereIn('status', ['active'])
                ->exists();

            if ($existing) continue;

            $firstEmail = $sequence->emails()->orderBy('order')->first();

            NurtureEnrollment::create([
                'sequence_id'   => $sequence->id,
                'user_id'       => $userId,
                'email'         => $email,
                'current_step'  => 0,
                'next_email_at' => now()->addHours($firstEmail->delay_hours ?? 0),
            ]);
        }
    }

    public function exit(string $email, string $reason = 'manual'): void
    {
        NurtureEnrollment::where('email', $email)
            ->where('status', 'active')
            ->update(['status' => 'exited']);
    }

    public function markConverted(string $email): void
    {
        NurtureEnrollment::where('email', $email)
            ->where('status', 'active')
            ->update(['status' => 'converted', 'converted_at' => now()]);
    }

    private function matchesConditions(?array $conditions, array $context): bool
    {
        if (!$conditions) return true;
        foreach ($conditions as $key => $value) {
            if (($context[$key] ?? null) != $value) return false;
        }
        return true;
    }
}

Job для відправлення листів за розкладом

// Запускається кожні 15 хвилин через Scheduler
class ProcessNurtureEmails implements ShouldQueue
{
    public function handle(): void
    {
        $enrollments = NurtureEnrollment::where('status', 'active')
            ->where('next_email_at', '<=', now())
            ->with(['sequence.emails'])
            ->get();

        foreach ($enrollments as $enrollment) {
            $emails = $enrollment->sequence->emails->sortBy('order');
            $currentEmail = $emails->get($enrollment->current_step);

            if (!$currentEmail) {
                $enrollment->update(['status' => 'completed']);
                continue;
            }

            // Перевіряємо додаткові умови кроку
            if ($currentEmail->conditions && !$this->checkStepConditions($enrollment, $currentEmail->conditions)) {
                // Пропускаємо крок
                $this->advanceToNextStep($enrollment, $emails);
                continue;
            }

            // Перевіряємо чи не відписався користувач
            if (EmailUnsubscribe::where('email', $enrollment->email)->exists()) {
                $enrollment->update(['status' => 'exited']);
                continue;
            }

            // Відправляємо лист
            Mail::to($enrollment->email)->queue(
                new NurtureEmail($enrollment, $currentEmail)
            );

            $this->advanceToNextStep($enrollment, $emails);
        }
    }

    private function advanceToNextStep(NurtureEnrollment $enrollment, Collection $emails): void
    {
        $nextStep = $enrollment->current_step + 1;
        $nextEmail = $emails->get($nextStep);

        if ($nextEmail) {
            $enrollment->update([
                'current_step'  => $nextStep,
                'next_email_at' => now()->addHours($nextEmail->delay_hours),
            ]);
        } else {
            $enrollment->update(['status' => 'completed', 'current_step' => $nextStep]);
        }
    }
}

Приклад послідовності для trial

День 0: "Добро пожаловати! Ось як почати" → Онбординг
День 1: "3 функції, що економлять час" → Цінність
День 3: "Відео: як інші компанії користуються нами" → Соціальний доказ
День 5: "Ти використав функцію X?" → Engagement-чек (відправляємо тільки якщо не використав)
День 7: "Твій trial закінчується через 7 днів" → Urgency
День 10: "Спеціальна пропозиція для тебе" → Офер
День 14: "Що тобі сподобалося/не сподобалося?" → CSAT + збереження

Триггери для виходу з послідовності

// Observer за покупками
class OrderObserver
{
    public function created(Order $order): void
    {
        // При покупці — виходимо з усіх nurture-послідовностей
        app(NurtureService::class)->markConverted($order->user->email);
    }
}

// При підключенні до CRM — теж сповіщаємо систему
class HandleCrmOpportunityCreated
{
    public function handle(): void
    {
        app(NurtureService::class)->exit($this->email, reason: 'crm_opportunity');
    }
}

Аналітика послідовностей

-- Конверсія за послідовностями
SELECT
  s.name,
  COUNT(e.id) AS enrolled,
  COUNT(e.id) FILTER (WHERE e.status = 'converted') AS converted,
  ROUND(100.0 * COUNT(e.id) FILTER (WHERE e.status = 'converted') / NULLIF(COUNT(e.id), 0), 1) AS conversion_rate,
  ROUND(AVG(EXTRACT(EPOCH FROM (e.converted_at - e.created_at)) / 3600)) AS avg_hours_to_convert
FROM nurture_sequences s
LEFT JOIN nurture_enrollments e ON e.sequence_id = s.id
GROUP BY s.id, s.name
ORDER BY conversion_rate DESC;

Тривалість

Повна система lead nurturing з послідовностями, умовами та аналітикою: 10–14 робочих днів.