I have heard about Web push notifications and Service Workers many times, but I have never implemented them until the last week for Just Comments. So I decided to share my notes about this technology.

First of all, there are plenty of articles and useful documentation about Web push notifications so I won’t add something new to it. I will try to summarize what I feel one needs to understand and know to get started quickly and implement a basic version of Web Push notifications.

Secondly, there are many platforms out there on the market that provide web push notifications service. Some of them have free trials, SendPulse, for instance, goes an extra mile and offers its users the Web Push feature for free.

In this tutorial, I won’t use any service like this and I will show how to implement similar functionality from scratch.

Let’s start with some key facts:

#1 Push notifications rely on multiple separate browser APIs

The entire feature of Push Notifications involves Push API and Notifications API which can be used separately. Also, it relies on Service Workers because only they can run in the background to be able to receive push notifications even if the user closed the sending website.

It means that you need to detect if the browser supports required APIs or not when you implement push notifications.

Big Diagram of How This Works

I created a simple diagram to wrap my head around different APIs and concepts. It connects various pieces via a sequence of actions/relationships between them.

So all starts with some JavaScript code on your Web page which registers (1) a service worker. The service worker provides (2) a service worker registration object which, in turn, gives access (3) to an instance of Push Manager. The push manager can provide (4) us a Push Subscription if the user allows. This subscription object can be sent to your backend (5). On the server, you can use the subscription to send a message (6) to the user’s browser. The service worker receives (7) the message, but it is not automatically shown to the user. The service worker parses the message and can decide what to do with it. Normally, the worker displays a Notification (8) using the Notification API.

The Coding Part

As I mentioned in the key facts, not all browsers support the APIs, so we need to check if the user’s browsers support service workers:

Don’t worry about applicationServerKey for now. applicationServerKey allows associating the subscription with your server. I will explain how to obtain this key later.

So what happens here: we call the pushManager.getSubscription method which returns a subscription if the user has already allowed push notifications and null otherwise. If we already have a subscription, we can send it to the backend. If not, we call pushManager.subscribe to ask the user to allow push notifications.

Now, for the step 5, you can use any method you like to send the subscription object to your server. I recommend stringifying it first with JSON.stringify(subscription).

For sending a message from your server to the client, I recommend using the web-push module:

Here, two event listeners are defined. With the push listener, we parse the message and invoke the showNotification method to display a notification. On notificationclick we close the notification and navigate to the URL sent via the push message.

Generating Keys

You can use the web-push library to generate keys. The key generation needs to be done once. Both the frontend and the backend use the same public key, and the backend only uses the private key:

You should specify the keys in the previous code snippets, where needed.

Conclusion

I find the APIs for Push Notifications to be quite simple and straightforward. Nevertheless, it takes quite some time, in the beginning, to wrap your head around all concepts and moving parts.

I hope you find these notes useful and you’ll come back to them once you need to implement push notifications. And if this time comes, please don’t ask for permissions as soon as the web page loads: it’s annoying, and most people would block it.