Встраивание чат-виджета на базе знаний с захватом лидов
Практическое руководство по встраиванию Simmetric Chat на ваш сайт: sandboxed iframe-loader, model pin, разрешаемый на сервере, захват лидов и настройка CORS.
Превратите документацию в ассистента на входе
В вашей базе знаний уже есть ответы, которые ищут посетители. Встроенный чат-виджет выводит эти ответы на ваш сайт как разговорную входную дверь: посетители задают вопросы, виджет выполняет тот же гибридный RAG-конвейер и ту же агентную инфраструктуру, которой пользуются ваши внутренние команды, а ответы приходят с цитатами из тех workspaces, которые вы решили открыть. Это руководство проходит по встраиванию виджета, контролю над тем, что он отвечает, захвату лидов и правильной настройке CORS - от админ-панели до работающего сниппета за несколько минут.
Двухшаговый embed: loader и sandboxed iframe
Виджет построен вокруг ориентированного на безопасность embed-паттерна. Вместо инъекции markup и стилей в вашу страницу виджет приходит в два шага:
- Скрипт-loader. Добавьте на сайт один тег script, указывающий на ваш widget-сервис с ID виджета. Loader - небольшой JavaScript-файл, создающий iframe на хост-странице.
- Панель iframe. Iframe загружает автономное приложение Preact - собранное как IIFE-бандл с инлайн-CSS, - которое рисует плавающую кнопку, панель чата и всё взаимодействие внутри собственного документа.
<script src="https://ваш-simmetric-chat.com/widget/loader.js?widgetId=WIDGET_ID"></script>Почему iframe? Потому что интерполяция строк недоверенного контента в хост-страницу - классический путь XSS. Запуск интерфейса виджета в sandboxed iframe с opaque origin полностью устраняет этот класс риска: содержимое чата никогда не выполняется в контексте вашей страницы. Старые embed-пути через интерполяцию строк были удалены из продукта именно поэтому, так что двухшаговый паттерн не опция среди прочих - это сам embed.
Связь между iframe и страницей идёт через небольшой версионированный протокол postMessage (типы сообщений simmetric:*), который обслуживает открытие/закрытие FAB, перекраску FAB и handshake'и хранилища сессий. Обе стороны валидируют каждое входящее сообщение против точного ожидаемого contentWindow, так что поддельные сообщения между разными iframe'ами игнорируются.
Создать виджет и направить его на знания
Всё начинается в админ-панели:
- Создайте виджет в Настройки → Виджеты. Создание привязано к лицензии (
widget_enabled) и соблюдает числовой лимит виджетов тарифа. - Привяжите виджет к одному или нескольким workspaces. Whitelist workspaces атомарно заменяет все предыдущие привязки, поэтому расслоение доступа к базе знаний - это вопрос того, какие workspaces прикрепить.
- Настройте брендинг: основной цвет, имя бота, логотипы, позиция (справа внизу или слева внизу). Развёртывания уровня Community получают разумные значения по умолчанию при пустых полях; полная кастомизация и white-labeling - enterprise-флаги.
- Скопируйте embed-сниппет в HTML вашего сайта.
Поскольку виджеты определены на workspace, знание, из которого виджет может черпать, - ровно объединение баз знаний привязанных workspaces. Support-виджет может видеть публичный документационный workspace, никогда не касаясь данных внутренних проектов.
Model pin ответов: разрешается на сервере
Недавнее добавление важно для контроля качества: конфигурация каждого виджета может выбирать конкретный LLM-провайдер и модель, обслуживающие чат-ответы этого виджета. Pin хранится в строке виджета и разрешается на сервере при каждом запросе чата - он никогда не приходит от клиента, прокси виджета или браузера посетителя. Модель с pin имеет приоритет над значением по умолчанию workspace, а виджеты без pin сохраняют стандартную цепочку разрешения. На практике: ваш маркетинговый виджет может работать на той самой модели, которую вы проверили для публичных ответов, независимо от того, что кто-то подменит на стороне клиента.
Захват лидов, уважающий посетителей
Захват лидов в виджете спроектирован под реальность публичной формы: абьюз концентрируется там, где собираются данные, поэтому lead-эндпоинт намеренно ограничен 3 запросами в час на источник (лимит виден пользователю). Поток:
- Посетитель видит барьер согласия на персональные данные до чата - явное признание того, как обрабатываются данные, а не спрятанная внизу ссылка на политику.
- Lead-карточка собирает контактные данные во время или после разговора, и отправки попадают в почтовый ящик лидов виджета в админ-панели, с CSV-экспортом для вашего конвейера.
- Сессии анонимны по решению дизайна: сервер создаёт сессию с 256-битным токеном и сроком 24 часа, и каждый последующий запрос валидируется против неё. Лимиты на сессию (20 сообщений в час, 5 разговоров в день) при превышении возвращают
429с подсказкойretryAfter, и интерфейс показывает предупреждение о лимите вместо молчаливого отказа.
Rate limit'ы - часть истории доверия, а не запоздалая мысль: публичная чат-поверхность должна изящно деградировать под нагрузкой или абьюзом, и lead-лимитер - самый узкий из трёх лимитеров на стороне виджета.
CORS: закрыт по умолчанию by design
Widget-трафик пересекает источники по определению, поэтому CORS - часть поверхности безопасности, а не запоздалая мысль. Каждый виджет несёт собственный список allowedOrigins, редактируемый из админ-панели. В рантайме динамический CORS-middleware валидирует заголовок Origin каждого запроса против списка этого виджета: запросы с неразрешённых источников отклоняются уже на preflight, а middleware падает fail-closed: если проверка источника не может обратиться к базе, доступ запрещается, а не разрешается.
Настройте в один проход:
- Добавьте источники вашего сайта (схема и хост, без игр с завершающим слэшем) в разрешённые источники виджета.
- Помните, что варианты поддомена считаются отдельными источниками:
example.comиwww.example.com- две записи. - Используйте
https://-источники в продакшене; widget-сервис говорит по тем же URL-правилам, что и остальной стек.
Всё остальное - URL loader'а, iframe, bootstrap сессии, SSE-поток чата - использует тот же хост, на котором вы разворачиваете widget-сервис, поэтому есть ровно одно место, где решается доверие к источнику: разрешённый список виджета.
Что где работает
Быстрая карта ориентации, потому что виджет затрагивает три процесса:
- Основной сервер - CRUD и брендинг виджетов, привязка workspaces, внутренний API, который widget-сервис вызывает своим API-ключом, и lead/analytics-эндпоинты для администраторов. Весь внутренний роутер возвращает
402, когда фича виджетов выключена. - Widget-сервис - публичная embed-поверхность: JS-loader, HTML iframe, создание сессий, выдача кэшированной конфигурации, SSE-прокси чата к основному серверу и lead-эндпоинт. Он аутентифицируется на основном сервере
WIDGET_API_KEYи несёт собственные лимитеры частоты. - Iframe - IIFE-клиент Preact с жизненным циклом чата: создание сессии, SSE-стриминг токен за токеном, отображение цитат, предложенные вопросы и барьеры согласия.
Прокси чата пересылает тот же формат событий, что и внутренний streaming API - статусные сообщения, анонсы плана, потоковые токены, цитаты и терминальные события done/error, - так что всё, что ваша команда видит в workspace-чате, посетители испытывают в виджете.
Чек-лист запуска
- Виджет создан, лицензионная фича активна, workspaces привязаны
- Брендинг настроен; white-label-флаг, если виджет не должен нести марку продукта
- Model pin ответов задан в строке виджета (разрешается на сервере)
- Разрешённые источники покрывают каждый сайт и поддомен, который будет его встраивать
- Захват лидов проверен end-to-end: барьер согласия, отправка, админ-ящик, CSV-экспорт
- Rate limit'ы поняты: 3 лида в час, 20 сообщений в час на сессию, 5 разговоров в день
Оттуда виджет - это drop-in: один тег script, один разрешённый список, одна база знаний, которой вы уже доверяете. Когда посетители задают вопросы, они получают ответы, опирающиеся ровно на выбранные вами workspaces, - с конвейером захвата лидов, вежливым к людям и строгим к ботам.

