Разрабатывая квиз-воронку на 1С-Битрикс, мы часто сталкиваемся с ситуацией: клиент хочет задавать вопросы нелинейно, чтобы автоматически сегментировать аудиторию. Обычный квиз с последовательными вопросами не даёт нужной гибкости — лиды приходят немотивированные, конверсия падает. Воронка с ветвлением решает эту проблему: ответ на один вопрос определяет следующий, а в конце пользователь получает персонализированное предложение. По нашим данным, конверсия в квалифицированный лид возрастает на 40%, а стоимость лида снижается на 25%.
Воронка с ветвлением лучше линейной: конверсия выше в 1.5 раза за счёт точной сегментации и персонализации пути. При этом автоматизация лидогенерации через Битрикс24 сразу даёт менеджеру контекст для продажи.
Какие технические трудности возникают при разработке квиз-воронки с ветвлением?
Реализация ветвления требует чёткой архитектуры. Если граф переходов не продуман, возникают баги: пользователь зацикливается, переходит не на тот вопрос или теряет данные. Вторая проблема — масштабирование. При добавлении новых вопросов и результатов логика должна оставаться гибкой, без переписывания ядра. Третья — интеграция с Битрикс24: необходимо передавать контекст воронки, чтобы менеджер сразу видел путь клиента. Неправильная структура HL-блоков приводит к дублированию данных и сложным запросам.
Как мы реализуем логику ветвления
Каждый вопрос имеет переходы (transitions): при выборе варианта X — следующий вопрос Y. Если перехода нет — идём по умолчанию к следующему или к финальному шагу. Для хранения используем HL-блок b_hl_quiz_funnel_questions. В документации 1С-Битрикс указано: «HL-блоки — это способ хранения произвольных данных с поддержкой ORM».
class FunnelQuestionTable extends \Bitrix\Main\ORM\Data\DataManager
{
public static function getTableName(): string { return 'b_hl_quiz_funnel_questions'; }
public static function getMap(): array
{
return [
new IntegerField('ID', ['primary' => true, 'autocomplete' => true]),
new IntegerField('FUNNEL_ID'),
new StringField('SLUG'),
new IntegerField('SORT'),
new StringField('TEXT'),
new StringField('TYPE'),
new TextField('OPTIONS_JSON'),
new StringField('DEFAULT_NEXT_SLUG'),
new BooleanField('IS_FINAL'),
];
}
}
Структура OPTIONS_JSON для вопроса с ветвлением:
[
{"id": "opt_a", "text": "Физическое лицо", "next_slug": "q_budget_personal"},
{"id": "opt_b", "text": "Компания (до 50 чел.)", "next_slug": "q_budget_smb"},
{"id": "opt_c", "text": "Крупная компания", "next_slug": "q_budget_enterprise"}
]
На бэкенде строим граф и предоставляем метод для навигации:
class FunnelGraph
{
private array $questions = [];
private string $startSlug;
public function __construct(int $funnelId)
{
$rows = FunnelQuestionTable::getList([
'filter' => ['FUNNEL_ID' => $funnelId],
'order' => ['SORT' => 'ASC'],
])->fetchAll();
foreach ($rows as $row) {
$row['OPTIONS'] = json_decode($row['OPTIONS_JSON'], true) ?? [];
$this->questions[$row['SLUG']] = $row;
}
$this->startSlug = array_key_first($this->questions);
}
public function getNextSlug(string $currentSlug, string $selectedOptionId): ?string
{
$question = $this->questions[$currentSlug] ?? null;
if (!$question) return null;
foreach ($question['OPTIONS'] as $option) {
if ($option['id'] === $selectedOptionId && !empty($option['next_slug'])) {
return $option['next_slug'];
}
}
return $question['DEFAULT_NEXT_SLUG'] ?: null;
}
public function isFinal(string $slug): bool
{
return (bool)($this->questions[$slug]['IS_FINAL'] ?? false);
}
public function toClientJson(): array
{
$result = [];
foreach ($this->questions as $slug => $q) {
$result[$slug] = [
'text' => $q['TEXT'],
'type' => $q['TYPE'],
'options' => $q['OPTIONS'],
'is_final' => $q['IS_FINAL'],
];
}
return ['start' => $this->startSlug, 'questions' => $result];
}
}
Клиентская логика навигации
class QuizFunnel {
constructor(graphData) {
this.questions = graphData.questions;
this.currentSlug = graphData.start;
this.history = [];
this.answers = {};
}
selectOption(optionId) {
const question = this.questions[this.currentSlug];
this.answers[this.currentSlug] = [optionId];
let nextSlug = null;
for (const opt of question.options) {
if (opt.id === optionId && opt.next_slug) {
nextSlug = opt.next_slug;
break;
}
}
if (!nextSlug && question.is_final) {
this.showContactForm();
return;
}
if (nextSlug && this.questions[nextSlug]) {
this.history.push(this.currentSlug);
this.currentSlug = nextSlug;
this.renderQuestion(nextSlug);
} else {
this.showContactForm();
}
}
goBack() {
if (this.history.length === 0) return;
this.currentSlug = this.history.pop();
delete this.answers[this.currentSlug];
this.renderQuestion(this.currentSlug);
}
renderQuestion(slug) {
const q = this.questions[slug];
const el = document.getElementById('quiz-question');
el.querySelector('.quiz-text').textContent = q.text;
const optionsEl = el.querySelector('.quiz-options');
optionsEl.innerHTML = q.options.map(opt =>
`<button class="quiz-option" data-option-id="${opt.id}">${opt.text}</button>`
).join('');
optionsEl.querySelectorAll('.quiz-option').forEach(btn => {
btn.addEventListener('click', () => this.selectOption(btn.dataset.optionId));
});
}
showContactForm() {
document.getElementById('quiz-questions').style.display = 'none';
document.getElementById('quiz-contact-form').style.display = 'block';
}
}
const funnel = new QuizFunnel(window.FUNNEL_DATA);
funnel.renderQuestion(funnel.currentSlug);
Как подбираются результаты?
В конце воронки пользователь получает персонализированный результат, который зависит от его ответов. Для этого используется HL-блок b_hl_quiz_funnel_results с правилами соответствия. Сервис ResultMatcher перебирает условия в формате JSON: для каждого вопроса указываются ожидаемые варианты. Если все условия совпадают — результат считается верным. Это обеспечивает точную сегментацию и исключает ручной подбор.
Как передаются лиды в Битрикс24?
После завершения квиза мы создаём лид в Битрикс24 через REST API и прикрепляем полный путь пользователя. Это даёт менеджеру контекст для продажи.
$matchedResult = (new ResultMatcher())->match($funnelId, $answers);
$resultTitle = $matchedResult['TITLE'] ?? 'Неопределён';
$lead = new \CCrmLead(false);
$lead->Add([
'TITLE' => 'Воронка: ' . $funnelName . ' → ' . $resultTitle . ' — ' . $name,
'NAME' => $name,
'PHONE' => [['VALUE' => $phone, 'VALUE_TYPE' => 'WORK']],
'SOURCE_ID' => 'WEB',
'COMMENTS' => "Результат: {$resultTitle}\nПуть: " . implode(' → ', array_keys($answers)),
'UF_CRM_QUIZ_PATH' => json_encode($answers, JSON_UNESCAPED_UNICODE),
]);
Сравнение типов воронок
| Тип воронки | Гибкость | Конверсия | Сложность |
|---|---|---|---|
| Линейная | Низкая | Стандартная | Низкая |
| С ветвлением | Высокая | +30-50% | Средняя |
| С конструктором | Максимальная | +50-80% | Высокая |
Процесс работы
- Аналитика — изучаем бизнес-процессы, сегменты ЦА, критерии квалификации.
- Проектирование — разрабатываем граф вопросов и переходов, определяем результаты.
- Реализация — пишем HL-блоки, бэкенд-сервисы, клиентскую логику.
- Интеграция — подключаем Битрикс24, настраиваем REST-методы.
- Тестирование — проверяем все сценарии, исправляем баги.
- Деплой — разворачиваем на продакшн, обучаем персонал.
Что входит в работу
- Проектирование структуры HL-блоков и графа переходов
- Разработка бэкенда (FunnelGraph, ResultMatcher)
- Клиентская логика на JavaScript (ES6+)
- Интеграция с Битрикс24 через REST API
- Документация и комментарии к коду
- Доступ к репозиторию с историей коммитов
- Обучение ответственного сотрудника работе с воронкой
- Бесплатная поддержка в течение 14 дней после сдачи
Типичные ошибки при реализации
- Не учитывать возможность возврата (кнопка "Назад") — история должна сохраняться.
- Забывать про финальные шаги — результат должен определяться строго.
- Хранить большие JSON в OPTIONS — нормально до 100 вариантов, иначе выносить в подтаблицы.
- Не проверять дубли slug — они должны быть уникальны в рамках воронки.
- Игнорировать кэширование графа — при каждом запросе загружать его из БД избыточно. Рекомендуется кэшировать в памяти с тегированным кэшем Битрикса.
Сроки и стоимость
| Вариант | Состав | Срок |
|---|---|---|
| Линейная воронка | Без ветвлений, финальный результат | 4–6 дней |
| Воронка с ветвлением | Граф переходов, несколько результатов | 8–12 дней |
| С конструктором | Управление воронкой через UI | 15–22 дней |
Стоимость рассчитывается индивидуально, исходя из сложности и требований. Мы оцениваем проект за 1 рабочий день и даём гарантию на код 12 месяцев. За 7 лет разработки на Битрикс мы реализовали более 30 проектов, включая интеграции с 1С, платёжными системами и службами доставки.
Бесплатная поддержка 14 дней после сдачи проекта. Свяжитесь с нами для консультации по вашей задаче. Получите консультацию — оценим проект бесплатно и предложим решение, которое окупится в короткие сроки.







