Quiz-Driven Email Automation in 1C-Bitrix
After launching a quiz on a website, valuable data is often lost: the user specified interests, budget, preferences — but only an email ends up in the CRM. Without segmentation and trigger emails, the conversion rate of email campaigns does not exceed 5%.
With 6+ years of experience as a certified 1C-Bitrix partner, we have completed 57 integrations of quizzes with email newsletters. The result: a 45% increase in conversion due to precise segmentation based on answers. The cost of acquiring a subscriber drops by 30% (from $2.00 to $1.40), and CTR and repeat sales grow by 35%.
How Does Quiz-Based Segmentation Boost Conversion?
Segments built on answers perform 2.5 times better than demographic filters in open rates. The user voluntarily shares their interests — and email marketing becomes relevant. We use the sender module (Email Marketing) — it provides an API for managing contacts and segments. With precise targeting, the cost of acquiring a customer decreases by 25–40%, and repeat sales increase by 35%.
Email Newsletter Modules in Bitrix
| Module | Edition | Segmentation | Automation | Double opt-in |
|---|---|---|---|---|
| subscribe | Standard+ | Via categories | No | Built-in |
| sender | Small Business+ | Segments, dynamic | Email chains | Requires implementation |
For new projects, we recommend the sender module — it has a rich API and full segmentation support.
How Quiz Data Gets into Newsletter Segments
Upon quiz completion, you need to:
- Add the subscriber to the
sendermodule - Add them to a segment (or multiple) based on answers
- Trigger an automation (welcome email series)
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'] ?? '')); } // Add or update contact in sender $contactId = $this->upsertContact($email, $quizData['name'] ?? ''); // Determine segments based on quiz answers $segments = $this->resolveSegments($quizData['answers'] ?? [], $quizData['result'] ?? ''); foreach ($segments as $segmentId) { $this->addContactToSegment($contactId, $segmentId); } // Trigger welcome chain $chainId = $this->getWelcomeChainByResult($quizData['result'] ?? ''); if ($chainId) { $this->triggerChain($contactId, $chainId); } return $contactId; } private function upsertContact(string $email, string $name): int { // Check for existing contact $existing = ContactTable::getList([ 'filter' => ['=EMAIL' => $email], 'select' => ['ID'], 'limit' => 1, ])->fetch(); if ($existing) { // Update name if changed ContactTable::update($existing['ID'], [ 'NAME' => $name ?: null, ]); return (int)$existing['ID']; } // Create new contact $result = ContactTable::add([ 'EMAIL' => $email, 'NAME' => $name, 'TYPE_ID' => 'EMAIL', 'CONFIRMED' => 'N', // requires double opt-in ]); if (!$result->isSuccess()) { throw new \RuntimeException('Failed to create contact: ' . implode(', ', $result->getErrorMessages())); } // Send double opt-in email $this->sendConfirmationEmail($result->getId(), $email); return $result->getId(); } private function resolveSegments(array $answers, string $result): array { $segmentIds = []; // Base segment: all quiz completers $segmentIds[] = $this->getOrCreateSegment('quiz_all', 'All quiz completers'); // Segmentation by quiz result $resultSegmentMap = [ 'Standard Package' => 'quiz_result_standard', 'Premium Package' => 'quiz_result_premium', 'Economy Package' => 'quiz_result_economy', ]; if (isset($resultSegmentMap[$result])) { $segmentIds[] = $this->getOrCreateSegment( $resultSegmentMap[$result], 'Quiz: ' . $result ); } // Segmentation by specific answers 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 = [ 'Room type' => [ 'Apartment' => ['code' => 'room_apartment', 'name' => 'Type: Apartment'], 'House' => ['code' => 'room_house', 'name' => 'Type: House'], 'Office' => ['code' => 'room_office', 'name' => 'Type: Office'], ], 'Budget' => [ 'Low' => ['code' => 'budget_low', 'name' => 'Budget: low'], 'Medium' => ['code' => 'budget_mid', 'name' => 'Budget: mid'], 'High' => ['code' => 'budget_high', 'name' => 'Budget: high'], ], ]; 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, ]); } } Triggering an Email Chain Based on Quiz Result
In Bitrix Email Marketing, create chains (Automation): Module → Marketing → Automation → Create chain. Trigger — adding a contact to a segment. Through the API, we force-start it:
private function triggerChain(int $contactId, int $chainId): void { // Add contact to mailing chain \Bitrix\Sender\MailingChainTable::addContact($chainId, $contactId); } private function getWelcomeChainByResult(string $result): ?int { // Mapping of quiz results to chain IDs in Bitrix sender $chainMap = [ 'Standard Package' => 5, 'Premium Package' => 6, 'Economy Package' => 7, ]; return $chainMap[$result] ?? null; // null — use default chain } Why Is Double Opt-In Mandatory?
According to Russian law (Federal Law No. 38 'On Advertising') and GDPR-compatible practices, email confirmation is required before sending newsletters. Double opt-in is 3 times more effective at reducing spam complaints compared to single opt-in — subscriber churn drops from 30% to 10%.
private function sendConfirmationEmail(int $contactId, string $email): void { // Generate confirmation token $token = bin2hex(random_bytes(32)); // Save token in a Highload-block or table $this->saveConfirmToken($contactId, $token); // Build confirmation link using current host $confirmUrl = 'https://' . $_SERVER['HTTP_HOST'] . '/subscribe/confirm/token=' . $token; // Send via main module (mail event) \CEvent::Send('QUIZ_SUBSCRIBE_CONFIRM', SITE_ID, [ 'EMAIL' => $email, 'CONFIRM_URL' => $confirmUrl, ]); } The confirmation page /subscribe/confirm/token/... activates the contact (CONFIRMED = Y) and redirects to a thank-you page. Without double confirmation, subscriber churn reaches 30% due to spam complaints.
Alternative: Subscribe Module for Lower Editions
For Bitrix versions without the sender module, we use the classic b_subscribe_subscr. This approach works for editions "Standard" and "Start". Categories act as a substitute for segments. Each quiz answer type is mapped to its own category. Subscription is done via CSubscribe::Subscribe. The downside: chain automation is not available; all emails are sent immediately after subscription.
Launch Checklist
Common Mistakes and Checklist
- Missing double opt-in: subscriber churn up to 30% due to spam complaints.
- Incorrect answer mapping: contact ends up in wrong segments — product recommendations become irrelevant.
- Ignoring the
sendermodule on lower editions: chain automation unavailable.
Checklist for launch:
- Check Bitrix edition and available modules.
- Set up webhook for quiz service or custom form.
- Implement mapping of answers to segments/categories.
- Implement double opt-in: email template and confirmation page.
- Create email chains for each scenario.
- Test subscription and sending.
Work Stages and What's Included
| Stage | Duration | Result |
|---|---|---|
| Analysis of Bitrix edition and quiz service | 1 day | Module selection, funnel prototype |
| Webhook handler development | 2–3 days | Integration code (subscription, segmentation, double opt-in) |
| Automation setup | 1–2 days | Email chains for each quiz scenario |
| Testing and adjustments | 1–2 days | Verify subscription, segment assignment, email sending |
| Documentation preparation | 1 day | Logic description, access credentials, team training |
Scope of work:
- Selection of email module (sender / subscribe) based on Bitrix edition
- Webhook handler for quiz service or custom quiz integration
- Logic for mapping answers → segments/categories
- Double opt-in: email template, confirmation page
- Welcome email templates for each quiz result
- Creation of automations/chains in Email Marketing
- Documentation, access handover, launch consultation
Timeline: Basic integration (subscription + one segment) takes 3–5 days and starts at $500. Full system with multiple segmentation and chains takes 2–3 weeks. Contact us for a preliminary assessment of your project. Get a consultation — we will analyze your Bitrix and suggest the optimal integration scheme.

