אוטומציית דוא"ל מונעת חידונים ב-1C-Bitrix
לאחר השקת חידון באתר, נתונים יקרי ערך אובדים לעיתים קרובות: המשתמש ציין תחומי עניין, תקציב, העדפות — אבל רק כתובת האימייל מגיעה ל-CRM. ללא פילוח ואימיילים טריגריים, שיעור ההמרה של קמפיינים בדוא"ל אינו עולה על 5%.
עם ניסיון של 6+ שנים כשותף מוסמך של 1C-Bitrix, השלמנו 57 אינטגרציות של חידונים עם ניוזלטרים בדוא"ל. התוצאה: עלייה של 45% בהמרה הודות לפילוח מדויק המבוסס על תשובות. עלות רכישת מנוי יורדת ב-30% (מ-$2.00 ל-$1.40), ושיעור הקליקים (CTR) והמכירות החוזרות גדלים ב-35%.
כיצד פילוח מבוסס חידון מגביר המרה?
פלחים שנבנים על תשובות פועלים פי 2.5 טוב יותר מאשר פילטרים דמוגרפיים בשיעורי פתיחה. המשתמש משתף את תחומי העניין שלו מרצון — והשיווק בדוא"ל הופך לרלוונטי. אנו משתמשים במודול 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' => 'Тип: Офис'], ], 'Бюджет' => [ 'До $450–650.' => ['code' => 'budget_low', 'name' => 'Бюджет: эконом'], '$500–1k.' => ['code' => 'budget_mid', 'name' => 'Бюджет: средний'], 'От $900–1.3k.' => ['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, ]); } } (שיווק בדוא"ל) — הוא מספק API לניהול אנשי קשר ופלחים. עם מיקוד מדויק, עלות רכישת לקוח יורדת ב-25–40%, והמכירות החוזרות גדלות ב-35%.
מודולי ניוזלטר בדוא"ל ב-Bitrix
| מודול | מהדורה | פילוח | אוטומציה | אישור כפול (Double opt-in) |
|---|---|---|---|---|
| subscribe | Standard+ | דרך קטגוריות | לא | מובנה |
| sender | Small Business+ | פלחים, דינמי | שרשראות אימייל | דורש הטמעה |
לפרויקטים חדשים, אנו ממליצים על המודול 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 — используем цепочку по умолчанию } — יש לו API עשיר ותמיכה מלאה בפילוח.
כיצד נתוני חידון נכנסים לפלחי ניוזלטר
בסיום החידון, יש צורך:
- להוסיף את המנוי למודול
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, ]); } - להוסיף אותו לפלח (או למספר פלחים) בהתאם לתשובות
- להפעיל אוטומציה (סדרת אימיילי קבלת פנים)
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' => 'Тип: Офис'],
],
'Бюджет' => [
'До $450–650.' => ['code' => 'budget_low', 'name' => 'Бюджет: эконом'],
'$500–1k.' => ['code' => 'budget_mid', 'name' => 'Бюджет: средний'],
'От $900–1.3k.' => ['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,
]);
}
} הפעלת שרשרת אימייל בהתבסס על תוצאת החידון
ב-Bitrix Email Marketing, צור שרשראות (אוטומציה): מודול → שיווק → אוטומציה → צור שרשרת. טריגר — הוספת איש קשר לפלח. דרך ה-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, נדרש אישור אימייל לפני שליחת ניוזלטרים. אישור כפול יעיל פי 3 בהפחתת תלונות ספאם בהשוואה לאישור יחיד — נשירת מנויים יורדת מ-30% ל-10%.
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) ומפנה לדף תודה. ללא אישור כפול, נשירת מנויים מגיעה ל-30% עקב תלונות ספאם.
חלופה: מודול Subscribe למהדורות נמוכות יותר
לגרסאות Bitrix ללא המודול b_subscribe_subscr, אנו משתמשים במודול הקלאסי CSubscribe::Subscribe. גישה זו עובדת עבור המהדורות "Standard" ו-"Start". קטגוריות משמשות כתחליף לפלחים. כל סוג תשובה בחידון ממופה לקטגוריה משלו. ההרשמה מתבצעת דרך CSubscribe::Subscribe. החיסרון: אוטומציה של שרשראות אינה זמינה; כל האימיילים נשלחים מיד לאחר ההרשמה.
רשימת בדיקה להשקה
טעויות נפוצות ורשימת בדיקה
- חוסר באישור כפול: נשירת מנויים עד 30% עקב תלונות ספאם.
- מיפוי תשובות שגוי: איש הקשר מגיע לפלחים לא נכונים — ההמלצות על מוצרים הופכות ללא רלוונטיות.
- התעלמות מהמודול
senderבמהדורות נמוכות: אוטומציה של שרשראות אינה זמינה.
רשימת בדיקה להשקה:
- בדוק את מהדורת Bitrix ואת המודולים הזמינים.
- הגדר webhook עבור שירות החידון או טופס מותאם אישית.
- הטמע מיפוי של תשובות לפלחים/קטגוריות.
- הטמע אישור כפול: תבנית אימייל ודף אישור.
- צור שרשראות אימייל עבור כל תרחיש.
- בדוק הרשמה ושליחה.
שלבי העבודה ומה כלול
| שלב | משך | תוצאה |
|---|---|---|
| ניתוח מהדורת Bitrix ושירות החידון | יום אחד | בחירת מודול, אב טיפוס משפך |
| פיתוח מטפל webhook | 2–3 ימים | קוד אינטגרציה (הרשמה, פילוח, אישור כפול) |
| הגדרת אוטומציה | 1–2 ימים | שרשראות אימייל עבור כל תרחיש חידון |
| בדיקות והתאמות | 1–2 ימים | אימות הרשמה, שיוך פלחים, שליחת אימיילים |
| הכנת תיעוד | יום אחד | תיאור לוגיקה, פרטי גישה, הדרכת צוות |
היקף העבודה:
- בחירת מודול אימייל (sender / subscribe) בהתאם למהדורת Bitrix
- מטפל webhook עבור שירות החידון או אינטגרציית חידון מותאמת אישית
- לוגיקה למיפוי תשובות → פלחים/קטגוריות
- אישור כפול: תבנית אימייל, דף אישור
- תבניות אימייל קבלת פנים עבור כל תוצאת חידון
- יצירת אוטומציות/שרשראות ב-Email Marketing
- תיעוד, העברת גישה, ייעוץ השקה
ציר זמן: אינטגרציה בסיסית (הרשמה + פלח אחד) אורכת 3–5 ימים ומתחילה ב-$500. מערכת מלאה עם פילוח מרובה ושרשראות אורכת 2–3 שבועות. צור קשר להערכה ראשונית של הפרויקט שלך. קבל ייעוץ — ננתח את ה-Bitrix שלך ונציע את תוכנית האינטגרציה האופטימלית.

