Виджет не работает — что проверить
Реальные кейсы, которые встречаются на проде. Для каждого — что увидите, в чём причина, как починить.
Кнопка виджета не появляется
Симптом
Вставили <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 — добавьте наши хосты:
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 с лидирующей точкой:
<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() до того, как посетитель откроет чат — например, сразу после входа:
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:
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 — добавим в этот раздел.

