Разработка интеграции Битрикс24 с Яндекс.Формы
Яндекс.Формы — популярный инструмент для сбора данных: опросы, лиды, заявки, регистрации. Компании их активно используют, потому что формы быстро создаются, легко встраиваются, не требуют разработки. Но собранные данные остаются внутри Яндекс.Форм и вручную переносятся в CRM — менеджеры тратят время, ошибки в данных, задержки. Интеграция с Битрикс24 решает: каждая новая запись в форме автоматически создаёт лид или сделку.
Механизм передачи данных из Яндекс.Форм
Яндекс.Формы поддерживают два способа передачи данных:
- Webhook (интеграция «Отправить запрос») — при заполнении формы Яндекс отправляет POST-запрос на указанный URL с данными формы.
- Email-уведомление — менее удобно для автоматизации.
- Готовые интеграции — Яндекс.Трекер, Яндекс.Метрика, но не Битрикс24.
Нас интересует первый вариант — Webhook. Настраивается в Яндекс.Формы → Интеграции → Отправить запрос.
Формат данных. По умолчанию Яндекс отправляет данные в формате application/x-www-form-urlencoded или application/json (зависит от настроек). Ключи — ID вопросов формы (answer_short_text_12345678, answer_email_87654321). Значения — ответы пользователя.
Пример тела запроса:
{
"answer_short_text_1111": "Иван Петров",
"answer_email_2222": "[email protected]",
"answer_phone_3333": "+79001234567",
"answer_long_text_4444": "Комментарий к заявке",
"form_id": "12345",
"form_name": "Заявка на консультацию"
}
Обработчик webhook на стороне Битрикс24
Создаём публичный контроллер, который принимает запросы от Яндекс.Форм:
// /local/yandex-forms/webhook.php
define('NO_KEEP_STATISTIC', true);
define('NO_AGENT_STATISTIC', true);
define('NO_AGENT_CHECK', true);
define('DisableEventsCheck', true);
require_once $_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/prolog_before.php';
\Bitrix\Main\Loader::includeModule('crm');
$rawBody = file_get_contents('php://input');
// Яндекс.Формы могут слать как JSON, так и form-encoded
$contentType = $_SERVER['CONTENT_TYPE'] ?? '';
if (strpos($contentType, 'application/json') !== false) {
$formData = json_decode($rawBody, true) ?? [];
} else {
parse_str($rawBody, $formData);
}
// Проверка токена (задаём в GET-параметре URL webhook'а)
$token = $_GET['token'] ?? '';
if ($token !== YANDEX_FORMS_WEBHOOK_TOKEN) {
http_response_code(403);
exit;
}
// Маппинг полей формы → поля лида
$formId = $formData['form_id'] ?? 'unknown';
$mapper = FormFieldMapper::getMapper($formId);
if (!$mapper) {
// Форма не зарегистрирована — логируем и выходим
\Bitrix\Main\Diag\Debug::addToLog("Yandex.Forms: unknown form_id={$formId}");
http_response_code(200);
exit;
}
$leadFields = $mapper->mapToLead($formData);
// Создать лид в CRM
$lead = new \CCrmLead(false);
$leadId = $lead->Add($leadFields, true, ['REGISTER_SONET_EVENT' => true]);
if (!$leadId) {
http_response_code(500);
echo json_encode(['error' => $lead->LAST_ERROR]);
exit;
}
http_response_code(200);
echo json_encode(['ok' => true, 'lead_id' => $leadId]);
Маппер полей форм
Каждая форма Яндекс.Форм имеет свой набор полей с уникальными ID. Маппинг — конфигурация, которая переводит ID вопроса в поле лида:
namespace Local\YandexForms;
class FormFieldMapper
{
private static array $mappers = [];
public static function register(string $formId, array $fieldMap): void
{
self::$mappers[$formId] = $fieldMap;
}
public static function getMapper(string $formId): ?self
{
if (!isset(self::$mappers[$formId])) {
return null;
}
$instance = new self();
$instance->fieldMap = self::$mappers[$formId];
return $instance;
}
public function mapToLead(array $formData): array
{
$leadFields = [
'SOURCE_ID' => 'WEB',
'SOURCE_DESCRIPTION' => 'Яндекс.Форма: ' . ($formData['form_name'] ?? ''),
];
foreach ($this->fieldMap as $yandexKey => $crmField) {
if (isset($formData[$yandexKey])) {
if ($crmField === 'PHONE') {
$leadFields['PHONE'] = [['VALUE' => $formData[$yandexKey], 'VALUE_TYPE' => 'WORK']];
} elseif ($crmField === 'EMAIL') {
$leadFields['EMAIL'] = [['VALUE' => $formData[$yandexKey], 'VALUE_TYPE' => 'WORK']];
} else {
$leadFields[$crmField] = $formData[$yandexKey];
}
}
}
return $leadFields;
}
}
// Регистрация форм в init.php или модуле
FormFieldMapper::register('12345', [
'answer_short_text_1111' => 'NAME',
'answer_email_2222' => 'EMAIL',
'answer_phone_3333' => 'PHONE',
'answer_long_text_4444' => 'COMMENTS',
]);
Управление маппингами через интерфейс
Если форм много — хранить маппинги в конфиге неудобно. Решение: таблица b_local_yandex_form_mapping и страница администрирования в /local/admin/yandex_forms.php.
Структура таблицы:
| Поле | Описание |
|---|---|
| ID | Первичный ключ |
| FORM_ID | ID формы в Яндекс |
| FORM_NAME | Название для понимания |
| YANDEX_FIELD_KEY | Ключ поля в Яндекс (answer_...) |
| CRM_FIELD_CODE | Поле лида/сделки в Битрикс24 |
| CRM_ENTITY_TYPE | LEAD или DEAL |
| IS_ACTIVE | Активность |
Дополнительные сценарии
Создание сделки вместо лида. Для некоторых форм (например, «Заявка на крупный проект») имеет смысл сразу создавать сделку с заполненными реквизитами, а не лид. Маппер поддерживает поле CRM_ENTITY_TYPE = DEAL — в этом случае используем \CCrmDeal::Add().
Дедупликация. Если клиент заполнил форму дважды — не создавать дубли. Перед созданием лида проверяем наличие существующего по email или телефону через CCrmLead::GetList() с фильтром по PHONE или EMAIL.
Уведомление ответственного. После создания лида — уведомить менеджера через CIMNotify::Add() или через открытые линии Битрикс24.
Привязка к рекламным кампаниям. Если в URL формы передаются UTM-метки (utm_source, utm_campaign) — Яндекс.Формы можно настроить на передачу их в webhook. Сохраняем в UF-поля лида для аналитики.
Безопасность webhook
- URL webhook не должен быть очевидным — добавить
?token=RANDOM_SECRETв 32+ символа. - Ограничить доступ по IP: Яндекс.Формы отправляют запросы с диапазона
5.45.192.0/18и213.180.193.0/24— добавить в.htaccessили nginx allow. - Логировать все входящие запросы с телом в отдельную таблицу для отладки.
Сроки разработки
| Вариант | Состав | Срок |
|---|---|---|
| Одна форма → лид | Webhook, маппинг, создание лида | 1–2 дня |
| Несколько форм | Маппер с конфигом, разные сущности CRM | 3–4 дня |
| С UI управления | Интерфейс маппинга, дедупликация, логи | 5–8 дней |







