Игрок поставил рекорд в «Змейке», закрыл вкладку и забыл про игру на неделю. Через три дня кто-то другой прошёл дальше и занял его место в таблице лидеров. Без push-уведомления игрок узнает об этом только одним способом — если сам зайдёт и проверит. С push-уведомлением телефон или ноутбук покажет сообщение сам, без визита на сайт. Эта статья — про то, как браузер такое умеет и что для этого нужно настроить.
Тема легко путается с двумя другими, уже разобранными на курсе. ManyChat — это чат-бот внутри Telegram или Instagram, отдельного мессенджера: сообщение приходит в приложение, которое пользователь и так открывает каждый день. SMS-шлюз вроде SMSC — платный канал доставки, где за каждое сообщение снимаются деньги с баланса. Web Push — третий, самостоятельный вариант: встроенная возможность браузера, без мессенджера-посредника и без счёта за отправку.
Содержание
- Что такое Web Push простыми словами
- Значок с числом и всплывающее сообщение — не одно и то же
- Чем Web Push отличается от ManyChat
- Чем Web Push отличается от SMS
- Из чего состоит система: три участника
- Что нужно, чтобы Web Push заработал на сайте
- Как выглядит запрос разрешения — и почему не стоит спрашивать сразу
- Как отправить уведомление с сервера
- Что можно положить в уведомление
- Пример: уведомления в «Змейке»
- Какие браузеры и устройства поддерживают Web Push
- Где хранить ключи VAPID
- Как пользователь отписывается от уведомлений
- Как проверить работу push во время разработки
- Частые ошибки при подключении Web Push
- Чек-лист «Web Push готов к работе»
- Частые вопросы
- Заключение
Что такое Web Push простыми словами
Web Push — это API браузера, который позволяет сайту присылать пользователю уведомления даже тогда, когда сайт не открыт. Работает это только с разрешения самого пользователя: сайт не может присылать уведомления втихую, сначала он обязан спросить, и человек должен нажать «Разрешить» в стандартном системном диалоге браузера.
После разрешения браузер выдаёт сайту нечто вроде почтового адреса — уникальную ссылку, куда можно присылать сообщения именно для этого пользователя на этом устройстве. Сайт сохраняет этот адрес у себя на сервере. Дальше, когда нужно отправить уведомление, сервер посылает запрос не напрямую на телефон пользователя, а на специальную службу самого браузера — она называется push-сервисом. У Chrome и других браузеров на движке Chromium это Firebase Cloud Messaging, у Firefox — собственная служба Mozilla, у Safari — служба Apple. Push-сервис знает, на каком устройстве сейчас находится пользователь, и доставляет сообщение туда, даже если сайт в этот момент закрыт.
Последний шаг делает Service Worker — скрипт, который работает в фоне браузера отдельно от вкладки сайта. Именно он получает пришедшее сообщение от push-сервиса и превращает его в уведомление, которое видно на экране: значок, текст, иконка сайта. Если ты уже проходил тему PWA в четвёртом модуле курса, Service Worker тебе знаком — там он отвечал за офлайн-режим «Змейки», кэшировал файлы игры, чтобы она открывалась без интернета. Для push-уведомлений используется тот же самый механизм, просто с другой задачей.
Значок с числом и всплывающее сообщение — не одно и то же
В описании темы обычно упоминают сразу две вещи: значок с числом на иконке и всплывающее сообщение. Технически это разные механизмы, и стоит развести их сразу, чтобы не путаться дальше по статье.
Всплывающее сообщение — это то, о чём вся статья: системное уведомление с текстом, которое браузер или операционная система показывает поверх остальных окон или на экране блокировки. За него отвечает Web Push API вместе с Service Worker, и именно этот механизм разобран здесь во всех деталях.
Значок с числом — отдельная возможность, которая называется Badging API. Она позволяет сайту, установленному как PWA, показать на своей иконке маленький кружок с цифрой — точно так же, как это делают обычные мобильные приложения с числом непрочитанных сообщений. Управляется значок методом navigator.setAppBadge(), который можно вызвать как из кода страницы, так и из Service Worker при получении push-события. Например, при новом push-уведомлении о том, что рекорд обойдён, Service Worker может одновременно и показать всплывающее сообщение, и увеличить число на значке иконки «Змейки» — если игра установлена на устройство как PWA. Работает Badging API не во всех браузерах одинаково полно, и на iPhone его поддержка более ограничена, чем на компьютере или Android, поэтому опираться стоит в первую очередь на само уведомление, а значок считать приятным дополнением сверху.
Чем Web Push отличается от ManyChat
ManyChat решает задачу коммуникации внутри чужой платформы. Бот живёт в Telegram или Instagram, и чтобы получить сообщение, пользователь должен иметь установленное приложение мессенджера и быть подписанным на канал или бота. Это удобно, потому что мессенджеры люди и так открывают по многу раз в день, но без аккаунта в конкретном мессенджере связь не работает вообще.
Web Push устроен наоборот: не нужен отдельный мессенджер, разрешение выдаётся прямо на сайте одним кликом. Зато и охват другой. ManyChat достаёт пользователя там, где живёт вся его переписка, а Web Push работает только в границах конкретного браузера на конкретном устройстве — сменил браузер или телефон, разрешение придётся получать заново.
Разница есть и в характере сообщений. Чат-бот ManyChat отлично подходит для диалога: задать вопрос, дождаться ответа, повести пользователя по сценарию с кнопками. Web Push — одностороннее короткое сообщение без диалога внутри самого уведомления. Кликнул — попал на сайт, а дальше разговор продолжается уже там.
Чем Web Push отличается от SMS
С SMS разница ещё более прямая. SMS — платный канал: за каждое отправленное сообщение снимаются деньги с баланса в шлюзе вроде SMSC, и чем больше уведомлений, тем выше счёт. Web Push бесплатен по своей природе — платить приходится разве что за свой сервер, но не за каждое сообщение, потому что доставку берёт на себя push-сервис браузера.
Второе отличие — в надёжности и в том, что нужно от пользователя. SMS долетает почти всегда, если номер существует и телефон включён. Web Push зависит от того, был ли выдан доступ заранее и жив ли ещё браузер на устройстве. Отправить push тому, кто ни разу не был на сайте, невозможно в принципе — в отличие от SMS, для которой достаточно знать номер телефона.
Третье отличие — в назначении. SMS используется для одноразовых кодов входа, где доставка должна быть гарантированной и мгновенной, а платёж за сообщение оправдан ценностью действия. Web Push для такой задачи не подходит: он не даёт той же гарантии доставки и годится не для срочного кода, а для напоминания, которое можно пропустить без последствий.
| ManyChat (чат-бот) | SMS-шлюз (SMSC) | Web Push | |
|---|---|---|---|
| Где живёт | Внутри Telegram или Instagram | На экране телефона, отдельным SMS | В браузере на компьютере или телефоне |
| Нужна установка | Приложение мессенджера + подписка на бота | Не нужна, достаточно номера телефона | Не нужна, достаточно разрешения в браузере |
| Стоимость отправки | Бесплатно или по тарифу ManyChat | Платно, спишется с баланса шлюза | Бесплатно, платишь только за свой сервер |
| Формат сообщения | Диалог с кнопками и сценариями | Короткий текст без интерактива | Короткое уведомление без диалога |
| Надёжность доставки | Высокая, пока жив аккаунт в мессенджере | Очень высокая, доходит почти всегда | Зависит от разрешения, устройства и браузера |
| Подходит для | Поддержки, рассылок, сценариев с ответами | Кодов входа, оплаты, срочных подтверждений | Напоминаний, необязательных уведомлений |
Из чего состоит система: три участника
Чтобы не путаться в деталях реализации, полезно держать в голове, что в Web Push всегда участвуют три стороны, и у каждой своя роль.
Браузер пользователя отвечает за само разрешение и за создание подписки. Он же хранит установленный Service Worker и в нужный момент будит его, когда приходит push-сообщение — даже если вкладка сайта в этот момент не открыта.
Push-сервис — посредник, встроенный в браузер и управляемый его производителем, а не разработчиком сайта. Разработчик не может выбрать push-сервис по вкусу или настроить его: какой браузер, такой и сервис, это часть браузерной инфраструктуры, а не стороннее решение вроде SMS-шлюза.
Сервер сайта — единственная часть, которую пишешь ты сам. Он хранит подписки пользователей и в нужный момент отправляет push-сервису запрос: доставь вот это сообщение вот этому адресу подписки. Дальше эстафету принимает push-сервис и Service Worker, а сервер сайта в процесс доставки уже не вмешивается.
flowchart TB
A["Пользователь разрешает уведомления"] --> B["Браузер создаёт push-подписку"]
B --> C["Сервер сохраняет подписку в базе"]
C --> D["Наступает событие: рекорд обойдён"]
D --> E["Сервер шлёт запрос push-сервису браузера"]
E --> F["Push-сервис доставляет сообщение"]
F --> G["Service Worker показывает уведомление"]
Что нужно, чтобы Web Push заработал на сайте
Первое требование — сайт должен работать по HTTPS. Браузеры не дают доступ к push-подписке на обычном незащищённом HTTP, потому что через открытый протокол уязвимую подписку было бы легко перехватить. Если «Змейка» опубликована через GitHub Pages из третьего модуля курса, это требование уже выполнено само собой — GitHub Pages отдаёт страницы по HTTPS по умолчанию.
Второе требование — установленный и активный Service Worker. Без него некому будет получать push-сообщения и превращать их в уведомления на экране. Если PWA-версия «Змейки» из четвёртого модуля уже готова, Service Worker там уже есть — для push его нужно не создавать заново, а расширить: добавить обработчик события push, который вызывает showNotification у самого Service Worker.
Третье — пара ключей VAPID (сокращение от Voluntary Application Server Identification) — способ, которым сервер подтверждает push-сервису право слать уведомления по конкретной подписке. Открытый ключ передаётся в браузер при подписке, закрытый остаётся только на сервере. Ключи генерируются один раз для проекта, обычно готовой библиотекой, и переиспользуются для всех пользователей сайта.
Четвёртое — логика на сервере: таблица с подписками пользователей и код, который умеет отправлять push через нужную библиотеку. Для Node.js самый распространённый вариант — web-push: она берёт на себя шифрование сообщения и формирование запроса к push-сервису конкретного браузера.
Как выглядит запрос разрешения — и почему не стоит спрашивать сразу
У браузера есть системное окно с вопросом: «Сайт хочет присылать вам уведомления. Разрешить?» Есть особенность, о которой новички часто не знают: если человек один раз нажал «Заблокировать», сайт больше не может показать этот диалог повторно через код — вернуть разрешение можно только вручную, через настройки браузера. Второго шанса почти нет.
Худший сценарий — спрашивать разрешение сразу при заходе на сайт, ещё до того, как человек понял, зачем оно нужно. Такой запрос выглядит как назойливое всплывающее окно у случайного сайта, и большинство людей отвечает отказом на автомате, не читая. После отказа сайт эту дверь для себя закрывает надолго.
Более рабочий подход — спрашивать разрешение после осмысленного действия, когда пользователь уже показал интерес. В «Змейке» уместный момент — сразу после личного рекорда: показать свою кнопку «Присылать уведомление, если кто-то тебя обойдёт» и только по клику на неё вызывать системный запрос браузера.
Как отправить уведомление с сервера
Логика на сервере складывается из нескольких шагов, и почти все они похожи на то, что уже разбиралось в статье про SMS-шлюз — только вместо SMSC отправку берёт на себя браузер.
- Фронтенд получает у пользователя разрешение через
Notification.requestPermission(). - Фронтенд вызывает
pushManager.subscribe()у зарегистрированного Service Worker, передавая открытый VAPID-ключ. Браузер возвращает объект подписки — тот самый уникальный адрес для доставки. - Фронтенд отправляет этот объект на сервер, а сервер сохраняет его в базе рядом с идентификатором пользователя — например, в таблице Supabase, если игра уже дошла до пятого модуля курса.
- Когда наступает событие, которое стоит показать пользователю — кто-то обошёл его рекорд, — сервер достаёт из базы подписку нужного игрока.
- Сервер вызывает библиотеку
web-pushи передаёт ей текст сообщения и сохранённую подписку. - Библиотека формирует зашифрованный запрос и отправляет его на нужный push-сервис — Firebase Cloud Messaging для Chrome, службу Mozilla для Firefox и так далее, в зависимости от браузера пользователя.
- Push-сервис доставляет сообщение на устройство, а Service Worker получает событие
pushи вызываетshowNotification()с текстом, заголовком и иконкой.
Сервер сайта не выбирает push-сервис сам и не хранит для каждого браузера отдельные учётные данные — за это отвечает подписка, в которой уже зашит правильный адрес. Библиотека web-push разбирает эту разницу автоматически, поэтому код отправки выглядит одинаково независимо от браузера получателя.
Что можно положить в уведомление
Метод showNotification(), который вызывает Service Worker, принимает не только текст. У него есть набор параметров, из которых складывается вид сообщения на экране:
- title — заголовок уведомления, обычно название игры или проекта.
- body — основной текст, например «Кто-то обошёл твой рекорд в «Змейке»».
- icon — маленькая иконка сайта, которая показывается рядом с текстом.
- badge — упрощённый монохромный значок, который некоторые мобильные браузеры используют в строке состояния вместо полноценной иконки.
- image — крупная картинка внутри самого уведомления, если нужно показать что-то заметнее иконки, например скриншот новой позиции в таблице лидеров.
- actions — до нескольких кнопок прямо в уведомлении, каждая со своим текстом и идентификатором действия, например «Играть сейчас» или «Посмотреть таблицу».
- tag — метка, по которой новое уведомление заменяет предыдущее с тем же тегом вместо того, чтобы копиться отдельной пачкой на экране.
- vibrate — на устройствах с вибромотором можно задать короткий паттерн вибрации при показе.
Клик по уведомлению или по одной из кнопок-действий отдельно обрабатывается в Service Worker через событие notificationclick. Внутри этого обработчика обычно открывают нужную страницу сайта — например, сразу таблицу лидеров, если пользователь нажал кнопку «Посмотреть таблицу», — и закрывают само уведомление, чтобы оно не висело на экране после того, как человек на него отреагировал.
У самого сообщения есть разумный предел объёма — это короткое уведомление, а не место для длинного текста или тяжёлой картинки. Конкретные ограничения по размеру зависят от push-сервиса, через который идёт доставка, поэтому на практике текст стоит держать в пределах одного-двух коротких предложений: заголовок и суть, без расчёта на большой объём.
Пример: уведомления в «Змейке»
Возьмём два сценария, которые логично добавить в учебный проект курса поверх обычной таблицы лидеров.
Первый — напоминание о собственном рекорде. Игрок какое-то время не заходил в игру. Раз в несколько дней сервер может проверять, у кого результат стоит без изменений дольше обычного, и присылать короткое уведомление вроде «Твой рекорд в «Змейке» — 42 очка. Побьёшь его сегодня?»
Второй, более интересный сценарий — уведомление о том, что рекорд обойдён. Если в игре есть общая таблица лидеров из Supabase, сервер может отслеживать, когда новый результат превышает чей-то прежний рекорд из топа, и сразу отправлять push тому, чью позицию заняли: «Кто-то обошёл твой рекорд в «Змейке». Теперь ты на третьем месте». Такое уведомление приходит именно в момент, когда есть конкретный повод вернуться и отыграться, а не по расписанию рассылки.
Оба сценария используют одну схему: событие на сервере — поиск подписки в базе — отправка через web-push — показ уведомления Service Worker'ом. Разница только в том, что триггерит отправку и какой текст в сообщении.
По способу запуска такие проверки бывают двух видов. Первый — отправка сразу в момент события: как только новый результат в таблице лидеров превысил чей-то рекорд, серверный обработчик записи сразу же готовит и шлёт push тому, кого обошли, без задержки. Второй — периодическая проверка по расписанию, например раз в сутки: отдельная задача на сервере проходит по подпискам и ищет тех, кто давно не заходил, чтобы прислать напоминание о собственном рекорде. Для мгновенных событий вроде обгона в таблице лучше подходит первый способ, для мягких напоминаний — второй.
Какие браузеры и устройства поддерживают Web Push
Большинство современных браузеров на компьютере — Chrome, Firefox, Edge, Opera — поддерживают Web Push без особых оговорок уже много лет. На Android ситуация похожая: и мобильный Chrome, и большинство других браузеров на этой платформе работают с push-уведомлениями так же, как их десктопные версии.
Отдельная история — iPhone. Долгое время Safari на iOS вообще не поддерживал Web Push. Ситуация изменилась начиная с iOS 16.4: Apple добавила поддержку, но с условием — уведомления работают только у сайтов, добавленных на домашний экран как полноценное PWA-приложение, а не у сайта, просто открытого вкладкой в обычном Safari. Прямая связь с темой PWA из четвёртого модуля: чтобы push дошёл до владельца iPhone, сначала должна быть готова PWA-версия «Змейки», и пользователь должен сам добавить её на домашний экран через меню «Поделиться».
Практический вывод: закладывай Web Push как канал, который точно работает на компьютерах и на Android, а на iPhone — только для тех, кто установил PWA-версию сайта. Поэтому не стоит делать push единственным способом что-либо сообщить.
Где хранить ключи VAPID
Закрытый VAPID-ключ даёт право слать push-уведомления от имени сайта всем подписанным пользователям — по сути, это такой же секрет проекта, как пароль от SMS-шлюза или ключ стороннего API. Если он попадёт в код фронтенда или в публичный репозиторий, кто угодно сможет либо читать логику отправки, либо — в худшем случае — злоупотребить доступом к серверной части, которая эти ключи использует.
Открытый ключ VAPID не секретен по своей природе — он передаётся в браузер при каждой подписке и виден в коде страницы, для него ничего специально прятать не нужно. А вот закрытый ключ должен жить исключительно на сервере, в переменных окружения, точно по тем же правилам, что описаны в статье про хранение секретов и токенов: не в git, не в клиентском коде, доступ только из серверной части приложения.
Как пользователь отписывается от уведомлений
Отписаться человек может двумя путями, и сервер сайта видит их по-разному. Первый — через настройки самого браузера: там для каждого сайта можно сменить разрешение с «Разрешено» на «Заблокировано» в любой момент, без визита на сайт вообще. Сервер об этом узнает не сразу, а только когда попробует отправить следующий push и получит от push-сервиса ошибку — обычно с кодом вроде 410, означающим, что подписка больше недействительна. Это нормальная ситуация, а не сбой: увидев такую ошибку, сервер должен удалить подписку из своей базы, а не пытаться слать на неё снова.
Второй путь — кнопка отписки прямо в интерфейсе сайта, если её предусмотреть. Тогда фронтенд сам вызывает pushManager.getSubscription(), получает текущую подписку, вызывает у неё метод unsubscribe() и сообщает серверу, что эту запись нужно удалить из базы. Такой путь дружелюбнее: пользователь явно решает отказаться от уведомлений внутри знакомого интерфейса, а не идёт в системные настройки браузера, о существовании которых многие новички даже не задумываются.
В обоих случаях правило одно: подписка, помеченная как недействительная, должна пропасть из базы, а не оставаться мёртвым грузом. Иначе каждая рассылка будет спотыкаться об одни и те же ошибки на одних и тех же старых записях.
Как проверить работу push во время разработки
Не обязательно ждать боевого сервера, чтобы увидеть, как выглядит уведомление. В инструментах разработчика браузера (в Chrome — вкладка Application, раздел Service Workers) есть возможность вручную отправить тестовое push-событие в конкретный Service Worker и посмотреть, как он его обработает и что покажет на экране — без реального похода на push-сервис. Это удобно на этапе отладки обработчика push и notificationclick: логику показа и клика по уведомлению можно проверить локально, и только когда она работает как задумано, переходить к проверке настоящей отправки через web-push с сервера. Такой подход экономит время: не нужно каждый раз ждать реальной доставки, чтобы понять, правильно ли Service Worker собирает заголовок, текст и кнопки уведомления.
Частые ошибки при подключении Web Push
Ошибка 1. Спрашивать разрешение сразу при первом заходе
Пользователь ещё не понял, зачем сайту его уведомления, и в большинстве случаев отвечает отказом не глядя. После отказа вернуть разрешение программно уже нельзя.
Ошибка 2. Слать push слишком часто
Даже те, кто разрешил уведомления, быстро отзывают разрешение через настройки браузера, если сайт присылает push по любому поводу. Уведомление должно быть событием, а не постоянным шумом.
Ошибка 3. Не обрабатывать устаревшие подписки
Подписка может протухнуть — например, если пользователь переустановил браузер или сменил устройство. Если сервер не удаляет такие записи из базы и продолжает слать на них запросы, это просто мёртвый груз в таблице подписок и лишние ошибки в логах при каждой рассылке.
Ошибка 4. Хранить закрытый VAPID-ключ в клиентском коде
Точно та же ошибка, что с паролем от SMS-шлюза: ключ, видимый в браузере пользователя, перестаёт быть секретом для кого угодно, кто откроет консоль разработчика.
Ошибка 5. Считать Web Push заменой всех остальных каналов
На iPhone push работает только для установленных PWA, а часть пользователей в принципе отклоняет разрешение. Полагаться только на push, без запасного способа что-то сообщить, — риск, что заметная доля аудитории просто не получит сообщение никаким путём.
Чек-лист «Web Push готов к работе»
- Сайт работает по HTTPS.
- Service Worker зарегистрирован и умеет обрабатывать событие
push. - Сгенерирована пара ключей VAPID, закрытый ключ лежит в переменных окружения сервера.
- Запрос разрешения показывается после осмысленного действия пользователя, а не сразу при заходе.
- Подписки пользователей сохраняются в базе рядом с идентификатором аккаунта.
- На сервере есть код, который отправляет push через библиотеку вроде
web-pushпри нужном событии. - Устаревшие или недействительные подписки удаляются из базы при ошибке отправки.
- В интерфейсе сайта есть понятная кнопка отписки от уведомлений.
- Продумана частота уведомлений — они привязаны к конкретным событиям, а не рассылаются просто так.
- Учтено поведение на iPhone: push работает только для PWA, установленных на домашний экран.
Частые вопросы
Нужно ли пользователю ставить приложение, чтобы получать Web Push?
Нет, для компьютера и Android достаточно обычного браузера и разрешения на уведомления. Исключение — iPhone: там push работает только у сайтов, добавленных на домашний экран как PWA.
Работает ли Web Push, если вкладка сайта закрыта?
Да, в этом и смысл технологии. Уведомление доставляет push-сервис браузера и показывает Service Worker, а не сама вкладка — она в этот момент может быть давно закрыта.
Сколько стоит отправка push-уведомления?
Сама доставка бесплатна — её берёт на себя push-сервис браузера. Платить приходится только за свой сервер, который формирует и отправляет запросы, но не за каждое отправленное сообщение как таковое.
Можно ли отправить push прямо из браузера, без сервера?
Технически показать локальное уведомление можно и без сервера, пока вкладка открыта. Но настоящий push, который приходит при закрытой вкладке, требует сервера с закрытым VAPID-ключом — иначе push-сервис браузера не примет запрос на отправку.
Что будет, если пользователь выключил телефон или закрыл браузер навсегда?
Пока устройство выключено, уведомление просто ждёт своей очереди у push-сервиса. Как только устройство снова online, доставка обычно происходит. Если пользователь удалил браузер или очистил его данные, подписка становится недействительной, и сервер узнаёт об этом по ошибке при следующей попытке отправки.
Чем Web Push отличается от push-уведомлений мобильного приложения из App Store или Google Play?
Механика похожая — тоже подписка, тоже push-сервис, тоже фоновая доставка. Разница в том, что мобильные push работают через нативный SDK внутри установленного приложения, а Web Push — та же идея, но средствами браузера, без публикации приложения в сторе.
Заключение
Web Push закрывает узкую, но полезную задачу: напомнить о себе пользователю, который уже был на сайте и один раз разрешил уведомления, без установки отдельного приложения и без счёта за каждое сообщение. Механика опирается на то, что уже знакомо после модуля про PWA, — Service Worker, — и добавляет к нему всего два новых элемента: подписку через pushManager и пару ключей VAPID на сервере.
Как и с SMS, здесь важно не путать роли: сервер сайта решает, когда и что отправить, а сама доставка — работа push-сервиса браузера, в которую вмешиваться не нужно и не получится. Держи закрытый ключ в переменных окружения, спрашивай разрешение только после того, как человек увидел ценность, и не превращай уведомления в постоянный шум — тогда канал будет работать на удержание игроков, а не на массовые отказы от подписки.
Читай дальше
Все статьиНе просто статьи — тебя доведут до результата
В практикуме за 2499 ₽ рядом живая команда практикующих разработчиков и маркетологов: ведём по шагам до твоего работающего приложения. Не «ролики и сам разбирайся» — помогаем на каждом затыке.
Перейти к практикуму