# Заявки из чата приходят в сквозную аналитику без источника

> Вебхук чата приходит сервер-серверу, cookie визита в нём нет — и 23 заявки из 23 попали в аналитику без источника. Разбираем, как довезти метку.

12 августа 2026 · Заря · 8 минут

Чат на сайте отдаёт заявки в сквозную аналитику через вебхук, и они приходят без источника: не видно ни рекламной кампании, ни страницы, с которой человек написал. Причина обычно не в аналитике и не в настройках чата.

## Почему заявки из чата приходят без источника

Потому что вебхук чата приходит с сервера сервиса на ваш сервер, а метка визита живёт в cookie браузера. В запросе от чата этой cookie нет и быть не может: браузер посетителя в обмене не участвует.

Обработчик при этом выглядит рабочим — он читает метку из полей формы. Но если поле в форму никто не положил, читается пустая строка, и так на каждом событии.

_Тихая поломка: строка читается, значение всегда пустое_

```php
// Выглядит правильно, а не работает никогда:
// вебхук приходит сервер-серверу, cookie roistat_visit в нём нет,
// а поля roistat_visit в форме чата никто не заводил.
$roistatVisit = isset($form['roistat_visit']) ? $form['roistat_visit'] : '';
```

Факты в одном из разборов сошлись с точностью до строчки. В кабинете аналитики 23 заявки из 23 по каналу чата — без номера визита, источник помечен как неопределённый. В логе обработчика за семь месяцев 182 события, из них 26 контактных форм, и во всех payload метка визита пустая.

Проверка занимает минуту и не требует доступа в кабинет: откройте лог обработчика и посмотрите одно событие целиком. Если поля с меткой нет в самом payload — чинить надо на сайте, а не в аналитике.

## Как передать метку визита, если cookie в вебхук не попадает

Через произвольное поле клиента. Виджет чата умеет принимать свои поля с сайта: код на странице читает cookie и отдаёт значение виджету. Клиенту это поле не показывается, оператор видит его в карточке, а в вебхук оно приезжает вместе с данными формы.

_Метка визита уходит в виджет с сайта, а не из кабинета чата_

```js
window.replainSettings = {
  id: 'идентификатор чата',
  // Метку кладём в произвольное поле клиента: клиент его не видит,
  // в вебхуке оно придёт вместе с данными формы.
  fields: {
    roistat_visit: (document.cookie.match(/(?:^|;\s*)roistat_visit=([^;]+)/) || [])[1] || ''
  },
  onWidgetLoaded: function () {
    // Счётчик аналитики ставит cookie асинхронно и может не успеть
    // к моменту загрузки виджета — досылаем поле, когда она появится.
    var tries = 0, t = setInterval(function () {
      var m = document.cookie.match(/(?:^|;\s*)roistat_visit=([^;]+)/);
      if (m) { window.ReplainAPI('setFields', { roistat_visit: m[1] }); clearInterval(t); }
      if (++tries > 30) { clearInterval(t); }
    }, 1000);
  }
};
```

- Cookie аналитики ставится асинхронно, поэтому одной строки в настройках мало — нужна досылка после загрузки виджета
- Имя, почту и телефон через этот же механизм передавать нельзя: если передать значения всех полей формы, форма клиенту показана не будет
- Поле сохраняется в карточке клиента на стороне чата, поэтому приходит и в последующих событиях того же диалога, а не только в момент отправки формы

Проверять это надо на живом трафике, а не на тестовом запросе. В логе после правки видно и метку в payload, и ответ аналитики: пришёл визит 467383, заявка создана.

## Все ли события чата приносят контакты

Нет. Контакты клиента несут четыре разных события, а обработчик в том разборе реагировал на одно — остальные три логировались и пропускались, то есть эти обращения не попадали в аналитику вообще.

| Событие | Когда возникает | Обрабатывалось |
| --- | --- | --- |
| Контактная форма | Клиент заполнил форму в виджете | да |
| Офлайн-форма | Операторы не в сети, клиент оставил контакты | нет |
| Авто-запрос контактов | Чат сам просит контакты по ходу диалога | нет |
| Запрос обратного звонка | Клиент просит перезвонить | нет |

Это вторая причина «неполной передачи данных», и снаружи она неотличима от первой: заявки просто есть не все. Разница видна только в логе — событие пришло, а в аналитику ушёл ответ «пропущено».

## Что вебхук требует от обработчика

Ответ 200 и быстро. У этого сервиса таймаут обработчика 10 секунд и до 5 повторов примерно раз в минуту; если ответ не 200, доставка всех последующих событий этого клиента приостанавливается, а по исчерпании попыток события удаляются.

- Отвечать 200 всегда, даже когда событие вам неинтересно — иначе сервис перестанет присылать события по этому клиенту
- Не поднимать CMS ради вебхука: из ядра берутся только реквизиты подключения к базе, чтобы уложиться в таймаут
- Быть идемпотентным: до пяти повторов означает, что одно обращение может приехать пять раз
- Держать секретный токен в адресе обработчика и отдавать 403 без него

_Защита от повторной доставки_

```php
// Идемпотентность на уровне схемы, а не логики:
// UNIQUE по идентификатору события + INSERT IGNORE.
// Повтор доставки не создаст ни второй строки, ни второй заявки.
$stmt->execute();
$stored = $stmt->affected_rows > 0;   // 0 — такое событие уже приходило

if (!$stored) {
    echo json_encode(array('status' => 'ok', 'message' => 'Duplicate event'));
    exit;
}
```

Отдельная и почти невидимая беда: после переезда сайта на новую площадку адрес вебхука начал отдавать 404. По правилам сервиса это сначала приостанавливает доставку, а потом удаляет события — обращения через чат не доходили никуда и следа не оставляли. При смене домена, хостинга или движка адреса вебхуков проверяются первыми.

## Как различить заявки нескольких сайтов в одной аналитике

Класть домен в заголовок заявки и в её поля. Если у компании несколько сайтов, они обычно пишут в один проект аналитики одним ключом счётчика и одним ключом вебхука, а заголовок заявки у всех одинаковый — «Новая заявка с чата». В списке заявок такие обращения неразличимы.

_Заголовок и поле site отвечают на вопрос «с какого сайта пришли»_

```php
// Домен — в заголовок заявки и в поля.
// Это разделение по сайтам на уровне заявок; визиты им не разделишь.
$title = $leadEvents[$eventType] . ($domain !== '' ? ' — ' . $domain : '');

$payload = array(
    'title'         => $title,
    'roistat_visit' => $roistatVisit,
    'fields'        => array(
        'site'       => $domain,
        'event_type' => $eventType,
        'page'       => $page,
    ),
);
```

Полного разделения это не даёт: пока в проекте аналитики выключен мультидомен, визиты всех сайтов лежат в одной куче, и разбивка возможна только по заявкам. Это отдельное решение и отдельные деньги, но заголовок с доменом делается за час и закрывает вопрос «откуда эта заявка» уже сегодня.

## Куда девать переписку, если в аналитику её не отправить

Хранить у себя и связывать с заявкой по номеру визита. Дописать сообщения в уже созданную заявку нельзя: вебхук умеет только создавать, а API заявок доступно на чтение. Отправлять каждое сообщение отдельно — значит превратить один диалог в десяток заявок.

- Две таблицы в базе сайта: карточка диалога на клиента и лента всех событий, включая реплики оператора
- Ключ склейки с аналитикой — номер визита: он виден в карточке заявки, по нему достаётся переписка
- Метка визита в карточке перезаписывается только непустым значением, иначе позднее событие затрёт раннее
- Если в событии метки нет, она подтягивается из карточки клиента по его идентификатору

Читать это должны менеджеры, а не разработчик через выгрузку. Поэтому переписка выведена в админку сайта отдельным разделом: список диалогов с фильтром по имени, телефону, почте, номеру визита и периоду — и карточка с лентой сообщений в хронологии.

- Переписка с телефонами и почтой — персональные данные: доступ по сессии администратора либо по токену, каталог логов наружу отдаёт 403
- Срок хранения задаётся явно и согласуется с владельцем данных; чистка идёт попутно при записи не чаще раза в сутки, если планировщика на хостинге нет
- Соединение с базой на время своих запросов переключается в utf8mb4 — иначе эмодзи из чата приезжают вопросительными знаками
- В выгрузке CSV значения, начинающиеся с =, +, - или @, предваряются апострофом, иначе таблица исполнит их как формулы

## Что проверять после правки

Не «код на месте», а сквозной путь: обращение в чате должно закончиться заявкой с номером визита. Промежуточные признаки ничего не доказывают.

- На боевой странице отдаётся новая версия скрипта, а не закэшированная — при кэше статики в неделю правку приходится доставлять сменой версии у подключений, в том разборе на 679 страницах
- В логе обработчика появилось событие с непустой меткой визита
- В кабинете аналитики по этому обращению создан лид, и номер визита у него заполнен
- Повторная отправка того же события заявку не дублирует
- Обработчик без токена отдаёт 403, с токеном — 200
- Перед заливкой у каждого правленого файла есть резервная копия на сервере, а откат описан одной строкой

## Может ли чужой виджет остановить сбор заявок

Может, и без вашего участия. В день работ у сервиса чата истёк TLS-сертификат домена, с которого грузится виджет. Браузеры перестали загружать скрипт с ошибкой сертификата, файл при этом сервером отдавался — виджет исчез со всех сайтов, где он стоял, примерно на три часа, пока сервис не выпустил новый сертификат.

Обхода на своей стороне нет: домен и сертификат чужие. Что реально можно сделать — знать об этом раньше клиента.

- Следить за сроком сертификата у внешних доменов, от которых зависит сбор заявок, а не только у своего
- Ставить оповещение на тишину: лог обработчика не пополнялся N дней — повод проверить, а не радоваться
- Держать адреса вебхуков в списке того, что проверяется после любого переезда

Тишина, впрочем, не всегда поломка. В том же разборе лог молчал три месяца — и оказалось, что обращений через чат за это время действительно не было, а вебхук всё время был исправен. Отличить одно от другого можно только живой проверкой.

## Если заявки не сходятся с аналитикой

Разбор начинается с лога обработчика и одной живой заявки, проведённой от клика до карточки в аналитике. Отчёт с причинами и приоритетами остаётся у вас, даже если чинить будете сами.

[Посмотреть услугу: маркетинг и SEO](https://it-zarya.ru/services/seo/) [Обсудить задачу](https://it-zarya.ru/contacts/)

---

Источник: https://it-zarya.ru/blog/chat-leads-no-source/ · IT-агентство «Заря» · itzarya@mail.ru
Markdown-версия любой страницы сайта — тот же адрес с `.md` на конце. Индекс для ассистентов: https://it-zarya.ru/llms.txt
