Виджет: установка и управление со страницы

Строка вставки, настройки из кабинета, вход посетителя и домены, а также команды сайта, события, приглашение в диалог и цели для Метрики.

Строка вставки #

Скрипт ставится один раз перед </body>. Всё остальное (цвет, тексты, звук, значок, каналы) приходит с сервера по data-widget-id и меняется в кабинете без правки страницы.

Пример вызова
<script async
  src="https://api.widgetchat.ru/widget/bozex-support-widget.js"
  data-widget-id="wc_9qA…Lk"
></script>

Один виджет на страницу. Скрипт async: он не блокирует отрисовку и не ждёт загрузки страницы.

Что виджет запрашивает #

GET /widget/config/{widgetId}

Настройки вида и текстов. Ответ разрешён только доменам, объявленным в карточке сайта: чужая страница с вашим widget-id настроек не получит.

Ответ
{"widgetId": "wc_9qA…Lk", "workspaceKey": "example-ru",
 "apiUrl": "https://api.widgetchat.ru",
 "tokenUrl": "https://api.widgetchat.ru/widget/token/wc_9qA…Lk",
 "appearance": {"color": "#07aa46", "title": "Напишите нам", … }}

Вход посетителя #

GET /widget/token/{widgetId}?deviceId=…

Виджет сам получает подписанный токен окна и дальше работает им. Токен привязан к рабочему пространству сайта и живёт ограниченное время; посетитель опознаётся по устройству, поэтому история сохраняется между визитами.

Программной идентификации посетителя (передать своё имя, почту или номер клиента из кода страницы) сейчас нет. Сведения о посетителе появляются в разговоре, только если их передал сам сайт при выдаче токена на своей стороне.

Домены #

Список доменов задаётся в карточке сайта. Виджет на неуказанном домене получит отказ на запрос настроек: это защита от чужой страницы, которая поставила бы ваш widget-id себе.

Управление со страницы: команды сайта #

Виджет кладёт на страницу объект window.WidgetChat. Через него сайт открывает и закрывает окно, показывает приглашение и подписывается на события. Идентификаторы нашей разметки использовать не нужно: они внутренние и меняются.

КомандаЧто делает
WidgetChat.open()Открыть окно чата
WidgetChat.open({ message: 'текст' })Открыть и подставить заготовленный вопрос в поле ввода
WidgetChat.close()Закрыть окно
WidgetChat.toggle()Открыть или закрыть, смотря что сейчас
WidgetChat.isOpen()true, если окно открыто
WidgetChat.unreadCount()Сколько ответов посетитель не прочитал
WidgetChat.showInvite('текст')Показать приглашение в диалог прямо сейчас
WidgetChat.hideInvite()Убрать приглашение
WidgetChat.attention()Заставить кнопку звать к себе; attention(false) отменяет
WidgetChat.on('open', fn)Подписаться на событие; off снимает подписку
WidgetChat.ready(fn)Выполнить, когда виджет готов
Пример вызова
<button id="ask">Написать нам</button>
<script>
  document.getElementById('ask').addEventListener('click', function () {
    WidgetChat.open({ message: 'Вопрос по доставке' })
  })
</script>

Кнопка нажата раньше загрузки #

Файл виджета грузится асинхронно, и первые секунды объекта на странице ещё нет. Если ваша кнопка может быть нажата в это время, поставьте перед вставкой виджета заглушку с очередью: виджет разберёт её сразу после запуска и выполнит накопленные команды.

Пример вызова
<script>
  window.WidgetChat = window.WidgetChat || { q: [] };
  ['open', 'close', 'toggle', 'showInvite', 'hideInvite', 'attention'].forEach(function (name) {
    WidgetChat[name] = WidgetChat[name] || function () {
      WidgetChat.q.push([name, [].slice.call(arguments)]);
    };
  });
</script>

Команда из очереди выполняется один раз, когда окно построено. Повторять её не нужно.

События #

Каждое событие приходит двумя путями: в обработчик WidgetChat.on('имя', fn) и на window как widgetchat:имя. Второй путь удобен, когда код выполняется раньше виджета или живёт в другом скрипте.

СобытиеКогда приходитЧто внутри
readyВиджет построен и готов принимать командыversion
openОкно открыто человеком или командой сайтапусто
closeОкно закрытопусто
inviteПоказано приглашение в диалогtext
sentСообщение посетителя принято серверомfirst: первое ли оно
messageПришёл ответ поддержкиtext, from
unreadИзменилось число непрочитанных ответовcount
goalВиджет отправил цель в счётчики сайтаgoal, params
Пример вызова
window.addEventListener('widgetchat:sent', function (event) {
  if (event.detail.first) console.log('первое обращение с этой страницы')
})

Приглашение в диалог #

Через заданное время у кнопки появляется облако с текстом, а сама кнопка начинает звать к себе. Нажатие на облако открывает чат, крестик убирает его.

По умолчанию виджет молчит. Приглашение включается в кабинете на шаге Приглашение, там же задаются задержка и текст облака. Атрибуты на теге скрипта сильнее настройки кабинета: ими удобно звать раньше и другими словами на отдельной странице, например на оформлении заказа.

АтрибутЗначение
data-invite-delayЧерез сколько секунд показать приглашение. Без атрибута виджет молчит; допустимо от 1 до 300
data-invite-textТекст приглашения. Без него виджет скажет своими словами на языке посетителя
Пример вызова
<script async
  src="https://api.widgetchat.ru/widget/bozex-support-widget.js"
  data-widget-id="wc_9qA…Lk"
  data-invite-delay="15"
  data-invite-text="Подскажем по наличию и срокам"
></script>

Приглашение показывается один раз за вкладку и никогда не появляется поверх открытого чата или свежего ответа поддержки. Отказ человека запоминается на время визита; в браузер до открытия чата виджет ничего не пишет.

Цели для Метрики и Google #

Виджет сам отправляет цели в счётчики, которые уже стоят на странице: в Яндекс.Метрику через reachGoal, в Google Tag Manager через dataLayer и в gtag. Номер счётчика указывать не нужно: Метрика знает свои счётчики сама. В кабинете Метрики цель создаётся как "JavaScript-событие" с тем же идентификатором.

ЦельКогда срабатывает
widgetchat_openПосетитель открыл окно чата
widgetchat_first_messageПервое сообщение посетителя, то есть само обращение
widgetchat_messageКаждое сообщение посетителя
widgetchat_replyПоддержка ответила
widgetchat_invite_shownПоказано приглашение в диалог
widgetchat_invite_clickПриглашение приняли
widgetchat_closeОкно закрыли
Пример вызова
<script async
  src="https://api.widgetchat.ru/widget/bozex-support-widget.js"
  data-widget-id="wc_9qA…Lk"
  data-metrika-id="12345678"
  data-goals="off"
></script>

data-metrika-id нужен, только если на странице несколько счётчиков и цели должны уходить в конкретный. data-goals="off" выключает отправку целиком.