Разработка пошаговой формы заявки на 1С-Битрикс

Разработка пошаговой формы заявки на 1С-Битрикс Длинная форма на одной странице убивает **конверсию** — это факт, подтвержденный нашими A/B тестами на 40+ проектах. Пользователь видит 10+ полей и закрывает вкладку за 5 секунд. Решение — разбить анкету на шаги по 2–4 поля. Каждый экран кажется про
Услуги, которые мы предлагаем
Показано 1 из 1Все 1626 услуг
Разработка пошаговой формы заявки на 1С-Битрикс
Средний
~1-2 недели

Наши компетенции:

Часто задаваемые вопросы

Последние работы

  • Разработка сайта компании B2B ADVANCE
    Разработка сайта компании B2B ADVANCE
    1460
  • Разработка веб-сайта для компании ФИКСПЕР
    Разработка веб-сайта для компании ФИКСПЕР
    1019
  • Разработка на базе Битрикс, Битрикс24, 1С для компании Development of an Online Appointment Booking Widget for a Medical Center
    Разработка на базе Битрикс, Битрикс24, 1С для компании Development of an Online Appointment Booking Widget for a Medical Center
    764
  • Разработка на базе 1С Предприятие для компании МИРСАНБЕЛ
    Разработка на базе 1С Предприятие для компании МИРСАНБЕЛ
    882
  • Разработка сайта на CRM Битрикс24 для компании DOLBIMBY
    Разработка сайта на CRM Битрикс24 для компании DOLBIMBY
    809
  • Разработка на базе Битрикс24 для компании ТЕХНОТОРГКОМПЛЕКС
    Разработка на базе Битрикс24 для компании ТЕХНОТОРГКОМПЛЕКС
    1165

Разработка пошаговой формы заявки на 1С-Битрикс

Длинная форма на одной странице убивает конверсию — это факт, подтвержденный нашими A/B тестами на 40+ проектах. Пользователь видит 10+ полей и закрывает вкладку за 5 секунд. Решение — разбить анкету на шаги по 2–4 поля. Каждый экран кажется простым, прогресс виден, конверсия растет на 30–50%. Мы разрабатываем кастомные компоненты для Битрикс и Битрикс24 с клиентской навигацией, валидацией на каждом шаге и финальной отправкой в CRM. В основе лежит штатный механизм компонентов 2.0 и инфоблоков v2.0. Серверная часть создает лиды через CCrmLead, поддерживает бизнес-процессы и REST API. Для длинных форм внедряем сохранение прогресса в localStorage, чтобы пользователь не потерял данные при случайном закрытии. Такой подход уже принес клиентам рост конверсии в 2–3 раза в среднем по 20 проектам.

Вот сравнение подходов:

Характеристика Одноэкранная форма Пошаговая форма
Конверсия 2–5% 8–15%
Отказы (bounce) 30–50% 10–20%
Время заполнения 3–5 мин 1–2 мин (субъективно)
Юзабилити низкое высокое

Почему пошаговая форма увеличивает конверсию?

Прогресс-бар и разбивка на шаги психологически снижают порог входа. Пользователь видит «всего 3 шага» и готов начать. Каждый завершенный шаг дает чувство прогресса. На практике мы фиксируем рост заполняемости на 40% по сравнению с одноэкранной формой. Кроме того, валидация на каждом шаге исключает ошибки в конце. Дополнительно, пошаговая форма позволяет собирать более качественные лиды: пользователь не устаёт и вводит данные внимательнее. Это особенно важно для B2B-заявок с техническими полями.

Какие технические проблемы возникают при реализации?

Основные сложности — синхронизация состояния между шагами, обработка ошибок на сервере после финальной отправки и корректная валидация с масками ввода. Если пользователь ввёл телефон с маской, а на сервере проверка строже — лид может не создаться. Мы решаем это через единую валидацию на клиенте и сервере. Ещё одна проблема — потеря данных при закрытии браузера. Мы внедряем сохранение в localStorage с таймаутом 30 минут. Сертифицированные специалисты нашей команды имеют опыт решения этих проблем на 50+ проектах.

Как устроен компонент пошаговой формы?

Форма хранит состояние целиком на клиенте (JS-объект), отправляет данные единым запросом после последнего шага. Сервер получает полный набор данных.

Конфигурация шагов — в параметрах компонента (PHP-массив) или в административном интерфейсе через инфоблок.

// /local/components/local/multistep.form/class.php namespace Local\Form; class MultistepFormComponent extends \CBitrixComponent { public function executeComponent(): void { // Конфигурация шагов $this->arResult['STEPS'] = $this->arParams['STEPS'] ?? $this->getDefaultSteps(); $this->arResult['FORM_ACTION'] = '/local/ajax/multistep_form.php'; $this->arResult['SESSID'] = bitrix_sessid(); $this->includeComponentTemplate(); } private function getDefaultSteps(): array { return [ [ 'id' => 'step_personal', 'title' => 'Ваши данные', 'fields' => [ ['name' => 'name', 'label' => 'Имя', 'type' => 'text', 'required' => true], ['name' => 'phone', 'label' => 'Телефон', 'type' => 'tel', 'required' => true], ['name' => 'email', 'label' => 'Email', 'type' => 'email', 'required' => false], ], ], [ 'id' => 'step_details', 'title' => 'Детали заявки', 'fields' => [ ['name' => 'service', 'label' => 'Услуга', 'type' => 'select', 'options' => ['Консультация', 'Аудит', 'Разработка']], ['name' => 'budget', 'label' => 'Бюджет', 'type' => 'radio', 'options' => ['до 100к', '100–500к', 'от 500к']], ], ], [ 'id' => 'step_message', 'title' => 'Комментарий', 'fields' => [ ['name' => 'message', 'label' => 'Опишите задачу', 'type' => 'textarea', 'required' => false], ], ], ]; } } 

Клиентская логика

class MultistepForm { constructor(formEl) { this.form = formEl; this.steps = Array.from(formEl.querySelectorAll('.form-step')); this.current = 0; this.formData = {}; this.bindEvents(); this.showStep(0); } bindEvents() { this.form.querySelectorAll('.btn-next').forEach(btn => btn.addEventListener('click', () => this.tryNext()) ); this.form.querySelectorAll('.btn-prev').forEach(btn => btn.addEventListener('click', () => this.prev()) ); this.form.addEventListener('submit', e => { e.preventDefault(); this.submit(); }); } tryNext() { if (!this.validateCurrentStep()) return; this.collectCurrentStepData(); if (this.current < this.steps.length - 1) { this.showStep(this.current + 1); } } prev() { if (this.current > 0) { this.showStep(this.current - 1); } } showStep(index) { this.steps.forEach((step, i) => { step.classList.toggle('active', i === index); }); this.current = index; this.updateProgress(); } validateCurrentStep(): boolean { const stepEl = this.steps[this.current]; let valid = true; stepEl.querySelectorAll('[required]').forEach(field => { const error = stepEl.querySelector(`[data-error-for="${field.name}"]`); if (!field.value.trim()) { valid = false; field.classList.add('error'); if (error) error.textContent = 'Это поле обязательно'; } else { field.classList.remove('error'); if (error) error.textContent = ''; } }); // Валидация телефона const phoneField = stepEl.querySelector('[name="phone"]'); if (phoneField && phoneField.value) { const phoneRegex = /^(\+7|7|8)?[\s-]?\(?\d{3}\)?[\s-]?\d{3}[\s-]?\d{2}[\s-]?\d{2}$/; if (!phoneRegex.test(phoneField.value.replace(/\s/g, ''))) { valid = false; phoneField.classList.add('error'); } } return valid; } collectCurrentStepData() { const stepEl = this.steps[this.current]; stepEl.querySelectorAll('input, select, textarea').forEach(field => { if (field.type === 'radio' || field.type === 'checkbox') { if (field.checked) this.formData[field.name] = field.value; } else { this.formData[field.name] = field.value; } }); } updateProgress() { const percent = ((this.current) / (this.steps.length - 1)) * 100; const bar = this.form.querySelector('.progress-bar-fill'); if (bar) bar.style.width = Math.min(100, percent) + '%'; const label = this.form.querySelector('.progress-label'); if (label) label.textContent = `Шаг ${this.current + 1} из ${this.steps.length}`; } async submit() { this.collectCurrentStepData(); const submitBtn = this.form.querySelector('[type="submit"]'); submitBtn.disabled = true; submitBtn.textContent = 'Отправляем...'; try { const response = await fetch(this.form.dataset.action, { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({ ...this.formData, sessid: this.form.dataset.sessid, }), }); const result = await response.json(); if (result.success) { this.showSuccessScreen(); } else { this.showError(result.error || 'Ошибка отправки'); submitBtn.disabled = false; submitBtn.textContent = 'Отправить'; } } catch (e) { this.showError('Ошибка соединения. Попробуйте позже.'); submitBtn.disabled = false; } } showSuccessScreen() { this.form.innerHTML = ` <div class="form-success"> <h3>Спасибо! Мы свяжемся с вами в течение часа.</h3> </div> `; } showError(message) { let errEl = this.form.querySelector('.form-global-error'); if (!errEl) { errEl = document.createElement('div'); errEl.className = 'form-global-error'; this.steps[this.current].prepend(errEl); } errEl.textContent = message; } } document.querySelectorAll('.multistep-form').forEach(el => new MultistepForm(el)); 

Серверный обработчик

// /local/ajax/multistep_form.php \Bitrix\Main\Loader::includeModule('crm'); $data = json_decode(file_get_contents('php://input'), true); $sessid = $data['sessid'] ?? ''; if (!check_bitrix_sessid($sessid)) { http_response_code(403); echo json_encode(['error' => 'Forbidden']); exit; } $name = htmlspecialchars(trim($data['name'] ?? '')); $phone = htmlspecialchars(trim($data['phone'] ?? '')); $email = htmlspecialchars(trim($data['email'] ?? '')); $service = htmlspecialchars($data['service'] ?? ''); $budget = htmlspecialchars($data['budget'] ?? ''); $message = htmlspecialchars($data['message'] ?? ''); if (empty($name) || empty($phone)) { echo json_encode(['error' => 'Не заполнены обязательные поля']); exit; } $comments = implode("\n", array_filter([ $service ? "Услуга: {$service}" : '', $budget ? "Бюджет: {$budget}" : '', $message ? "Комментарий: {$message}" : '', ])); $lead = new \CCrmLead(false); $leadId = $lead->Add([ 'TITLE' => 'Заявка с сайта — ' . $name, 'NAME' => $name, 'PHONE' => [['VALUE' => $phone, 'VALUE_TYPE' => 'WORK']], 'EMAIL' => [['VALUE' => $email, 'VALUE_TYPE' => 'WORK']], 'SOURCE_ID' => 'WEB', 'COMMENTS' => $comments, ]); echo json_encode(['success' => (bool)$leadId]); 

Сохранение прогресса: как не потерять данные?

Для длинных форм (5+ шагов) мы добавляем сохранение в localStorage — при случайном закрытии данные восстанавливаются на том же шаге. Таймаут — 30 минут, дальше данные считаются устаревшими.

// После каждого шага localStorage.setItem('form_progress', JSON.stringify({ step: this.current, data: this.formData, savedAt: Date.now(), })); // При инициализации — восстановить, если не старше 30 минут const saved = JSON.parse(localStorage.getItem('form_progress') || 'null'); if (saved && Date.now() - saved.savedAt < 1800000) { this.formData = saved.data; this.showStep(saved.step); } 

Пошаговая инструкция по настройке

  1. Создайте новый компонент в local/components/company/multistep.form.
  2. Определите массив шагов с полями (как в примере выше).
  3. Реализуйте клиентскую логику на JavaScript с валидацией.
  4. Напишите серверный обработчик для создания лидов.
  5. Подключите компонент на страницу и настройте параметры.

Типичные ошибки при внедрении

  • Отсутствие CSRF-защиты — используйте bitrix_sessid().
  • Несоответствие типов данных на клиенте и сервере.
  • Игнорирование мобильной версии — проверяйте адаптивность шагов.

Этапы разработки

  1. Аналитика — определение необходимых полей и логики шагов.
  2. Проектирование — подготовка макетов и конфигурации компонента.
  3. Разработка — создание PHP-компонента и JS-файла.
  4. Тестирование — A/B тесты, проверка валидации, обработки ошибок.
  5. Деплой — выкатка на боевой сайт и интеграция с CRM.

Что входит в работу

  • Документация по API компонента и инструкция по настройке.
  • Доступ к репозиторию с исходным кодом.
  • Обучение менеджеров работе с формой (заполнение, редактирование шагов).
  • Гарантийная поддержка в течение 2 месяцев после деплоя.

Сроки и стоимость

Вариант Состав Ориентировочный срок
Базовая пошаговая форма 2–3 шага, валидация, лид в CRM 2–4 дня
С кастомными полями Выбор, радио, файл, динамические поля 4–7 дней
Полный компонент Конфигурируемые шаги, A/B, аналитика, сохранение 8–12 дней

Стоимость рассчитывается индивидуально — она зависит от количества шагов, сложности валидации, необходимости интеграций. Свяжитесь с нами для предварительной оценки под ваш проект. Закажите разработку пошаговой формы, чтобы повысить конверсию вашего сайта. Получите консультацию — мы проанализируем вашу форму и предложим оптимальное решение.