Skip to main content
Enable web push notifications in the browser to send timely messages to users.
Track your campaigns: The SDK service worker can track delivery, opens, and clicks. For custom tracking implementations, see Push Notification Tracking.

Prerequisites

  1. HTTPS — Web push requires a secure context
  2. Service Worker — A service worker file to handle push events (default path /sw.js)
  3. Write key — Your Zixflow write key
  4. User permission — Users must grant notification permission

Step 1: Install the package

npm install @zixflow/analytics-browser@^1.1.5

Step 2: Add a service worker

Copy the SDK service worker to your web root as public/sw.js (or serve it at another path and pass that path as swUrl). The package includes a reference worker at node_modules/@zixflow/analytics-browser/.../plugins/web-push/sw.js. A minimal starter:
// public/sw.js — prefer the full SDK worker for automatic tracking beacons

self.addEventListener('install', (event) => {
  self.skipWaiting()
})

self.addEventListener('activate', (event) => {
  event.waitUntil(self.clients.claim())
})

self.addEventListener('push', (event) => {
  if (!event.data) return

  let data
  try {
    data = event.data.json()
  } catch (e) {
    return
  }

  const title = data.title || 'Notification'
  const options = {
    body: data.body || '',
    icon: data.icon || '/icon.png',
    badge: data.badge || '/badge.png',
    image: data.image,
    data: data,
    tag: data.tag || 'zixflow-push',
    requireInteraction: data.requireInteraction || false,
    actions: data.actions || []
  }

  event.waitUntil(self.registration.showNotification(title, options))
})

self.addEventListener('notificationclick', (event) => {
  event.notification.close()

  const clickedUrl = event.action
    ? event.notification.data.actions?.[event.action]?.url
    : event.notification.data.url || '/'

  event.waitUntil(
    clients.openWindow(clickedUrl).then((windowClient) => {
      if (windowClient) windowClient.focus()
    })
  )
})
For automatic delivery/open tracking, use the full worker shipped with the SDK (it listens for SDK_CONFIG and posts to https://cdp.zixflow.com/v1/track).

Step 3: Enable the Web Push plugin

Prefer init options (recommended):
import {
  AnalyticsBrowser,
  subscribeToPush,
  unsubscribeFromPush,
} from '@zixflow/analytics-browser'

const analytics = AnalyticsBrowser.load(
  { writeKey: 'YOUR_WRITE_KEY' },
  {
    webPush: {
      enabled: true,
      swUrl: '/sw.js',
      autoSubscribe: false,
      // apiHost defaults to 'cdp.zixflow.com/v1'
      onNotificationClick: (url, action, data) => {
        console.log('Notification clicked:', url, action, data)
        window.location.href = url
      }
    }
  }
)
Or register the plugin manually:
import { AnalyticsBrowser, WebPushPlugin } from '@zixflow/analytics-browser'

const analytics = AnalyticsBrowser.load({ writeKey: 'YOUR_WRITE_KEY' })
await analytics.register(
  WebPushPlugin({
    swUrl: '/sw.js',
    autoSubscribe: false,
  })
)

Step 4: Request push permission

Request permission from a user gesture (for example a button click):
document.getElementById('subscribe-btn').addEventListener('click', async () => {
  try {
    await subscribeToPush(analytics)
    console.log('Push notifications enabled')
  } catch (err) {
    console.error('Failed to enable push notifications:', err)
  }
})

Step 5: Identify users

Associate the subscription with a known user:
analytics.identify('user@example.com', {
  email: 'user@example.com',
  first_name: 'John'
})

Web Push API reference

Subscribe

import { subscribeToPush } from '@zixflow/analytics-browser'

await subscribeToPush(analytics)
// optional overrides: { apiHost, protocol, swUrl }

Unsubscribe

import { unsubscribeFromPush } from '@zixflow/analytics-browser'

await unsubscribeFromPush(analytics)

Best practices

  1. Request permission after explaining value — not on first paint
  2. Trigger subscribe from a user gesture
  3. Provide an unsubscribe path
  4. Test on HTTPS
  5. Handle permission denied / blocked states
  6. Deep-link notifications to useful content

Troubleshooting

Permission denied

Explain value before requesting permission, then guide users to browser settings to re-enable.

Service worker not registered

if ('serviceWorker' in navigator) {
  navigator.serviceWorker
    .register('/sw.js')
    .then((reg) => console.log('SW registered:', reg))
    .catch((err) => console.error('SW registration failed:', err))
}

Push not received

  • HTTPS enabled
  • Service worker registered at the configured swUrl
  • User granted notification permission
  • User identified with analytics.identify()
  • Subscription created via subscribeToPush
  • Browser supports web push