Frontend Development 14 min read

How to Subscribe a User to Push Notifications with Service Workers

This guide walks you through detecting push support, registering a service worker, requesting notification permission, creating a PushSubscription with proper options, and sending the subscription data to a backend for later use, all using modern JavaScript APIs.

Yuewen Frontend Team
Yuewen Frontend Team
Yuewen Frontend Team
How to Subscribe a User to Push Notifications with Service Workers

Subscribe a User

The first step is to obtain permission from the user to send messages, which gives you a PushSubscription . The JavaScript API for this is straightforward, so we’ll walk through the logic step by step.

Feature Detection

Check whether the current browser supports service workers and push messages:

<code>if (!('serviceWorker' in navigator)) {
  // This browser does not support Service Worker, hide UI
  return;
}
if (!('PushManager' in window)) {
  // This browser does not support Push, hide UI
  return;
}</code>

Even though more browsers support both, progressive enhancement with feature detection is always a good idea.

Register a Service Worker

After confirming support, register the service worker file (e.g., /service-worker.js ) which runs in a privileged context and can access the push API:

<code>function registerServiceWorker() {
  return navigator.serviceWorker.register('service-worker.js')
    .then(function(registration) {
      console.log('Service worker successfully registered.');
      return registration;
    })
    .catch(function(err) {
      console.error('Unable to register service worker.', err);
    });
}</code>

Request Permission

Once the service worker is registered, request the user’s permission to show notifications. The API now returns a Promise , so we need to handle both the old callback style and the new promise style:

<code>function askPermission() {
  return new Promise(function(resolve, reject) {
    const permissionResult = Notification.requestPermission(function(result) {
      resolve(result);
    });
    if (permissionResult) {
      permissionResult.then(resolve, reject);
    }
  })
  .then(function(permissionResult) {
    if (permissionResult !== 'granted') {
      throw new Error('We weren\'t granted permission.');
    }
  });
}</code>

The permission dialog looks like this:

Subscribe a User with PushManager

After registration and permission, call registration.pushManager.subscribe() with the required options:

<code>function subscribeUserToPush() {
  return navigator.serviceWorker.register('service-worker.js')
    .then(function(registration) {
      const subscribeOptions = {
        userVisibleOnly: true,
        applicationServerKey: urlBase64ToUint8Array('BEl62iUYgUivxIkv69yViEuiBIa-Ib9-SkvMeAtA3LFgDzkrxZJjSgSnfckjBJuBkr3qBUYIHBQFLXYp5Nksh8U')
      };
      return registration.pushManager.subscribe(subscribeOptions);
    })
    .then(function(pushSubscription) {
      console.log('Received PushSubscription: ', JSON.stringify(pushSubscription));
      return pushSubscription;
    });
}</code>

The userVisibleOnly option must be set to true to avoid silent pushes. Chrome currently enforces this, and attempting to omit it results in an error.

Chrome currently only supports push subscriptions that generate a user‑visible notification. Use pushManager.subscribe({userVisibleOnly: true}) for now.

The applicationServerKey is the public VAPID key that identifies your application to the push service:

Authorization and Subscription

When you call subscribe() , the browser may automatically request notification permission if it hasn’t been granted yet. For finer control, use the askPermission() function shown earlier.

PushSubscription Object

The resulting PushSubscription contains everything needed to send a push message later:

<code>{
  "endpoint": "https://some.pushservice.com/something-unique",
  "keys": {
    "p256dh": "BIPUL12DLfytvTajnryr2PRdAgXS3HGKiLqndGcJGabyhHheJYlNGCeXl1dn18gSJ1WAkAPIxr4gK0_dQds4yiI=",
    "auth": "FPssNDTKnInHVndSTdbKFw=="
  }
}</code>

The endpoint is the URL to which you POST a push message, and the keys are used to encrypt the payload.

Send Subscription to Your Server

Serialize the subscription and POST it to your backend:

<code>function sendSubscriptionToBackEnd(subscription) {
  return fetch('/api/save-subscription/', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(subscription)
  })
  .then(function(response) {
    if (!response.ok) {
      throw new Error('Bad status code from server.');
    }
    return response.json();
  })
  .then(function(responseData) {
    if (!(responseData.data && responseData.data.success)) {
      throw new Error('Bad response from server.');
    }
  });
}</code>

On the Node server, store the subscription for later use:

<code>app.post('/api/save-subscription/', function(req, res) {
  if (!isValidSaveRequest(req, res)) { return; }
  return saveSubscriptionToDatabase(req.body)
    .then(function(subscriptionId) {
      res.setHeader('Content-Type', 'application/json');
      res.send(JSON.stringify({ data: { success: true } }));
    })
    .catch(function(err) {
      res.status(500);
      res.setHeader('Content-Type', 'application/json');
      res.send(JSON.stringify({ error: { id: 'unable-to-save-subscription', message: 'The subscription was received but we were unable to save it to our database.' } }));
    });
});</code>

FAQ

Can I change the push service used by the browser?

No. The push service is chosen by the browser. Calling subscribe() triggers a network request to that service.

Do all browsers use the same push API?

Yes. The Web Push protocol defines a common API across browsers.

If a user subscribes on desktop, are they also subscribed on mobile?

No. The user must subscribe separately in each browser and on each device, granting permission each time.

FrontendJavaScriptpush notificationsAPIweb pushservice workers
Yuewen Frontend Team
Written by

Yuewen Frontend Team

Click follow to learn the latest frontend insights in the cultural content industry. We welcome you to join us.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.