Sign up

browser push notifications

How To Send Push Messages to a Web Browser

Angela Stringfellow

Last updated on

The benefits of push messages for businesses with an online presence are innumerable. By opening up a direct communication channel between you and your users, it becomes a critical component in the customer engagement strategy of every business.

For a long time, push messages were limited to mobile applications. This changed with Chrome update 42 when push messages were introduced for browsers, giving the power of push messages to websites and web-based applications.

This article will guide you on how to send push messages to web browsers.

Service Workers

Service workers are required to send push messages for web applications. A service worker is a client-side proxy that facilitates your web application and the rest of the internet. They are written in JavaScript and can be used to have granular control over network requests by treating different requests differently.

An additional task performed by service workers is handling push messages. It is a script that executes separately from the main browser thread. This is what enables you to send browser push messages even when the browser is not open. To prevent man-in-the-middle attacks, service workers are available only for secured servers connected to TLS using the HTTPS protocol.

Browser Push Messages

To send browser push messages, the following three steps have to be completed:

  1. The subscribing user must agree to receive push messages.
  2. An API call must be sent from application server to trigger the push message.
  3. The service worker must receive the push message and display it to the user.

Subscribing Users

The first step is to check whether service workers and push messages are supported in the browser. The following code helps to do that.

if (!('serviceWorker' in navigator)) {
  console.log('Service workers not supported in this browser.') // Service Worker isn't supported on this browser
  return;
}
if (!('PushManager' in window)) {
  console.log('Service workers not supported in this browser')// Push messages are not supported on this browser.
  return;
}

If service workers or push messages are not supported by the browser, the UI elements for push messages will be disabled or hidden.

Service Worker Registration

The service worker has to be registered, installed, and activated on the browser before it can be used. You’ll therefore need to register a service worker in your main js code. This tells the browser the location of the browser and also initiates the installation process. This has to be in the entry point of your web application.

You can use the code below to accomplish this by simply adapting it to suit your specific requirements.

if (!('serviceWorker' in navigator)) {
  console.log('Service worker not supported');
  return;
}

navigator.serviceWorker.register('/service-worker.js')
  .then(function(registration) {
    console.log('Service worker registered successfully with scope:', registration.scope);
  })
  .catch(function(err) {
    console.error('Unable to register service worker.', err);
  })
});

Your application can attempt to register a service worker each time a page is loaded, but the browser will only register a service worker if it is new or updated.

Permission

Once a service worker has been successfully registered, you need the explicit consent of the user to be able to send push messages. The API to get user permission returns a Promise.

The following code can be used to get user permissions.

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('Permission was not granted');
      }
    });
}

The method `Notification.requestPermission()` displays the prompt to the user.

Subscribe User

Once the permission is granted, you have to subscribe the user with the function `registration.pushManager.subscribe()`.

The following code snippet can be used for this task. Just replace `<public key>` with the publickey for your application.

function subscribeUserToPush() {
  return navigator.serviceWorker.register('/service-worker.js')
    .then(function(registration) {
      const subscribeOptions = {
        userVisibleOnly: true,
        applicationServerKey: urlBase64ToUint8Array(
          '<public key>'
        )
      };

      return registration.pushManager.subscribe(subscribeOptions);
    })
    .then(function(pushSubscription) {
      console.log('Subscription received for push notification: ', JSON.stringify(pushSubscription));
      return pushSubscription;
    });
}

Push Messages

You can set up an admin page from where push notifications can be triggered. You can also set up event-based triggers to send messages. For Node applications you need to install the package `web-push` with the following command.

npm install web-push --save

The package should be added in the Node script.

const webpush = require('web-push');

The web push needs application server keys.

const appKeys = {
  publicKey: '<public key>',
  privateKey: '<private key>'
};
webpush.setAppDetails(
  'mailto:mail@app.com',
  appKeys.publicKey,
  appKeys.privateKey
);

When a trigger to push messages is received, subscriptions are retrieved from the database and a push notification is sent to each one.

You can use the following code snippet to accomplish this:

return getSubscriptionsFromDatabase()
  .then(function(subscriptions) {
    let promiseChain = Promise.resolve();

    for (let i = 0; i < subscriptions.length; i++) {
      const subscription = subscriptions[i];
      promiseChain = promiseChain.then(() => {
        return triggerPushMsg(subscription, dataToSend);
      });
    }

    return promiseChain;
  })

const triggerPushMsg = function(subscription, dataToSend) {
  return webpush.sendNotification(subscription, dataToSend)
    .catch((err) => {
      if (err.statusCode === 404 || err.statusCode === 410) {
        console.log('Subscription has expired or is no longer valid: ', err);
        return deleteSubscriptionFromDatabase(subscription._id);
      } else {
        throw err;
      }
    });
};

The `triggerPushMsg()` method is used to send messages to subscribers. The method `webpush.sendNotification()` will return a promise. The promise will resolve if the message was delivered successfully, but if the promise is rejected, you’ll need to check the error and debug it.

Conclusion

There are many more nuances to sending browser push messages beyond what is covered in this article, and it can easily become a complex task. MagicBell can eliminate this complex process and integrate browser push messages with a couple of clicks and a couple of lines of code.