Виджеты для сайта
Встраивайте голосового агента на любой сайт, чтобы посетители могли начать голосовой разговор прямо из браузера. Вкладка Widgets предоставляет embed-коды, опции кастомизации и настройки безопасности доменов.
Callback Widget работает совсем иначе, чем виджеты на этой странице — вместо старта голосового звонка в браузере он собирает телефонный номер посетителя, и ваш агент сам перезванивает. См. отдельную страницу Callback Widget.
Типы виджетов
Hanc.AI предлагает четыре типа браузерных виджетов плюс отдельный Callback Widget для телефонных callback:
| Виджет | Имя тега | Описание | Лучше всего для |
|---|---|---|---|
| Floating Widget | hanc-ai-floating-call | Orb-кнопка, плавающая над вашей страницей | Всегда видимый призыв к действию |
| Pill Widget | hanc-ai-pill-call | Компактная пилюлевидная кнопка, размещённая inline в вашем контенте | Минимальный footprint внутри существующего макета |
| Pill Floating Widget | hanc-ai-pill-floating-call | Та же компактная форма pill, что и у Pill, но плавает со страницей, как виджет Floating | Когда нужна эстетика pill, следующая за посетителем при скролле |
| Inline Widget | hanc-ai-inline-call | Полноразмерная кнопка вызова, встроенная в контент страницы | Выделенные секции «Поговорить с нами» |
| Callback Widget | hanc-ai-callback | Форма для номера телефона; агент перезванивает посетителю | Лидген-страницы, high-intent лендинги — см. Callback Widget |
Общие атрибуты
Все типы виджетов поддерживают эти ключевые атрибуты:
| Атрибут | Обязательно | Описание | По умолчанию |
|---|---|---|---|
agent-id | Да | Уникальный идентификатор агента | — |
voice-service-url | Нет | Переопределить URL голосового сервиса | Автоопределение |
api-base-url | Нет | Переопределить базовый URL API | Автоопределение |
Атрибуты отображения
| Атрибут | Описание | Значения | По умолчанию |
|---|---|---|---|
position | Позиция виджета на странице | bottom-right, bottom-left, top-right, top-left, static | bottom-right |
size | Размер виджета в пикселях | Число | 120 |
theme | Имя цветовой темы | См. Цветовые темы | default |
Атрибуты текста кнопки
| Атрибут | Описание | По умолчанию |
|---|---|---|
button-start-text | Текст на бездействующей кнопке | "Call" |
button-connecting-text | Текст при соединении | "Connecting..." |
button-end-text | Текст во время активного звонка | — |
Атрибуты Terms
| Атрибут | Описание | По умолчанию |
|---|---|---|
terms-enabled | Включить диалог согласия до звонка | false |
terms-content | Markdown-форматированный текст согласия | "" |
terms-url | Ссылка на вашу страницу Terms & Conditions | "https://hanc.ai/terms" |
privacy-url | Ссылка на вашу страницу Privacy Policy | "https://hanc.ai/privacy" |
Terms-атрибуты, заданные на HTML-элементе, переопределяются настройками виджета агента, полученными из API, если только skip-fetch не выставлен в true.
Атрибуты звука
| Атрибут | Описание | По умолчанию |
|---|---|---|
sound-enabled | Включить звуки старта/окончания звонка | true |
sound-volume | Громкость звуковых эффектов | 0.25 |
sound-preset | Идентификатор пресета звука | "1" |
Цветовые темы
Кастомизируйте внешний вид виджета с помощью 11 встроенных цветовых тем:
| Тема | Значение |
|---|---|
| Default | default |
| Purple | purple |
| Blue | blue |
| Cyan | cyan |
| Emerald | emerald |
| Amber | amber |
| Tangerine | tangerine |
| Rose | rose |
| Ember | ember |
| Black | black |
| White | white |
У каждой темы есть тёмный и светлый варианты. Задайте тему через атрибут theme в embed-коде или сконфигурируйте её в настройках виджета агента.
Примеры встраивания
Floating Widget
<hanc-ai-floating-call agent-id="YOUR_AGENT_ID"></hanc-ai-floating-call>
<script src="https://unpkg.com/hanc-webrtc-widgets" async type="text/javascript"></script>
Floating Widget с темой и позицией
<hanc-ai-floating-call
agent-id="YOUR_AGENT_ID"
theme="emerald"
position="bottom-left"
size="140"
></hanc-ai-floating-call>
<script src="https://unpkg.com/hanc-webrtc-widgets" async type="text/javascript"></script>
Pill Widget
<hanc-ai-pill-call agent-id="YOUR_AGENT_ID"></hanc-ai-pill-call>
<script src="https://unpkg.com/hanc-webrtc-widgets" async type="text/javascript"></script>
Inline Widget
<hanc-ai-inline-call agent-id="YOUR_AGENT_ID"></hanc-ai-inline-call>
<script src="https://unpkg.com/hanc-webrtc-widgets" async type="text/javascript"></script>
URL скрипта выше всегда грузит последнюю выпущенную версию виджета — ваш сайт автоматически подхватывает улучшения, а @latest используется по умолчанию, когда версия не указана. Если нужно зафиксировать конкретный релиз, закрепите его явно, добавив нужную версию, например https://unpkg.com/hanc-webrtc-widgets@X.Y.Z.
События виджета
Виджеты генерируют события, которые можно слушать в JavaScript:
| Событие | Описание |
|---|---|
status-changed | Срабатывает при смене статуса звонка |
connecting | Звонок устанавливается |
connected | Звонок активен |
idle | Нет активного звонка |
error | Произошла ошибка |
audio-track | Получен удалённый аудиотрек (для визуализации) |
local-audio-track | Локальный аудиотрек микрофона (для визуализации) |
microphone-enabled | Микрофон был включён |
microphone-disabled | Микрофон был выключен |
call-start | Срабатывает при успешном старте звонка |
call-end | Срабатывает при завершении звонка |
Пример: слушаем события
const widget = document.querySelector('hanc-ai-floating-call');
widget.addEventListener('call-start', () => {
console.log('Call started');
});
widget.addEventListener('call-end', () => {
console.log('Call ended');
});
Как разрешить агенту открывать страницы
Во время звонка из браузера агент может попросить ваш сайт открыть страницу — «давайте покажу тарифы» — и посетитель видит это, не прерывая разговор.
Решение остаётся за вашей страницей. Агент присылает запрос, ваш код решает, что он означает. Открыть адрес, переключить вкладку, прокрутить к разделу и раскрыть аккордеон — всё это допустимые ответы.
Нужны три шага, и по отдельности ни один не работает.
Шаг 1 — Скажите агенту, какие страницы есть
Агент не видит карту вашего сайта. Он просит только тот путь, который вы ему дали, — перечислите их в промпте агента или в базе знаний:
Страницы сайта:
/pricing — тарифы и цены
/contact — форма связи и телефон
/product/crm — CRM
Пропустите этот шаг — и агенту нечего просить, он просто не попытается.
Шаг 2 — Обработайте запрос на своей странице
Добавьте это один раз, где угодно после скрипта виджета. Событие всплывает по документу, так что document — подходящее место:
<script>
document.addEventListener('agent-command', (event) => {
const { type, payload } = event.detail;
if (type === 'navigate') {
// SPA: переход без перезагрузки — звонок продолжается.
router.push(payload.path);
// Обычный сайт: открыть вторую вкладку, эта (и звонок) останется жива.
// window.open(payload.path, '_blank');
event.preventDefault(); // ← это и говорит агенту «принято»
}
});
</script>
Звонок живёт в этой странице. window.location.href = … выгружает документ, и разговор уходит вместе с ним — посетителя обрывает на полуслове. Если есть роутер, переходите без перезагрузки; иначе открывайте страницу в новой вкладке. Переподключения нет: перезагрузку не переживает ничто.
preventDefault() обязателенЭто единственный способ сказать «я обработал». Без него агенту сообщат, что сайт не поддерживает навигацию: он перестанет пытаться до конца звонка и вернётся к объяснениям, куда нажать. В консоли ничего не появится — страница просто выглядит так, будто проигнорировала запрос, потому что так и есть.
Шаг 3 — Проверьте
Позвоните своему агенту с сайта и попросите открыть страницу по названию. Должно произойти два события: страница открылась, и агент сказал что-то вроде «вот цены», а не «найдите их в меню».
Как отвечать агенту данными
Некоторые команды — это вопросы, а не указания. Приходят они так же, но отвечать нужно через respond():
| Команда | О чём спрашивает агент | Чем отвечаете |
|---|---|---|
navigate | «открой этот путь» | ничем — достаточно preventDefault() |
page_context | «что сейчас перед посетителем?» | чем угодно полезным: путь, заголовок, товар |
cart_state | «что у него в корзине?» | позиции, суммы, валюта |
<script>
document.addEventListener('agent-command', (event) => {
const { type, respond } = event.detail;
if (type === 'page_context') {
event.preventDefault();
respond({ path: location.pathname, title: document.title });
}
});
</script>
На ответ после preventDefault() есть около секунды, так что await допустим, а медленный запрос к API — нет. Отвечайте тем, что уже под рукой.
Что агент может просить, а что нет
- Только пути внутри вашего сайта. Путь обязан начинаться с
/. Всё, что уводит с домена —//evil.com,https://…, обратные слэши — отсекается до того, как дойдёт до страницы. Увести посетителя на чужой сайт агент не может. - Только звонки из браузера. На телефонном звонке открывать нечего, поэтому там таких команд нет.
- Одного отказа достаточно. Если страница не подтвердила первый запрос, агент перестаёт спрашивать до конца звонка. Он не будет пытаться снова и — что важнее — не скажет посетителю, что открыл то, чего не открывал.
Выводите каждую команду до того, как фильтруете: document.addEventListener('agent-command', e => console.log(e.detail)). Видите в консоли navigate — агент свою часть сделал, значит дело в preventDefault() или в вашем обработчике. Не видите ничего — агенту не сказали, что такой путь существует; вернитесь к шагу 1.
Технические требования
Виджеты требуют, чтобы браузер посетителя поддерживал:
- WebGL 2.0 — для отрисовки
- Web Audio API — для обработки звука
- WebRTC — для реал-тайм голосовой связи
Все современные браузеры (Chrome, Firefox, Safari, Edge) поддерживают эти технологии.
Ограничения доменов
Контролируйте, какие сайты могут встраивать виджет вашего агента.
Всегда разрешённые домены
Следующие домены всегда разрешены, независимо от конфигурации:
hanc.ai(и поддомены)hanc.me(и поддомены)localhost
Allow All Domains
По умолчанию ваш виджет можно встраивать на любой сайт. Переключите «Allow all domains» в настройках виджета, чтобы ограничить это.
Ограничение конкретными доменами
При ограничении добавьте каждый домен, которому должно быть разрешено встраивание:
- Вводите имена доменов без
https://(например,example.com) - Поддомены нужно добавлять отдельными записями (например,
www.example.com,shop.example.com) - Порты можно указывать (например,
localhost:3000) - Максимум 50 доменов можно добавить в whitelist
Для продакшен-агентов ограничивайте виджеты своими собственными доменами, чтобы предотвратить несанкционированное встраивание.
Terms & Conditions
Включите диалог согласия до того, как звонящие смогут начать разговор.
Конфигурация
| Настройка | Описание |
|---|---|
| Enable Terms | Переключатель диалога terms |
| Terms Content | Markdown-форматированный текст согласия, показываемый пользователям (макс. 5000 символов) |
| Terms URL | Ссылка на вашу полную страницу Terms & Conditions |
| Privacy URL | Ссылка на вашу страницу Privacy Policy |
Когда включено:
- Пользователи видят диалог согласия до старта звонка
- Они должны нажать «Agree», чтобы продолжить
- Согласие хранится локально в браузере
- Кнопка Reset Consent очищает сохранённое согласие для тестирования
Форматирование контента
Контент terms поддерживает форматирование Markdown:
- Используйте
####для заголовков - Используйте
**bold**для акцента - Используйте переводы строк для читаемости
Связанное
- Callback Widget — телефонные обратные звонки для посетителей, которым не хочется говорить в браузере
- Обзор голосовых агентов
- Settings — настройки агента, включая конфигурацию виджета
- Интеграции — API-ключи и настройка телефонных номеров