PD Документация ← На главную

Web Push SDK

Браузерный пакет pushdata подписывает браузер на Web Push, регистрирует его в PushData, снимает подписку при выходе и вместе с эталонным service worker отмечает доставку и клик. Работает только с публичным ключом приложения (pk_…), который безопасно хранить в JavaScript страницы; отправки и контакты — с вашего сервера, секретным ключом.

Пакет публикуется. Пока pushdata не появился в npm, соберите его из каталога app/sdk репозитория PushData (pnpm install && pnpm builddist/) и подключите как file:-зависимость или скопируйте dist/index.js на сайт. API и шаги руководства те же.

Требования: сайт по HTTPS (или localhost), Chrome / Edge / Firefox / Opera, Safari 16.4+ (на iOS — после добавления сайта на экран «Домой»).

1. Ключи приложения

В дашборде откройте Приложения → ваше приложение → Настройки: понадобятся ID приложения и публичный ключ pk_… (раздел «API-ключи»). Секретный ключ pd_… на страницу не попадает.

2. Web Push в PushData

Приложения → ваше приложение → Провайдеры Push → Web Push: нажмите «Сгенерировать ключи VAPID» и укажите контакт (mailto: или URL сайта). Публичный ключ VAPID SDK получает сам (GET /api/v1/public/apps/:id/vapid).

3. Установка

bash
npm install pushdata

Эталонный service worker: скачайте app.pushdata.ru/sw.js и положите в корень сайта как /sw.js — воркер обязан быть на том же origin, что и страница. Он показывает уведомление, открывает click_action и сам отмечает delivered / clicked.

4. Подписка

ts
import { PushDataClient } from 'pushdata'

const client = new PushDataClient({
  appId: 'APP_ID', // Приложения → Настройки
  publicKey: 'pk_…', // Приложения → Настройки → API-ключи (публичный)
  apiUrl: 'https://api.pushdata.ru',
  // При включённой проверке идентичности — HMAC id пользователя с вашего сервера (шаг 7):
  // identityHash: async userId => (await fetch(`/api/pushdata-identity?user=${encodeURIComponent(userId)}`)).text(),
})

if (client.isSupported()) {
  // По клику пользователя (браузеры блокируют запрос разрешения без жеста):
  // разрешение, регистрация /sw.js, подписка VAPID, POST /api/v1/public/devices.
  const device = await client.subscribe({ userId: 'user-123', tags: ['news'] })
  console.log(device.id, device.created ? 'new' : 'refreshed')
}

Идемпотентно: вызывайте subscribe при каждом визите вошедшего пользователя — подписка обновится, строка устройства останется той же. Без userId SDK держит случайный id браузера, чтобы устройство переподписывалось на свою же строку.

5. Выход пользователя

ts
await client.unsubscribe() // отписка в браузере + DELETE /api/v1/public/devices
const { isSubscribed } = await client.getSubscriptionStatus()

6. События

Эталонный воркер отмечает delivered при получении push и clicked при клике по уведомлению (POST /api/v1/events с pushdata_notification_id / pushdata_device_id из payload). Со страницы — client.trackEvent(notificationId, 'opened').

Свой воркер: передайте его путь в swPath и отмечайте события сами:

js
globalThis.addEventListener('push', (event) => {
  const payload = event.data.json()
  event.waitUntil(globalThis.registration.showNotification(payload.title, { body: payload.body, data: payload.data }))
})
globalThis.addEventListener('notificationclick', (event) => {
  const { pushdata_notification_id, pushdata_device_id, click_action } = event.notification.data ?? {}
  event.notification.close()
  event.waitUntil(fetch('https://api.pushdata.ru/api/v1/events', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json', 'Authorization': 'Public pk_…' },
    body: JSON.stringify({ type: 'clicked', notification_id: pushdata_notification_id, device_id: pushdata_device_id }),
  }))
})

7. Проверка идентичности

При включённой Приложения → Настройки → Проверка идентичности подписка с userId должна нести заголовок X-Identity-Hash — hex HMAC-SHA256 от id пользователя на секрете идентичности приложения. Секрет не попадает в браузер: сделайте авторизованный эндпоинт, который возвращает хэш, и передайте функцию в identityHash. Без него PushData ответит 401 identity_unverified. Анонимной подписке хэш не нужен.

8. Без пакета

Тот же сценарий на чистом JavaScript — регистрация воркера, подписка VAPID, POST /api/v1/public/devices с platform: "web", token (endpoint) и ключами web_push_p256dh / web_push_auth в base64url:

ts
const API = 'https://api.pushdata.ru'
const PUBLIC_KEY = 'pk_…'
const VAPID_PUBLIC_KEY = '…' // Приложения → Провайдеры Push → Web Push

const registration = await navigator.serviceWorker.register(`/sw.js?key=${encodeURIComponent(PUBLIC_KEY)}&api=${encodeURIComponent(API)}`)
const toBytes = (s: string) => Uint8Array.from(atob(s.replace(/-/g, '+').replace(/_/g, '/')), c => c.charCodeAt(0))
const toBase64Url = (buf: ArrayBuffer | null) => btoa(String.fromCharCode(...new Uint8Array(buf ?? new ArrayBuffer(0)))).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '')
const subscription = await registration.pushManager.subscribe({ userVisibleOnly: true, applicationServerKey: toBytes(VAPID_PUBLIC_KEY) })

const res = await fetch(`${API}/api/v1/public/devices`, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json', 'Authorization': `Public ${PUBLIC_KEY}` },
  body: JSON.stringify({
    platform: 'web',
    token: subscription.endpoint,
    web_push_p256dh: toBase64Url(subscription.getKey('p256dh')),
    web_push_auth: toBase64Url(subscription.getKey('auth')),
    user_id: 'user-123',
  }),
})
const { id: deviceId } = await res.json()

Публичные эндпоинты отвечают на CORS для любого origin.

9. Проверка

  1. Откройте сайт, нажмите кнопку подписки, разрешите уведомления.
  2. Приложения → ваше приложение → Устройства: появилась строка с платформой Web и браузером.
  3. Отправить уведомление → цель «пользователь» или «устройство» → уведомление появляется в браузере; в карточке уведомления растут delivered и clicked.
СимптомПроверьте
NOT_SUPPORTEDHTTPS, поддерживаемый браузер; Safari на iOS — сайт добавлен на экран «Домой»
PERMISSION_DENIEDразрешение запрошено по клику; в настройках сайта уведомления не заблокированы
VAPID_MISSINGключи VAPID сгенерированы у провайдера Web Push
401 unauthorizedpublicKey — ключ pk_ именно этого приложения
401 identity_unverifiedпроверка идентичности включена — передайте identityHash или подписывайте анонимно
воркер не регистрируется/sw.js лежит в корне сайта на том же origin, отдаётся с Content-Type: application/javascript

Ошибки SDK — PushDataError с code (NOT_SUPPORTED, PERMISSION_DENIED, VAPID_MISSING, INVALID_CONFIG или код сервиса: unauthorized, identity_unverified, validation_error, rate_limited).