Интеграция квиз-формы с email-рассылкой 1С-Битрикс

Наша компания занимается разработкой, поддержкой и обслуживанием решений на Битрикс и Битрикс24 любой сложности. От простых одностраничных сайтов до сложных интернет магазинов, CRM систем с интеграцией 1С и телефонии. Опыт разработчиков подтвержден сертификатами от вендора.
Предлагаемые услуги
Показано 1 из 1 услугВсе 1626 услуг
Интеграция квиз-формы с email-рассылкой 1С-Битрикс
Средняя
~1-2 недели
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1165
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    811
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Разработка на базе Битрикс, Битрикс24, 1С для компании Development of an Online Appointment Booking Widget for a Medical Center
    563
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Разработка на базе 1С Предприятие для компании МИРСАНБЕЛ
    743
  • image_crm_dolbimby_434_0.webp
    Разработка сайта на CRM Битрикс24 для компании DOLBIMBY
    655
  • image_crm_technotorgcomplex_453_0.webp
    Разработка на базе Битрикс24 для компании ТЕХНОТОРГКОМПЛЕКС
    976

Интеграция квиз-формы с email-рассылкой 1С-Битрикс

Email-маркетинг, построенный на результатах квиза, значительно эффективнее стандартных массовых рассылок — потому что сегментация основана на реальных предпочтениях пользователя, выраженных в его ответах. Клиент ответил «Интересует ремонт ванной» — попадает в сегмент ванных комнат. Ответил «Бюджет от 500 тысяч» — получает письма про премиум-материалы. В 1С-Битрикс для этого есть модуль subscribe (рассылки), а с версии Битрикс 20+ — встроенный Email-маркетинг. Задача — подключить к этой системе результаты квиза.

Модули рассылок в Битрикс

Модуль subscribe — классический, доступен во всех редакциях. Таблицы: b_subscribe, b_subscribe_subscr, b_subscribe_rubric. Работает через компоненты bitrix:subscribe.form, bitrix:subscribe.sender.

Email-маркетинг (модуль sender) — более современный, поддерживает сегменты, автоматизации, шаблоны. Таблицы: b_sender_contact, b_sender_mailing_chain, b_sender_mailing_chain_segment. Требует редакцию «Малый бизнес» и выше.

Для новых проектов рекомендую sender — у него API богаче.

Сбор данных квиза и подписка через модуль sender

При завершении квиза нужно:

  1. Добавить подписчика в модуль sender
  2. Добавить его в нужный сегмент (или несколько) на основе ответов
  3. Запустить автоматизацию (приветственная серия писем)
namespace Local\Quiz;

use Bitrix\Sender\ContactTable;
use Bitrix\Sender\SegmentTable;

class EmailSubscribeHandler
{
    /**
     * @param array $quizData ['email', 'name', 'answers' => [...], 'result' => '...']
     */
    public function subscribe(array $quizData): int
    {
        $email = filter_var($quizData['email'] ?? '', FILTER_VALIDATE_EMAIL);
        if (!$email) {
            throw new \InvalidArgumentException('Invalid email: ' . htmlspecialchars($quizData['email'] ?? ''));
        }

        // Добавляем или обновляем контакт в sender
        $contactId = $this->upsertContact($email, $quizData['name'] ?? '');

        // Определяем сегменты по ответам квиза
        $segments = $this->resolveSegments($quizData['answers'] ?? [], $quizData['result'] ?? '');

        foreach ($segments as $segmentId) {
            $this->addContactToSegment($contactId, $segmentId);
        }

        // Запускаем welcome-цепочку
        $chainId = $this->getWelcomeChainByResult($quizData['result'] ?? '');
        if ($chainId) {
            $this->triggerChain($contactId, $chainId);
        }

        return $contactId;
    }

    private function upsertContact(string $email, string $name): int
    {
        // Ищем существующий контакт
        $existing = ContactTable::getList([
            'filter' => ['=EMAIL' => $email],
            'select' => ['ID'],
            'limit'  => 1,
        ])->fetch();

        if ($existing) {
            // Обновляем имя если изменилось
            ContactTable::update($existing['ID'], [
                'NAME' => $name ?: null,
            ]);
            return (int)$existing['ID'];
        }

        // Создаём нового
        $result = ContactTable::add([
            'EMAIL'      => $email,
            'NAME'       => $name,
            'TYPE_ID'    => 'EMAIL',
            'CONFIRMED'  => 'N', // требуется double opt-in
        ]);

        if (!$result->isSuccess()) {
            throw new \RuntimeException('Failed to create contact: ' . implode(', ', $result->getErrorMessages()));
        }

        // Отправляем double opt-in письмо
        $this->sendConfirmationEmail($result->getId(), $email);

        return $result->getId();
    }

    private function resolveSegments(array $answers, string $result): array
    {
        $segmentIds = [];

        // Базовый сегмент: все прошедшие квиз
        $segmentIds[] = $this->getOrCreateSegment('quiz_all', 'Все прошедшие квиз');

        // Сегментация по результату квиза
        $resultSegmentMap = [
            'Стандартный пакет' => 'quiz_result_standard',
            'Премиум пакет'     => 'quiz_result_premium',
            'Эконом пакет'      => 'quiz_result_economy',
        ];

        if (isset($resultSegmentMap[$result])) {
            $segmentIds[] = $this->getOrCreateSegment(
                $resultSegmentMap[$result],
                'Квиз: ' . $result
            );
        }

        // Сегментация по конкретным ответам
        foreach ($answers as $answer) {
            $tag = $this->answerToSegmentTag($answer['question'] ?? '', $answer['answer'] ?? '');
            if ($tag) {
                $segmentIds[] = $this->getOrCreateSegment($tag['code'], $tag['name']);
            }
        }

        return array_unique(array_filter($segmentIds));
    }

    private function answerToSegmentTag(string $question, string $answer): ?array
    {
        $mapping = [
            'Тип помещения' => [
                'Квартира'    => ['code' => 'room_apartment', 'name' => 'Тип: Квартира'],
                'Частный дом' => ['code' => 'room_house',     'name' => 'Тип: Частный дом'],
                'Офис'        => ['code' => 'room_office',    'name' => 'Тип: Офис'],
            ],
            'Бюджет' => [
                'До 50 000 руб.'        => ['code' => 'budget_low',    'name' => 'Бюджет: эконом'],
                '50 000 – 100 000 руб.' => ['code' => 'budget_mid',    'name' => 'Бюджет: средний'],
                'От 100 000 руб.'       => ['code' => 'budget_high',   'name' => 'Бюджет: высокий'],
            ],
        ];

        return $mapping[$question][$answer] ?? null;
    }

    private function getOrCreateSegment(string $code, string $name): int
    {
        $existing = SegmentTable::getList([
            'filter' => ['=CODE' => $code],
            'select' => ['ID'],
            'limit'  => 1,
        ])->fetch();

        if ($existing) {
            return (int)$existing['ID'];
        }

        $result = SegmentTable::add([
            'CODE'   => $code,
            'NAME'   => $name,
            'ACTIVE' => 'Y',
        ]);

        return $result->getId();
    }

    private function addContactToSegment(int $contactId, int $segmentId): void
    {
        \Bitrix\Sender\ContactSegmentTable::add([
            'CONTACT_ID' => $contactId,
            'SEGMENT_ID' => $segmentId,
        ]);
    }
}

Автоматическая цепочка писем по результату квиза

В Email-маркетинге Битрикс создаём цепочки (Automation):

  • Модуль → Маркетинг → Автоматизация → Создать цепочку

Триггер — добавление контакта в сегмент. Через API запускаем принудительно:

private function triggerChain(int $contactId, int $chainId): void
{
    // Добавляем контакт в рассылочную цепочку
    \Bitrix\Sender\MailingChainTable::addContact($chainId, $contactId);
}

private function getWelcomeChainByResult(string $result): ?int
{
    // Маппинг результатов квиза → ID цепочек в Битрикс sender
    $chainMap = [
        'Стандартный пакет' => 5,
        'Премиум пакет'     => 6,
        'Эконом пакет'      => 7,
    ];

    return $chainMap[$result] ?? null; // null — используем цепочку по умолчанию
}

Double opt-in: обязательная часть

По российскому законодательству (ФЗ-38 «О рекламе») и GDPR-совместимым практикам нужно подтверждение email перед отправкой рассылки.

private function sendConfirmationEmail(int $contactId, string $email): void
{
    // Генерируем токен подтверждения
    $token = bin2hex(random_bytes(32));

    // Сохраняем токен в Highload-блоке или таблице
    $this->saveConfirmToken($contactId, $token);

    // Формируем ссылку подтверждения
    $confirmUrl = 'https://example.com/subscribe/confirm/?token=' . $token;

    // Отправляем через модуль main (событие почты)
    \CEvent::Send('QUIZ_SUBSCRIBE_CONFIRM', SITE_ID, [
        'EMAIL'        => $email,
        'CONFIRM_URL'  => $confirmUrl,
    ]);
}

Страница подтверждения: /subscribe/confirm/?token=... — активирует контакт (CONFIRMED = Y) и редиректит на страницу благодарности.

Интеграция с классическим модулем subscribe

Для версий Битрикс без sender-модуля — используем b_subscribe_subscr:

// Подписка через старый модуль
\CModule::IncludeModule('subscribe');

$subscriber = new \CSubscribe();
$subscribeId = $subscriber->Add([
    'FORMAT'   => 'html',
    'EMAIL'    => $email,
    'ACTIVE'   => 'Y',
    'CONFIRMED' => 'N',
]);

// Подписываем на рубрики, соответствующие сегментам квиза
$rubricIds = $this->resolveRubricIds($quizAnswers);
foreach ($rubricIds as $rubricId) {
    $subscriber->Subscribe($subscribeId, $rubricId, SITE_ID);
}

Состав работ

  • Выбор модуля рассылки (sender vs subscribe) исходя из редакции Битрикс
  • Webhook-обработчик для квиз-сервиса или интеграция кастомного квиза
  • Логика маппинга ответов → сегменты/рубрики
  • Double opt-in: шаблон письма, страница подтверждения
  • Шаблоны приветственных писем под каждый результат квиза
  • Создание автоматизаций/цепочек в Email-маркетинге

Сроки: базовая интеграция (подписка + один сегмент) — 3–5 дней. Полная система с множественной сегментацией и цепочками — 2–3 недели.