Методы виджета
После подключения скрипта виджет публикует глобальный объект window.apxChat для управления чатом из кода страницы. Метод init() доступен сразу, остальные — после монтирования React-компонента.
Подключение
<script src="https://cdn.apx.chat/static/widget.js" async></script>
<script>
window.addEventListener('load', function () {
window.apxChat.init('ВАШ_ТОКЕН');
});
</script>Два разных токена
Часто путают токен в init() и токен в setToken() — это разные вещи с разным назначением:
| Метод | Что за токен | Для чего |
|---|---|---|
init(token) | Токен виджета | Идентифицирует, какой виджет загружать (его настройки, операторы, дизайн) |
setToken(token) | Токен вашего пользователя | Даёт AI-оператору доступ к вашему API от имени этого пользователя |
init(token, client?, options?)
Первичная инициализация виджета. Делает HTTP-запрос на сервер, получает конфиг (тема, дизайн, аналитика, операторы), создаёт DOM-контейнер #apx-chat-root и монтирует в него React-приложение.
| Параметр | Тип | Обяз. | Описание |
|---|---|---|---|
token | string | да | Токен виджета из админ-панели. Идентифицирует, какой именно виджет загружать |
client | string | нет | Ваш внутренний ID пользователя сайта. Значение приходит со страницы и ничем не подтверждено, поэтому для авторизации не используется — если нужен идентификатор, которому можно доверять, см. подписанную личность |
options.proxyApiUrl | string | нет | Подмена MAIN_URL / API_URL / SOCKET_URL. См. Proxy виджета |
options.proxyWidgetUrl | string | нет | Подмена WIDGET_URL |
window.apxChat.init(
'1430a564bc7ccfeb0093d2302548a0fb',
'user-42',
{
proxyApiUrl: 'https://yourdomain.com/chat-api',
proxyWidgetUrl: 'https://yourdomain.com/chat-widget',
},
);open()
Открывает окно чата. Полезно, когда нужно открыть чат по своей кнопке на сайте (например, «Связаться с нами» в шапке), а не только по дефолтной круглой кнопке виджета.
document.getElementById('support-btn').onclick = () => window.apxChat.open();close()
Закрывает окно чата.
window.apxChat.close();toggle()
Переключает состояние чата (открыт ↔ закрыт).
window.apxChat.toggle();changeTheme(theme)
Переключает тему оформления виджета. Полезно для синхронизации с темой вашего сайта. Невалидное значение игнорируется с предупреждением в консоли. Вызывать можно и до init(), и сразу после него: тема применится, как только виджет загрузится.
Надолго выбор сохраняется, только если в настройках канала тема не задана. Выбор записывается в localStorage, но тема канала главнее: если она задана, при следующей загрузке страницы виджет снова откроется в ней. Новые веб-каналы создаются со светлой темой. Поэтому, чтобы тема виджета совпадала с темой сайта, вызывайте changeTheme при каждой загрузке страницы и при переключении темы на сайте.
| Параметр | Тип | Описание |
|---|---|---|
theme | 'light' | 'dark' | Целевая тема |
// у вас на сайте переключили тёмную тему — синхронизируем виджет
window.apxChat.changeTheme('dark');setToken(token)
Передаёт токен вашего пользователя AI-оператору, чтобы тот мог дёргать ваше API от его имени. Не путать с init(token) — здесь токен идентифицирует клиента на вашем сайте, а не виджет.
Зачем это нужно
В админ-панели для AI-оператора можно настроить API-интеграции — список endpoint'ов вашего бэкенда (заказы, профиль, баланс и т.д.), которые AI вызывает как tools во время диалога. У каждого endpoint есть флаг useUserToken:
useUserToken: false— AI вызывает endpoint без авторизации (публичные данные).useUserToken: true— сервер берёт токен, сохранённый черезsetToken(), и подставляет его в заголовокAuthorizationпри вызове.
Так AI «понимает», от чьего имени делать запросы:
Клиент: «Где мой заказ?» AI вызывает
GET https://yourshop.com/api/ordersсAuthorization: Bearer <user_jwt>Ваш бэкенд возвращает заказы конкретно этого пользователя AI отвечает: «Заказ #1234 в пути, прибудет завтра»
Сервер подставляет токен в заголовок Authorization: <prefix> <token> при вызове ручки — префикс настраивается в интеграции, по умолчанию Bearer.
Без setToken() AI имеет доступ только к публичным/анонимным endpoint'ам и не может работать с персональными данными.
| Параметр | Тип | Описание |
|---|---|---|
token | string | JWT или любой токен вашего бэкенда, по которому он умеет авторизовать пользователя |
Метод можно вызывать в любой момент, в том числе до того, как виджет закончил загрузку — вызов не потеряется.
// после логина у вас на сайте
window.apxChat.setToken(myJwtFromBackend);Жизненный цикл токена
| Что происходит | Что с токеном |
|---|---|
вызвали setToken(token) | сохраняется на сервере в зашифрованном виде |
| закрылась последняя вкладка с чатом | удаляется сразу |
| закрылась одна из нескольких вкладок | сохраняется, пока открыта хотя бы одна |
вызвали clearToken() | удаляется сразу |
| ничего из перечисленного (например, обрыв связи) | удаляется автоматически не позже чем через 24 часа |
| виджет переподключился | переотправляется автоматически, вызывать setToken заново не нужно |
Что гарантируется
- Токен хранится только в оперативной памяти браузера и в зашифрованном виде на нашем сервере. В
localStorageон не попадает. - Его не видит ни оператор в чате, ни AI-модель: заголовок
Authorizationформируется на сервере в момент вызова, модель не может его прочитать или переслать. - Он уходит только на те адреса, которые вы сами прописали в API-интеграции. Переадресации при вызове ваших ручек запрещены — токен не может «уехать» на сторонний домен по редиректу.
Не передавайте основной JWT вашего пользователя. Выпускайте для чата отдельный токен с
коротким сроком жизни и доступом только к тем ручкам, которые нужны AI. Если авторизация на
сайте построена на httpOnly-куках, setToken вам не подойдёт в принципе — JS не может
прочитать такую куку; используйте подписанную личность.
clearToken()
Отзывает токен пользователя. Вызывайте при выходе из аккаунта на вашем сайте — иначе AI сможет обращаться к вашему API от имени этого пользователя, пока открыта вкладка.
// пользователь разлогинился у вас на сайте
window.apxChat.clearToken();setIdentity(identity) / clearIdentity()
Альтернатива setToken() для тех, кто не хочет отдавать токены пользователей. Ваш бэкенд подписывает идентификатор пользователя, а мы передаём его в ваше API вместе с подписью запроса — самого токена у нас не существует. Работает при авторизации через httpOnly-куки.
Полное описание, включая формат подписи и проверку на вашей стороне — Подписанная личность.
window.apxChat.setIdentity(identityJwtFromBackend);
window.apxChat.clearIdentity(); // при выходе из аккаунтаpopup.toggle(uuid?)
Открывает и закрывает попап — маркетинговое всплывающее окно с формой, ссылкой, товарами или игрой (не путать с чатом). Попапы настраиваются в кабинете в разделе «Маркетинг → Попап» и показываются сами по условиям показа, а метод управляет ими из кода сайта.
| Параметр | Тип | Описание |
|---|---|---|
uuid | string (опц.) | UUID попапа. Если этот попап на экране — закрывает его, если на экране другой — показывает этот вместо него. Без аргумента закрывает показанный попап, а если на экране ничего нет — открывает первый подходящий попап сайта: сначала с триггером «Вручную (через JS API)», затем по приоритету |
Готовый вызов с UUID и кнопкой копирования есть в редакторе попапа на шаге «Условия показа», если выбрать «Вручную (через JS API)».
Вызывать метод можно сразу после init(), не дожидаясь загрузки виджета: пока виджет загружает попапы, вызовы ждут и потом выполняются по порядку — до 10 вызовов popup.toggle() и stories.open() вместе.
Метод учитывает частоту, условия показа, расписание и сроки публикации: если попап сейчас показывать нельзя, вызов ничего не делает. Пауза между автопоказами на вызов из кода не действует. Истории без uuid метод не открывает — для них есть stories.open().
Внутри просто диспатчит CustomEvent('apx-popup-toggle') — можно делать то же самое напрямую без обёртки.
window.apxChat.popup.toggle();
window.apxChat.popup.toggle('a3f7c2e1-...');Событие apx-popup-toggle
Кастомное событие на window. Виджет слушает его и переключает попап. Можно диспатчить вручную — без обёртки popup.toggle().
window.dispatchEvent(
new CustomEvent('apx-popup-toggle', {
detail: { uuid: 'a3f7c2e1-...' },
}),
);| Поле detail | Тип | Описание |
|---|---|---|
uuid | string (опц.) | UUID попапа — работает так же, как аргумент popup.toggle(uuid) |
stories.open(popupId?, storyId?)
Открывает плеер интерактивных историй — так же, как если бы посетитель нажал на кружок или карточку историй. Нужен, когда у историй выбран вход «Без лаунчера» или вы хотите открывать их своей кнопкой на сайте.
| Параметр | Тип | Описание |
|---|---|---|
popupId | string (опц.) | UUID попапа историй — виден в адресе его редактора в кабинете, после /dashboard/popup/. Без аргумента открываются первые по приоритету истории сайта |
storyId | string (опц.) | ID истории (кружка) в этом попапе, с которой начать показ. Без него — с первой истории, а если включено «Начинать с того, что посетитель ещё не видел» — с первой непросмотренной. Неизвестный ID — показ с первой истории |
Готовый вызов с UUID и кнопкой копирования есть у сохранённых историй в редакторе: на шаге «Условия показа», в блоке «Открыть истории из кода сайта», а при входе «Без лаунчера» — ещё и на вкладке «Вход в истории». Выбирать «Вручную (через JS API)» и включать автопоказ для вызова не нужно. ID истории с кнопкой копирования указан под её заголовком на вкладке «Истории и слайды».
Вызывать метод можно сразу после init(), как и popup.toggle(): пока виджет загружает истории, вызов ждёт и выполняется, как только они загрузятся.
Это действие посетителя: частота, условия показа и расписание не проверяются, учитываются только сроки публикации. Если на экране уже есть попап или другие истории, они закроются — одновременно показывается только одно окно.
Если открыть истории нельзя, вызов ничего не делает и не пишет ошибок в консоль. Так бывает, когда:
- в UUID опечатка;
- истории выключены или для них не выбран этот сайт;
- срок публикации ещё не начался или уже закончился;
- ни один слайд ещё не готов к показу — фото и видео обрабатываются;
- истории недоступны вашей организации.
Без popupId вызов ничего не делает, если на сайте нет ни одних историй.
document
.getElementById('stories-btn')
.addEventListener('click', () => window.apxChat.stories.open('b91d4c7a-...'));
// сразу с нужной истории
window.apxChat.stories.open('b91d4c7a-...', 'ID_ИСТОРИИ');booking.open(options?)
Открывает онлайн-запись в окне виджета — на вкладке «Запись», поверх любого экрана: стартового, FAQ, формы или звонка. Нужен, чтобы записывать клиентов своей кнопкой на сайте, например «Записаться» в карточке услуги. Работает на сайтах с виджетом канала, у которого включена онлайн-запись.
Поле options | Тип | Описание |
|---|---|---|
branchId | string (опц.) | ID филиала, с которого начать запись |
serviceId | string (опц.) | ID услуги |
specialistId | string (опц.) | ID специалиста |
Без аргументов запись открывается с начала: предвыбор предыдущего вызова сбрасывается. С options клиент начинает запись с заданного выбора — можно передать одно поле или несколько. Поля, которые вы не передали, берутся из значений по умолчанию в настройках канала, если они там заданы. Если филиал, услуга или специалист не найдены или не связаны между собой (специалист не работает в этом филиале, услугу там не оказывают), виджет пишет в консоль ApxChat: booking.open — филиал, услуга или специалист не найдены и оставляет только ту часть выбора, которая подходит.
Готовый вызов с кнопкой копирования есть в кабинете: в настройках канала сайта, в блоке «Онлайн-запись» → «Открыть запись своей кнопкой» (там же можно выбрать филиал, услугу и специалиста из каталога), и в «Онлайн-запись → Настройки» рядом со ссылкой на публичную страницу.
Вызывать метод можно сразу после init(), не дожидаясь загрузки виджета: вызов подождёт и выполнится, когда виджет загрузится.
Если запись на канале выключена, вызов ничего не открывает и пишет в консоль предупреждение ApxChat: онлайн-запись выключена на канале. Так же — пока запись не опубликована в кабинете («Онлайн-запись → Настройки»).
В режиме «только запись» — когда в канале выключен чат, а запись включена, — кнопка виджета открывает запись, а open() и toggle() ничего не делают и пишут ApxChat: чат выключен на канале. Открывать окно из кода в этом режиме нужно через booking.open().
Во время диалога вызов работает как стрелка «Назад»: окно переходит на стартовый экран с вкладкой «Запись», а переписка не теряется — клиент может вернуться в диалог после записи.
Каждый вызов начинает новую запись. Если клиент уже записался и видит подтверждение, кнопка виджета и вкладка «Запись» показывают это подтверждение, а booking.open() — новую запись.
// запись с начала
window.apxChat.booking.open();
// сразу с нужной услуги в нужном филиале
window.apxChat.booking.open({
branchId: 'ID_ФИЛИАЛА',
serviceId: 'ID_УСЛУГИ',
});Если скрипт виджета загружается позже кнопок, можно ставить вызовы в очередь через глобальную функцию APX — вызовы booking.open из неё выполнятся, когда загрузится виджет канала с записью:
<script>
window.APX = window.APX || function () { (APX.q = APX.q || []).push(arguments); };
</script>
<button onclick="APX('booking.open', { serviceId: 'ID_УСЛУГИ' })">Записаться</button>Примеры
Кнопка «Записаться» на странице услуги
<button id="book-haircut" type="button">Записаться</button>
<script>
document.getElementById('book-haircut').addEventListener('click', () => {
window.apxChat.booking.open({ serviceId: 'ID_УСЛУГИ' });
});
</script>Открыть чат по клику на свою кнопку
document
.getElementById('support-btn')
.addEventListener('click', () => window.apxChat.open());Дать AI-оператору доступ к данным залогиненного пользователя
window.apxChat.init('ВАШ_ТОКЕН', 'user-42');
// JWT вашего пользователя — AI будет ходить с ним в API-интеграции,
// у которых в админке включён флаг useUserToken
window.apxChat.setToken(jwt);Синхронизация темы с сайтом
const syncTheme = () => {
const theme = document.documentElement.dataset.theme; // 'light' | 'dark'
window.apxChat.changeTheme(theme);
};
// При каждой загрузке страницы: иначе после перезагрузки вернётся тема из настроек канала
syncTheme();
// И при каждом переключении темы на сайте
new MutationObserver(syncTheme).observe(document.documentElement, {
attributes: true,
attributeFilter: ['data-theme'],
});