При запуске нового продукта или после изменений в сервисе часто возникает одна и та же картина: менеджеры собирают фидбэк вручную через почту или мессенджеры, данные теряются, аналитика запаздывает. Недавно к нам пришёл клиент из интернет-магазина электроники — их Net Promoter Score был неизвестен, так как опросы проводились раз в полгода по email с откликом 3%. Мы поставили всплывающий опросник на странице заказа, и уже через месяц получили 1200 ответов с детальной картиной. За месяц NPS вырос с 20 до 45 — это позволило оперативно исправить проблемные зоны в сервисе доставки. Опросник на сайте — единственный способ получать структурированные данные без потерь. В Битриксе нет готового модуля для опросов приличного уровня — встроенный iblock можно использовать для хранения, но логику опроса приходится писать с нуля.
Как реализовать опросник на 1С-Битрикс?
Собираем архитектуру на HL-блоках — это быстрее и гибче, чем инфоблоки. Типовые сценарии:
- NPS (Net Promoter Score) — шкала 0–10 с комментарием.
- CSAT (Customer Satisfaction) — 1–2 вопроса после конкретного действия.
- Полноценный опросник — несколько страниц с разными типами вопросов, ветвление, триггеры показа.
Структура данных через HL-блоки:
class SurveyTable extends \Bitrix\Main\ORM\Data\DataManager { public static function getTableName(): string { return 'b_hl_surveys'; } public static function getMap(): array { return [ new IntegerField('ID', ['primary' => true, 'autocomplete' => true]), new StringField('TITLE'), new StringField('SLUG'), new StringField('TYPE'), // nps | csat | full new TextField('QUESTIONS_JSON'), // Конфигурация вопросов new StringField('TRIGGER'), // page_load | exit_intent | scroll_50 | after_order new IntegerField('SHOW_DELAY'), // Задержка показа в секундах new BooleanField('IS_ACTIVE', ['values' => [false, true]]), new DatetimeField('DATE_FROM'), new DatetimeField('DATE_TO'), ]; } } class SurveyResponseTable extends \Bitrix\Main\ORM\Data\DataManager { public static function getTableName(): string { return 'b_hl_survey_responses'; } public static function getMap(): array { return [ new IntegerField('ID', ['primary' => true, 'autocomplete' => true]), new IntegerField('SURVEY_ID'), new IntegerField('USER_ID'), // NULL — анонимный new StringField('SESSION_ID'), new StringField('USER_IP'), new TextField('ANSWERS_JSON'), // {question_id: answer} new IntegerField('COMPLETION_SEC'), // Время прохождения new DatetimeField('CREATED_AT'), ]; } } Какие типы опросников стоит внедрить?
Выбор зависит от бизнес-задачи. Сравним варианты:
| Тип | Суть | Вопросов | Триггер | Время реализации |
|---|---|---|---|---|
| NPS | Готовность рекомендовать | 1–2 | Всплытие по задержке / exit | 2–3 дня |
| CSAT | Оценка конкретной точки | 1–3 | После заказа / обращения | 2–4 дня |
| Полноценный | Исследование аудитории | 5–20 | Комбинированные | 8–14 дней |
NPS-опрос — самый простой и дешёвый способ начать собирать обратную связь. Для него достаточно одного компонента с виджетом.
NPS-опросник: простой случай
Типовая реализация — одна страница, одно действие. Код компонента:
// /local/components/local/survey.nps/template.php ?> <div class="nps-widget" id="nps-widget" style="display:none;"> <div class="nps-container"> <button class="nps-close" onclick="NPS.dismiss()">×</button> <p class="nps-question"> Насколько вы готовы рекомендовать нас своим знакомым? </p> <div class="nps-scale"> <?php for ($i = 0; $i <= 10; $i++): ?> <button class="nps-score" data-score="<?= $i ?>"><?= $i ?></button> <?php endfor; ?> </div> <div class="nps-labels"> <span>Точно не буду рекомендовать</span> <span>Обязательно порекомендую</span> </div> <div class="nps-comment" style="display:none;"> <textarea placeholder="Расскажите подробнее..." id="nps-comment-text"></textarea> <button onclick="NPS.submit()">Отправить</button> </div> </div> </div> <script> const NPS = { surveyId: <?= (int)$arResult['SURVEY']['ID'] ?>, selectedScore: null, init() { setTimeout(() => { if (!this.wasShown()) { document.getElementById('nps-widget').style.display = 'flex'; this.markShown(); } }, <?= (int)$arResult['SURVEY']['SHOW_DELAY'] * 1000 ?>); document.querySelectorAll('.nps-score').forEach(btn => { btn.addEventListener('click', e => { this.selectScore(parseInt(e.target.dataset.score)); }); }); }, selectScore(score) { this.selectedScore = score; document.querySelectorAll('.nps-score').forEach(b => b.classList.remove('selected')); document.querySelector(`[data-score="${score}"]`).classList.add('selected'); document.querySelector('.nps-comment').style.display = 'block'; }, async submit() { if (this.selectedScore === null) return; await fetch('/local/ajax/survey_submit.php', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({ survey_id: this.surveyId, answers: { nps_score: this.selectedScore, comment: document.getElementById('nps-comment-text').value, }, sessid: BX.bitrix_sessid(), }), }); document.getElementById('nps-widget').innerHTML = '<p class="nps-thanks">Спасибо за ваш отзыв!</p>'; setTimeout(() => document.getElementById('nps-widget').style.display = 'none', 3000); }, dismiss() { document.getElementById('nps-widget').style.display = 'none'; this.markShown(); }, wasShown() { return !!localStorage.getItem('nps_shown_' + this.surveyId); }, markShown() { localStorage.setItem('nps_shown_' + this.surveyId, Date.now()); }, }; NPS.init(); </script> Триггеры показа
Опросник должен появляться в нужный момент, а не сразу при загрузке. Реализуем несколько триггеров:
const SurveyTriggers = { exitIntent(callback) { document.addEventListener('mouseleave', e => { if (e.clientY <= 0) callback(); }, {once: true}); }, scrollDepth(percent, callback) { const listener = () => { const scrolled = (window.scrollY / (document.body.scrollHeight - window.innerHeight)) * 100; if (scrolled >= percent) { window.removeEventListener('scroll', listener); callback(); } }; window.addEventListener('scroll', listener); }, afterOrder(callback) { if (window.location.href.includes('/order/success/')) { setTimeout(callback, 2000); } }, }; Триггеры настраиваются индивидуально для каждого опросника и могут комбинироваться. Для предотвращения повторных ответов используем localStorage/cookie для анонимных пользователей, проверку по user_id для авторизованных — это исключает дубли.
Как анализировать ответы?
Для NPS автоматически рассчитываем категорию промоутеров, пассивов и детракторов:
class NpsAnalytics { public static function calculate(int $surveyId): array { $responses = SurveyResponseTable::getList([ 'filter' => ['SURVEY_ID' => $surveyId], 'select' => ['ANSWERS_JSON'], ])->fetchAll(); $detractors = 0; // 0–6 $passives = 0; // 7–8 $promoters = 0; // 9–10 $total = 0; foreach ($responses as $r) { $answers = json_decode($r['ANSWERS_JSON'], true); $score = (int)($answers['nps_score'] ?? -1); if ($score < 0) continue; $total++; if ($score <= 6) $detractors++; elseif ($score <= 8) $passives++; else $promoters++; } if ($total === 0) return ['nps' => 0, 'total' => 0]; $nps = round(($promoters / $total - $detractors / $total) * 100); return [ 'nps' => $nps, 'total' => $total, 'promoters' => $promoters, 'passives' => $passives, 'detractors' => $detractors, ]; } } Пошаговый процесс разработки опросника
- Анализ и согласование — определяем цели (NPS, CSAT, исследование), выбираем триггеры и типы вопросов.
- Проектирование HL-блоков — создаём таблицы через API миграций, настраиваем поля.
- Реализация компонентов — пишем шаблоны виджетов, настраиваем AJAX-обработчики.
- Интеграция триггеров — подключаем exit-intent, прокрутку, события после заказа.
- Тестирование и отладка — проверяем на разных браузерах, устраняем конфликты.
- Запуск и аналитика — выводим дашборд с NPS, CSAT, конверсиями.
Что входит в работу
При заказе разработки опросника под ключ мы предоставляем:
- Настройка HL-блоков и миграций
- Написание компонентов (NPS, CSAT, кастомные)
- Реализация триггеров и защита от повторов
- Интеграция аналитики (NPS счётчик, сводные отчёты)
- Документация по API и настройке
- Доступы к репозиторию и тестовому стенду
- 30 дней технической поддержки после запуска
Почему HL-блоки лучше инфоблоков?
Highload-блоки — это таблицы с произвольным набором полей. Инфоблоки рассчитаны на контентное наполнение, а HL-блоки — на быстрые запросы с минимальной нагрузкой. Для опросников критична скорость записи данных без лишних событий. Таблица сравнения:
| Критерий | Инфоблоки | HL-блоки |
|---|---|---|
| Производительность записи | Средняя (события, оверхэд) | Высокая (прямой INSERT) |
| Гибкость полей | Фиксированные типы | Произвольные поля через ORM |
| Поддержка JSON-полей | Нет | Да, TextField |
| Подходит для опросов | Только хранение результатов | Хранение конфигурации и ответов |
Сроки и условия
Сроки зависят от сложности: простой виджет — от 2 дней, полноценный опросник — до 14 дней. Стоимость рассчитывается индивидуально. Окупаемость наступает в первый месяц за счёт автоматизации сбора данных и своевременного выявления проблем. Опираемся на HL-блоки — штатный инструмент Битрикса, гарантирующий совместимость с обновлениями. Наш опыт 10+ лет и более 50 внедрённых проектов подтверждает стабильность решений. Получите консультацию под вашу задачу — оценим объём работ без жёстких сроков. Закажите разработку опросника — и уже через месяц вы увидите чистый NPS вашего бизнеса.







