Пуш в браузере (Web Push)

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

Что этот выпуск умеет, а что нет. Можно включить браузерный пуш для бота, собрать согласия посетителей и отправить тестовое уведомление в один подписанный браузер прямо из кабинета. Отправить браузерный пуш из рассылки, кампании или реакции нельзя – единственная существующая сегодня отправка тестовая. Настраивайте и проверяйте канал сейчас, но не планируйте на нём рассылку.

Шаг 1. Установите сервис-воркер на своём домене

Без этого шага браузерный пуш физически не работает, и именно его чаще всего пропускают.

Браузерное уведомление показывает сервис-воркер, а сервис-воркер управляет только тем origin, который его отдал. Скрипт виджета загружается с нашего домена, поэтому он не может установить воркер для вашего сайта – файл нужно разместить у себя.

  1. Откройте в кабинете «Виджет» → Web Push и скачайте файл mybot-sw.js.

  2. Разместите его так, чтобы он отдавался из корня каждого origin, где работает виджет, ровно по такому пути:

    https://example.com/mybot-sw.js
    https://shop.example.com/mybot-sw.js
    

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

  3. Проверьте, что файл действительно отдаётся как JavaScript по HTTPS из корня сайта и что его не подменяет SPA-фолбэк или CDN на HTML-страницу. Ответ 404, редирект и тело index.html одинаково молча ломают регистрацию.

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

Путь важен: виджет регистрирует или переиспользует только воркер по пути /mybot-sw.js. Два публичных параметра маршрутизации (mb_key, mb_api) он подставляет сам, добавлять их вручную не нужно.

Если вы регистрируете воркер сами

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

navigator.serviceWorker.register("/mybot-sw.js?nav=https://shop.example.com");

Параметр nav – это список точных HTTPS-origin через запятую, не более 8. Воркер проверяет цель клика по своему списку и по собственному origin, независимо от серверного списка из шага 2: ни одна сторона не доверяет другой. Найдя такую регистрацию, виджет сохранит ваше значение nav, а не заменит его.

Если на сайте уже есть свой сервис-воркер

Виджет никогда не заменяет чужой сервис-воркер: замена сломала бы ваш сайт, а подписка через чужой воркер не установила бы обработчики пуша и клика. Если страницей уже управляет другой воркер, попытка подписки просто завершится как «недоступно». Разместите mybot-sw.js на сайте, где своего воркера в корневой области нет, или напишите в поддержку, прежде чем совмещать два воркера.

Шаг 2. Включите Web Push для бота

Web Push настраивается на экране «Виджет», рядом с остальным веб-каналом. Обязательных поля два:

  • Контакт VAPID – адрес mailto: или HTTPS-ссылка, по которым пуш-сервисы сообщат вам о проблемах с доставкой, например mailto:help@example.com.
  • Разрешённые ссылки уведомлений – по одному HTTPS-origin в строке. Клик по уведомлению может открыть только относительный адрес на вашем сайте или один из этих точных origin. Это обязательный ввод, а не необязательная мера защиты: уведомление со ссылкой куда-то ещё отклоняется до отправки.

При первом сохранении сервер генерирует пару ключей VAPID. Публичный ключ виден в настройках – это единственная половина, которую вообще получает браузер; приватная никогда не покидает сервер и не возвращается ни одним методом API.

Тихие часы (см. ниже) есть в API, но поля на этом экране пока нет.

Шаг 3. Соберите согласия посетителей

Согласие намеренно требует усилия, и виджет устроен так, что простая загрузка страницы не может стать подпиской:

  • Запрос разрешения браузера открывается только после явного клика посетителя по кнопке уведомлений в виджете.
  • Тот, кто ни разу не нажимал, не увидит ошибку: если браузер не поддерживает пуш или разрешение уже отклонено, элемент просто скрыт до первой попытки.
  • Загрузка виджета лишь обновляет уже выданное согласие. Она не может ни показать запрос, ни установить воркер, ни создать новую подписку.
  • Отказ сохраняется надолго и переживает перезагрузку страницы, даже если браузер держит свой объект подписки живым.

Оба действия доступны и вашему коду на странице после загрузки виджета:

await window.mybot.push.subscribe();   // покажет запрос и зарегистрирует подписку
await window.mybot.push.unsubscribe(); // отзовёт её на сервере и отпишет браузер

Подписка хранится со статусом согласия: subscribed, revoked (посетитель отписался) или expired (пуш-сервис сообщил, что адрес больше не существует). В кабинете и в API видны семейство браузера, локаль, часовой пояс, статус согласия и даты. Адрес пуш-сервиса и его ключи шифрования – серверный материал только на запись: он хранится зашифрованным и никогда не возвращается ни владельцу, ни клиенту API, ни MCP-инструменту.

Отправка

Раздел тестового уведомления отправляет одно сообщение в браузер, который подписался последним. Для этого нужны сразу три вещи:

  • включённый Web Push для бота;
  • хотя бы одна подписка в статусе subscribed;
  • один опубликованный документ типа Push в Контент-студии. Тестовая отправка ссылается на конкретную опубликованную версию – так же, как поп-ап или кампания.

Отправка асинхронная: кабинет получает идентификатор сообщения, а доставка идёт в фоне. Всё остальное, что нужно кампании – выбор аудитории, расписание, остановка, – в этом выпуске ни к какому экрану не подключено.

Ограничения содержимого уведомления

Каждое ограничение ниже – жёсткий отказ до того, как что-либо покинет сервер, а не обрезка.

ПолеОграничение
titleобязательно, 1–120 символов
bodyобязательно, 1–512 символов
tagнеобязательно, ≤128 символов
actionsне более 2; идентификатор и подпись каждого действия 1–64 символа, без повторов
icon_url, image_urlтолько HTTPS, без userinfo и якоря
navigationотносительный путь, начинающийся с /, либо один из точно разрешённых origin
dataтолько ключи action, campaign_id, content_id, experiment_id, message_id; каждое значение ≤256 символов
собранная полезная нагрузкане более 3 КиБ целиком

Ещё два правила стоит знать. Значение в data, похожее на секрет, – содержащее bearer , secret, password, token= или знак @ – отклоняется, поэтому в уведомление нельзя протащить значение профиля или токен доступа. А полезная нагрузка, которая пытается принести собственную receipt_signature, отклоняется сразу: это служебное значение сервер подставляет в момент доставки, и оно никогда не бывает контентом.

Протокол-относительная (//host/path) и «обратнослэшевая» формы ссылки считаются чужим origin, а не относительным путём, – и на сервере, и в воркере.

Тихие часы

Тихие часы – это повторяющиеся локальные интервалы, в которые доставка откладывается, а не отменяется: сообщение подождёт и уйдёт в первый разрешённый момент. Они считаются в часовом поясе получателя (записанном вместе с подпиской, с запасным вариантом – часовым поясом бота), а интервал, конец которого раньше начала, продолжается через полночь. Момент, попавший в «дыру» перевода часов, сдвигается вперёд до существующего времени, а не отбрасывается.

Тихие часы входят в конфигурацию Web Push и задаются через REST API (поле quiet_hours), но редактора в кабинете для них пока нет.

Доставка, повторы и квитанции

  • Сообщение забирает фоновый обработчик, берёт его в аренду на время доставки и повторяет попытки не более 8 раз и не дольше 24 часов – что наступит раньше.
  • Ответ 429 от пуш-сервиса повторяется по его Retry-After с потолком в 24 часа. Таймауты и ответы 5xx повторяются с разбросом задержки. Любой другой ответ 4xx терминальный.
  • Ответ 404 или 410 означает, что подписка браузера исчезла: она помечается как expired и больше не повторяется.
  • Сервис-воркер возвращает две квитанции: click, когда посетитель открыл уведомление, и close, когда он его закрыл. Каждая подписана и привязана к одному сообщению и одной подписке, поэтому её нельзя подделать или переиспользовать для другого сообщения.
  • Отчёт на экране настроек считает подписки по статусам и открытия уведомлений. Внутри фиксируются факты accepted, sent, failed, expired, clicked и closed; они же попадают в ленту событий клиента в разделе «Люди».

Тела ответов пуш-сервиса не сохраняются: у неудачной доставки остаётся только код причины из закрытого списка.

Ротация ключей VAPID

Ротация разрушительна и поэтому спрашивает дважды. Первый вызов отвечает 409 с числом активных подписок, и кабинет показывает его в диалоге подтверждения. Подтверждение создаёт новую пару ключей и гасит все существующие подписки; в ответе указано, сколько их было. Каждому посетителю придётся подписаться заново, потому что подписка браузера навсегда привязана к ключу, с которым была создана.

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

Границы безопасности

Пригодится, когда спросит служба безопасности:

  • MyBot отправляет только на публичный HTTPS-адрес на порту 443. Loopback, приватные, link-local, multicast и адреса CGNAT отклоняются, а если имя резолвится в несколько адресов, публичными должны быть все.
  • Имя перепроверяется и резолвится заново на каждой доставке, а не один раз при регистрации, и соединение прибивается к проверенному адресу. Редиректы не выполняются, тело ответа ограничено.
  • Адреса подписок дедуплицируются по ключевому отпечатку в пределах арендатора, поэтому один бот не может проверить, подписан ли браузер на другого.
  • Браузерные маршруты живут вне поверхности /api, в зоне доверия виджета: каждый заново проверяет подписанный ключ виджета, сессию виджета и точный origin страницы и расходует общий с виджетом лимит запросов.

Данные и хранение

Браузерные подписки и сообщения относятся к категории хранения push со сроком по умолчанию 180 дней. Они участвуют в объединении подписчиков, выгрузке и удалении персональных данных наравне с остальными клиентскими данными.

Поддержка браузеров и диагностика

Поддержку определяет браузер: одновременно нужны уведомления, сервис-воркеры и Push API. Актуальные версии Chrome, Edge и Firefox на компьютере и на Android подходят. В iOS Safari даёт веб-пуш только сайту, который посетитель добавил на домашний экран.

Если ничего не приходит:

  1. Откройте https://ваш-сайт/mybot-sw.js в браузере и убедитесь, что отдаётся скрипт, а не 404, редирект или HTML-страница.
  2. Проверьте, что origin страницы сохранён в разрешённых origin виджета, а ссылка уведомления ведёт на разрешённую ссылку.
  3. Убедитесь, что браузер посетителя действительно выдал разрешение и что страницей не управляет другой сервис-воркер.
  4. Перепроверьте после ротации ключей: подписаться заново должны все.
  5. Если тестовая отправка недоступна, не хватает либо подписанного браузера, либо опубликованного документа типа Push.

API и MCP

Семь владельческих маршрутов доступны по личному токену – см. REST API и токены. Для чтения нужен скоуп web_push:read и право на аналитику у бота, для записи – web_push:write и право на реакции. В MCP есть три инструмента только на чтение и намеренно нет инструментов включения, ротации и удаления – см. MCP.

Что дальше