Если форма в WPForms уже собирает заявки, следующий узкий и полезный шаг — отправлять их сразу в CRM через Webhook. Это снимает ручной перенос данных, уменьшает риск потерять лид и позволяет строить нормальную воронку без промежуточных CSV и копипаста.
Ниже разберём рабочую схему: как понять, что именно ломается, как собрать отправку на стороне WordPress, как проверить результат и где обычно ошибаются.
Когда Webhook нужен, а когда лучше не усложнять
Webhook имеет смысл, если CRM умеет принимать HTTP-запросы: POST с JSON, form-data или x-www-form-urlencoded. Если у сервиса есть официальный API и готовый интеграционный плагин, это часто проще. Но в реальных проектах Webhook удобен тем, что не привязан к конкретному плагину и позволяет передавать только нужные поля.
| Подход | Плюс | Минус |
|---|---|---|
| Готовый плагин интеграции | Быстро настраивается | Меньше контроля над payload |
| Webhook из WPForms | Гибко, можно фильтровать данные | Нужно проверить формат и ответ CRM |
Кастомный код через wp_remote_post() | Полный контроль | Нужно поддерживать код и обработку ошибок |
Диагностика: что проверить до внедрения
Перед кодом стоит понять, где именно может быть сбой. В 80% случаев проблема не в WPForms, а в формате запроса, SSL, авторизации или неверном URL.
Проверьте со стороны CRM
- какой метод нужен:
POST,PUTили другой; - какой формат ожидается: JSON, form-data, XML;
- нужен ли токен в заголовке
Authorization; - принимает ли CRM запросы с внешних серверов без whitelist IP;
- возвращает ли API понятный код ответа:
200,201,400,401,422.
Проверьте на стороне WordPress
- включён ли исходящий HTTP-запрос на хостинге;
- не блокирует ли firewall запросы к внешнему домену;
- есть ли у сайта корректный SSL-сертификат;
- не обрезаются ли поля формы на этапе отправки;
- не отправляется ли форма дважды через AJAX и обычный submit одновременно.
Пошаговое решение: отправка данных WPForms в CRM через Webhook
Ниже пример для случая, когда после отправки формы нужно отправить данные в внешний endpoint CRM. Логика простая: ловим отправку формы, собираем нужные поля и отправляем их через wp_remote_post().
Пример рассчитан на то, что вы знаете ID формы и ID полей. Их можно посмотреть в конструкторе WPForms.
<?php
add_action( 'wpforms_process_complete', 'wpform_ru_send_to_crm_webhook', 10, 4 );
function wpform_ru_send_to_crm_webhook( $fields, $entry, $form_data, $entry_id ) {
$target_form_id = 123;
if ( (int) $form_data['id'] !== $target_form_id ) {
return;
}
$payload = array(
'name' => isset( $fields[1]['value'] ) ? sanitize_text_field( $fields[1]['value'] ) : '',
'email' => isset( $fields[2]['value'] ) ? sanitize_email( $fields[2]['value'] ) : '',
'phone' => isset( $fields[3]['value'] ) ? sanitize_text_field( $fields[3]['value'] ) : '',
'source' => 'wpforms',
'page' => isset( $_SERVER['HTTP_REFERER'] ) ? esc_url_raw( wp_unslash( $_SERVER['HTTP_REFERER'] ) ) : '',
);
$response = wp_remote_post( 'https://crm.example.com/api/leads', array(
'timeout' => 15,
'headers' => array(
'Content-Type' => 'application/json; charset=utf-8',
'Authorization' => 'Bearer YOUR_API_TOKEN',
),
'body' => wp_json_encode( $payload ),
) );
if ( is_wp_error( $response ) ) {
error_log( 'WPForms CRM webhook error: ' . $response->get_error_message() );
return;
}
$code = wp_remote_retrieve_response_code( $response );
if ( $code < 200 || $code >= 300 ) {
error_log( 'WPForms CRM webhook HTTP ' . $code . ': ' . wp_remote_retrieve_body( $response ) );
}
}
Этот вариант хорош тем, что не зависит от стороннего плагина. Но если CRM требует другой формат, меняется только блок headers и body.
Если CRM ждёт form-data
Некоторые сервисы не любят JSON и принимают обычные поля формы. Тогда отправляйте массив без wp_json_encode() и без заголовка JSON:
<?php
$response = wp_remote_post( 'https://crm.example.com/api/leads', array(
'timeout' => 15,
'headers' => array(
'Authorization' => 'Bearer YOUR_API_TOKEN',
),
'body' => array(
'name' => sanitize_text_field( $fields[1]['value'] ),
'email' => sanitize_email( $fields[2]['value'] ),
'phone' => sanitize_text_field( $fields[3]['value'] ),
),
) );
Как понять, что решение сработало
Проверка должна быть не на уровне «форма отправилась», а на уровне фактического попадания данных в CRM.
- Отправьте тестовую заявку с уникальным email или телефоном.
- Проверьте запись в CRM: создалась ли сделка, лид или контакт.
- Посмотрите ответ API в логах WordPress, если CRM не приняла запрос.
- Если CRM возвращает ID сущности, убедитесь, что он совпадает с ожидаемым форматом.
- Проверьте, не дублируется ли заявка при повторной отправке формы.
Для быстрой диагностики удобно временно логировать ответ сервера. Если у вас включён WP_DEBUG_LOG, это поможет увидеть HTTP-код и тело ответа без лишних догадок.
<?php
if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
error_log( 'CRM response code: ' . $code );
error_log( 'CRM response body: ' . wp_remote_retrieve_body( $response ) );
}
Частые ошибки и как их исправить
401 Unauthorized
Обычно это неверный токен, неправильный заголовок авторизации или токен с ограниченными правами. Проверьте, нужен ли Bearer, либо CRM ожидает другой формат, например X-API-Key.
400 Bad Request или 422 Unprocessable Entity
Чаще всего проблема в структуре payload: CRM ждёт другие имена полей, обязательный параметр пустой или email не проходит валидацию. Сверьте схему запроса с документацией сервиса.
Запрос уходит, но лид не создаётся
Иногда CRM принимает запрос, но кладёт его в очередь или отбрасывает из-за бизнес-правил. Проверьте дубли, обязательные статусы, воронку и ограничения по источнику.
Форма отправляется дважды
Это бывает при одновременной обработке AJAX и кастомного хука без проверки формы. Всегда ограничивайте код конкретным form_id и не вешайте отправку на общий обработчик без условий.
SSL error или timeout
Если хостинг старый или внешний API медленный, запрос может падать по таймауту. Увеличьте timeout до разумного значения и проверьте сертификат удалённого сервера.
Чек-лист перед запуском в продакшн
- Проверен
form_idи ID полей. - Согласован формат запроса с CRM.
- Токен хранится не в открытом виде в репозитории.
- Включено логирование ошибок на этапе теста.
- Проверена отправка с реальной формы, а не только из админки.
- Убраны лишние поля, которые CRM не использует.
- Проверено, что запрос не дублируется при повторной отправке страницы.
Безопасность и производительность
Webhook не должен тормозить отправку формы. Если CRM отвечает медленно, лучше не держать пользователя на ожидании дольше необходимого. Для тяжёлых сценариев можно складывать данные в очередь и отправлять их отдельной задачей, но это уже отдельная архитектура.
С точки зрения безопасности:
- не передавайте в CRM лишние персональные данные;
- санитизируйте все поля до отправки;
- не храните токены в публичных файлах;
- по возможности ограничьте доступ к endpoint по IP или секретному ключу;
- не логируйте полный payload, если там есть чувствительные данные.
Если на сайте много форм и нужно централизованно управлять уведомлениями, иногда удобнее сначала привести сайт в порядок по технической части: убрать лишние дубли, почистить служебные скрипты и сократить конфликтные настройки. Для этого у WPShop есть Clearfy Pro: https://wpshop.ru/plugins/clearfy?utm_source=wpform.ru&utm_medium=article&utm_campaign=wpforms-otpravit-dannye-v-crm-cherez-webhook
Когда лучше идти не через код, а через промежуточный сервис
Если CRM требует сложную авторизацию, многоступенчатую трансформацию данных или ретраи с очередью, прямой вызов из WordPress может быть неудобен. В таком случае разумнее использовать промежуточный слой: Make, n8n или собственный endpoint, который уже отправляет данные в CRM в нужном формате. Это снижает зависимость от одного плагина и упрощает отладку.
Но если задача простая — передать заявку, имя, email и телефон — прямой Webhook из WPForms обычно закрывает её без лишней инфраструктуры.