Troubleshooting
Виджет / Troubleshooting

Виджет не работает — что проверить

Реальные кейсы, которые встречаются на проде. Для каждого — что увидите, в чём причина, как починить.

Кнопка виджета не появляется

Симптом

Вставили <script>-тег, открыли сайт — круглой кнопки в углу нет.

1. Скрипт реально загрузился?

DevTools → Network → фильтр widget-bundle. Должен быть GET 200 (или 304 из кеша).

  • 404 — опечатка в адресе (проверьте support.forestsnet.com/widget-bundle?ws=…).
  • Нет ?ws= в адресе скрипта — бандл загрузится, но виджет не запустится: он стартует только с ID проекта в параметре ws.
  • Запроса нет вообще — его блокирует расширение или CSP. См. ниже.
  • 500 — ошибка на нашей стороне. Сразу пишите в саппорт и пришлите URL.

Неверный или удалённый ID проекта ошибки не даёт: бандл отвечает 200, кнопка может появиться в стандартном оформлении, но сообщения не отправляются. Сверьте ID в сниппете.

2. Кнопка скрыта намеренно?

Атрибут data-hide-launcher="true" на script-теге или init({hideLauncher: true}) убирают кнопку — виджет тогда открывается только через window.SupportHub.open(). Ещё кнопку может спрятать ваш custom CSS.

3. Console: ошибки?

Сам виджет в Console ничего не пишет. Ищите сообщения браузера:

  • Refused to load the script…, Refused to connect to… — блокирует CSP. См. следующий пункт.
  • WebSocket connection to 'wss://…' failed — см. WebSocket падает.

4. CSP (Content Security Policy)

Если ваш сайт задаёт CSP — добавьте наши хосты:

http
Content-Security-Policy:
  script-src  'self' https://support.forestsnet.com 'unsafe-inline';
  style-src   'self' 'unsafe-inline';
  connect-src 'self' https://api.support.forestsnet.com wss://api.support.forestsnet.com;
  img-src     'self' data: blob: https://api.support.forestsnet.com;
  media-src   'self' https://api.support.forestsnet.com;
  • script-src — чтобы загрузить бандл. 'unsafe-inline' нужен, потому что сам сниппет-загрузчик — inline-скрипт. Если не хотите unsafe-inline, подключите виджет прямым <script async src="…">.
  • style-src 'unsafe-inline' — виджет добавляет свои стили тегами <style>.
  • connect-src — REST-запросы и WebSocket к нашему API.
  • img-src / media-src — вложения, картинки, видео и аудио отдаются с хоста API; логотип и иконка, загруженные в конструкторе, встроены как data:, а превью в поле ввода — blob:. Если задаёте картинки ссылкой (логотип, аватары, обложка), добавьте и эти хосты.

Если что-то всё ещё блокируется, Console назовёт директиву и хост.

5. Блокировщики

Расширения вроде Adblock, NoScript или Privacy Badger могут заблокировать бандл у отдельных посетителей. Если виджета не видит один конкретный посетитель — пусть проверит свои расширения.

WebSocket падает / постоянно переподключается

Виджет открывает WebSocket, только когда у посетителя есть диалог — после первого сообщения или сразу при загрузке, если открытый тикет уже есть. До этого соединения нет, и падать нечему. Если в Console снова и снова видно WebSocket connection to wss://… failed (виджет переподключается с нарастающей паузой, до 30 секунд), проверьте:

  • CSP connect-src — в нём должен быть wss://api.support.forestsnet.com.
  • Корпоративный прокси или файрвол, который не пропускает WebSocket: REST работает, а сокет — нет.
  • Просроченный или неверный visitor_token: сервер закрывает соединение с кодом 4401. См. Токен не принимается (401).

Без сокета виджет открывается и отправляет сообщения, но ответы оператора не появляются сразу — посетитель увидит их, когда снова откроет диалог. Запасного канала (long-polling) нет.

Один визитор → два контакта (cross-subdomain)

Посетитель пишет с example.com, потом переходит на app.example.com, и в дашборде это выглядит как два разных контакта с двумя параллельными беседами.

Причина

Visitor session ID хранится в cookie, привязанной к хосту, и в localStorage, который у каждого поддомена свой. По умолчанию поддомены его не делят.

Решение

Задайте cookie domain с лидирующей точкой:

html
<script
  async
  src="https://support.forestsnet.com/widget-bundle?ws=YOUR_WORKSPACE_UUID"
  data-cookie-domain=".example.com"
></script>

То же самое можно задать в поле «Cookie-домен (опционально)» в НастройкиКонструктор виджетаРасширенные — и сниппет на всех поддоменах останется одинаковым. data-cookie-domain важнее конфига (удобно, если стейдж и прод на разных доменах).

Visitor «забывается» после нескольких дней (Safari ITP)

В Safari посетитель возвращается через неделю, и SupportHub показывает его как нового — старая история не подхватывается.

Причина

Intelligent Tracking Prevention в Safari ограничивает cookie, выставленные скриптом, семью днями, а если посетитель давно не заходил на сайт, может удалить и остальные данные сайта. Без ID бэкенд считает посетителя новым.

Решение

Виджет хранит ID сразу в нескольких местах (cookie, localStorage, sessionStorage, IndexedDB) и при каждой загрузке восстанавливает cookie из уцелевшей копии. Это спасает, когда пропала только cookie; если Safari очистил всё, посетитель будет новым.

Чтобы связь не терялась, используйте identify с visitor_token из вашей системы.

Панель открывается пустой или сломанной

Причина 1: custom CSS

Custom CSS действует на всю страницу и может скрыть или перекрыть части панели. Очистите поле «Собственный CSS» в НастройкиКонструктор виджетаРасширенные, опубликуйте и проверьте снова.

Причина 2: запросы к API блокируются

Панель строится из конфига, встроенного в бандл, а история, статьи и новости загружаются с API. Если запросы к api.support.forestsnet.com блокирует CSP или сеть, эти части остаются пустыми. Проверьте Network на заблокированные запросы.

Кнопка «Отменить» в конструкторе отбрасывает только неопубликованные изменения черновика. Если проблема в опубликованной версии, исправьте поле и опубликуйте заново.

Prechat спрашивает, несмотря на identify

Причина

Виджет пропускает только те обязательные поля, которые уже знает. Обязательные поля задаются в НастройкиКонструктор виджетаФормы и темы; известными считаются email, имя и телефон из data-* атрибутов или identify() (Telegram ID не в счёт), а также данные контакта из прошлых обращений. Если обязателен телефон, а вы передали только email и имя, виджет спросит телефон.

Проверка происходит, когда посетитель открывает новый диалог, — вызов identify() после этого на уже открытый диалог не влияет.

Решение

Передавайте все обязательные поля и вызывайте identify() до того, как посетитель откроет чат — например, сразу после входа:

js
window.SupportHub.identify({
  email: user.email,
  name: user.fullName,
  phone: user.phone, // если телефон тоже обязателен
});

Powered by SupportHub не скрывается

Причина

Переключатель «Скрыть «Powered by SupportHub»» в разделе «Брендинг» доступен только на тарифах с собственным брендингом. На остальных он заблокирован, и строка остаётся.

Решение

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

Изменения в конструкторе не доезжают до посетителей

Причина

Конструктор сохраняет изменения в черновик, а посетители видят только опубликованную версию. Кнопка Опубликовать — в верхней панели конструктора.

Кеш

Опубликованный конфиг встроен в бандл, а бандл кешируется на 5 минут с фоновым обновлением (Cache-Control: public, max-age=300, stale-while-revalidate=86400). До 5 минут после публикации посетитель может получить старую версию, а потом браузер ещё раз покажет копию из кеша, пока в фоне загружает новую. Ответ /config кешируется на 60 секунд. Чтобы проверить изменения сразу, обновите страницу без кеша (hard refresh).

Реакции / inline-клавиатура не работают

Обе функции включены по умолчанию.

  • Реакции. Посетитель ставит реакцию на сообщение оператора: панель с эмодзи появляется при наведении или долгом нажатии на сенсорном экране. Переключателя в конструкторе нет — реакции работают, пока в конфиге conversation.reactions_enabled не выключен.
  • Inline-клавиатура. Кнопки под сообщением появляются, только если они есть у самого сообщения. Переключатель «Включить inline-клавиатуры» — в НастройкиКонструктор виджетаКнопки ответа: проверьте, что он включён и изменения опубликованы.

Токен не принимается (401)

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

bash
curl "https://api.support.forestsnet.com/api/webhooks/widget/YOUR_WS/recent?visitor_token=TOKEN"
  • invalid visitor_token signature — не тот секрет (например, его сменили в НастройкиКаналыWeb Widget, а ваш сервер подписывает старым) или HMAC посчитан не над теми байтами, что в первой части токена (например, над base64-строкой).
  • invalid visitor_token — токен не вида <base64url>.<hex> или payload — не JSON.
  • visitor_token expired — exp прошёл: проверьте TTL и часы на вашем сервере.
  • invalid visitor_token exp — exp не число.
  • visitor_token missing user_id — в payload нет user_id или он пустой.

Формат и проверки — в HMAC visitor token.

Сообщения не отправляются (403)

Отправка сообщений, загрузка файлов и identify получают 403 widget origin not allowed. Причина — список «Разрешённые домены» в НастройкиКонструктор виджетаПриватность: если он не пустой, запросы принимаются только с перечисленных доменов (example.com — только этот хост, *.example.com — любой поддомен). Добавьте домен сайта и опубликуйте.

Что-то ещё?

Не нашли свой кейс? Напишите нам через сам виджет на support.forestsnet.com — добавим в этот раздел.

Была ли страница полезной?