Інтеграція квіз-форми з 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
При завершенні квізу потрібно:
- Додати підписника в модуль
sender - Додати його в потрібний сегмент (або кілька) на основі відповідей
- Запустити автоматизацію (вітальна серія листів)
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: обов'язкова частина
За українським законодавством та 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 тижні.







