Установка виджета
Рекомендуемый сниппет — асинхронный загрузчик l.js. Он не блокирует страницу, не использует document.write / eval, не пишет cookie до открытия чата и переживает GTM (не зависит от document.currentScript).
Обычная установка
<script>
window.PLG_WORKSPACE_ID = "YOUR_WORKSPACE_ID";
window.PLG_SERVER = "https://YOUR_API";
(function (d) {
if (d.getElementById('plg-embed')) return;
var s = d.createElement('script');
s.id = 'plg-embed';
s.async = true;
s.charset = 'utf-8';
s.crossOrigin = 'anonymous';
s.src = window.PLG_SERVER + '/widget/l.js';
d.head.appendChild(s);
})(document);
</script>Согласие (152-ФЗ, GDPR, CMP)
По умолчанию режим auto: аналитика включена сразу. Виджет открывает presence-сокет при загрузке страницы и отправляет адрес страницы, заголовок, referrer и UTM-метки, а идентификатор посетителя пишется в localStorage — до того, как посетитель что-либо нажал.
Нужен CMP-first — поставьте window.PLG_CONSENT = 'needed'. Тогда до согласия не открывается сокет и не пишется localStorage (идентификатор живёт в sessionStorage до закрытия вкладки). Кнопка виджета при этом видна: открытие чата — функциональное действие, диалог начнётся в любом режиме.
window.PLG_CONSENT = 'needed'; // до загрузки сниппета
plg('consent', 'granted'); // после принятия cookies
plg('identify', { name: 'Иван', email: 'ivan@site.ru' });
plg('open');Разрешается сверху вниз, до первого совпадения: denied в конфиге сайта → Global Privacy Control или DNT=1 → сохранённый ответ посетителя (ключ plg_consent:<workspaceId>, свой на каждый воркспейс) → режим. Поэтому сайт, переключившийся на denied, действует и на старых посетителей, а GPC отзывает согласие, выданное в прошлый визит.
Presence отключается и отдельно от согласия: data-presence="0" на сниппете либо «Отслеживать посетителей» у канала.
CSP
Добавьте origin API в директивы сайта:
script-src https://YOUR_API 'unsafe-inline'; style-src 'unsafe-inline'; connect-src https://YOUR_API wss://YOUR_API; img-src https://YOUR_API;
script-src 'unsafe-inline'— рекомендуемый сниппет сам является инлайновым<script>. Если инлайн запрещён, поставьте на негоnonceили возьмите старый однострочный тег сsrc.style-src 'unsafe-inline'нужен: виджет вставляет<style>в свой Shadow DOM, а CSP проверяет стиль в момент вставки — теневое дерево от проверки не освобождает. Без разрешения виджет отрендерится без стилей.nonceзаменяет оба'unsafe-inline': поставьте его на тег сниппета — загрузчик перенесёт nonce наwidget.js, а виджет на свой<style>. Сscript-src 'nonce-…'без'strict-dynamic'nonce на сниппете обязателен, иначеwidget.jsзаблокируется.
Свой домен (first-party, AdGuard)
На nginx сайта заказчика проксируйте наш виджет на свой путь — блокировщики не режут first-party:
location /plg/ {
proxy_pass https://YOUR_API/widget/;
proxy_ssl_server_name on;
}
# затем:
# window.PLG_SERVER = location.origin + '/plg';
# s.src = location.origin + '/plg/l.js';Тильда / Bitrix / WordPress / GTM
- Тильда: Настройки сайта → Ещё → HTML-код для вставки в body, не в head-счётчики.
- Bitrix: Настройки → Настройки продукта → Настройки модулей → Главный модуль → Дополнительно, или через GTM.
- WordPress: плагин «Insert Headers and Footers» / аналог, вставка перед
</body>. - GTM: тег Custom HTML, trigger All Pages. ID и сервер задаются через
window.PLG_*, не через data-атрибуты.
Старый однострочный widget.js с data-workspace-id по-прежнему работает. Новый сниппет выдаётся в онбординге и на странице каналов.