PWA Push Notifications in JavaScript? Yes, You Can in 12 Steps!

an introduction

Where push notifications were until recently a privilege of native apps, that has now changed. Push notifications can now be sent directly to the PWA: just like with the original app, the browser doesn’t have to be open, not even in the background.

This tutorial discusses how to implement Push API in 12 steps. We add this API to our existing PWA to create “selfies” (access my previous tutorials from my profile).

mobile phone screen

Project preparation

As a starting point for the tutorial, clone the following GitHub repository:

git clone 

Next, on your device, go to the directory:

 cd progressive-web-app

 cd pwa-article/pwa-app-native-features-push-api-init

Install the dependencies using:

Open the web application at: http://localhost:8080/index.html.

Progressive selfies - duck on the shelf

Push API with JavaScript

Web Push Notifications Flow

Web Push Notification is a protocol with 4 actors (Picture 1):

  • User: This is the person who wants to receive notifications.
  • Application or PWA: Runs in the browser. Browsers that use the Push API contain a file Payment service It is responsible for forwarding push notifications from the server to the user.
  • Service Agent: It acts as a proxy server between the application, the browser and the network
  • Push server or server: This sends push notifications to the service worker via Payment service.

web push notification flow

picture 1

1. The flow starts when the application asks the user So to receive notifications.

2. Once the user gives the permission, the app Service worker registers.

3. – 6. When the PWA receives the recording from the service worker, the PWA can use it to create a file Subscription payment. a Payment service It is also required to create a payment subscription. The payment subscription contains a file Payment service end point To also send a push notification.

7. At this point, the application sends the generated payment subscription to the server. server needs Pay subscription end point To send notifications.

8. When the server receives the payment subscription, it is stored in a database called Subscriptions.

9. The server sends a push notification to the endpoint of the push subscription. Then a push notification is sent Via payment service to the service workerwho listens to push event.

10. In service worker Then it forwards the push notification to the user.

11. When user clicks on push notification, service worker receives it through notification click event.

12. The service worker can now do almost anything they want with a push notification.

Now that you know the flow, it’s time to move on to the real implementation.

Steps 1 and 2: User permissions

Before you can send notifications to a user, you must request permission from that user through a prompt view. For this prompt to start, add the code below to the current file: src / js / pushpi.js (List 1).

src / js /pushapi.js

const enableNotificationsButtons = document.querySelectorAll('.enable-notifications'); 

const askForNotificationPermission = () => { 
      Notification.requestPermission(result => { 
      if (result === 'granted') { 
          // configurePushSubscription(); 

if ('Notification' in window) {
      for (let i = 0; i < enableNotificationsButtons.length; i++) { 
          enableNotificationsButtons[i].style.display = 'inline-block'; 
          enableNotificationsButtons[i].addEventListener('click', askForNotificationPermission); 


list 1

Put the code below at the bottom of src/index.html So we can use pushapi.js (List 2):

<script src=""></script>

Menu 2

We ask for permission from the user when they click the Enable Notifications button in our PWA (Picture 2). The button should only be visible if the browser supports push notifications! In the code, you can identify this validation by the condition: “if (“notification” in the window)”.

Enable notifications

picture 2

Add the following in src / css / app.css (List 3).

.enable-notifications { 
  display: none; 

3 . list

Show notification

As a first step, we show the user a notification (with an OK/Cancel button) when we get permission (menu 4).

add this code to src/js/pushapi.js

const displayConfirmNotification = () => { 
     if ('serviceWorker' in navigator) { 
        const options = {
              body: 'You successfully subscribed to our Notification service!',
              icon: 'src/images/icons/app-icon-96x96.png',
              image: 'src/images/main-image-sm.jpg',
              dir: 'ltr',
              lang: 'en-US',
              badge: 'src/images/icons/app-icon-96x96.png',
              tag: 'confirm-notification',
              actions: [ 
                      action: 'confirm',
                      title: 'Okay',
                      icon: 'src/images/icons/app-icon-96x96.png' 
                      action: 'cancel',
                      title: 'Cancel',
                      icon: 'src/images/icons/app-icon-96x96.png' 
         .then(sw => sw.showNotification('Successfully subscribed!', options));


Menu 4

the Navigator. Service worker. Ready … Checks whether the service agent is activated. Also, by job sw.showNotification(), A notice appears.

Steps 3 and 4: Register a service worker

Service worker registration and activation is already described in my first PWA tutorial.

Step 5: Subscribe to Push Notifications

For a user to subscribe to push notifications, two steps are required:

  • First, get the user’s consent (steps 1 and 2).
  • Getting Subscription payment via Payment service (Step 5).

What is the payment service?

  • Each browser manages push notifications via its own system, the so-called “push service”.
  • When the user gives permission to push notifications, the app is able to subscribe to the browser’s push service.
  • This creates a private payment subscription that contains the . Endpoint URL Payment servicewhich is different for each browser (Menu 5).
  • In step 9, push notifications are sent to these URLs, encrypted with a public key.
  • The payment service ensures that the payment notification is sent to the correct customer.
  'keys': {
	'p256dh': 'BGhFV5qx5cdOaD_XF293OqMdYSUIrMrzj2-RuzGwOTIhdW8v’, 
	'auth': 'HA1JEiRAp2HLuVH639Oumw'


5 . menu

The endpoint is the payment service URL. The server uses this endpoint to send a push notification (step 9). The main object contains the values ​​used to encode the notification.

How does the payment service know which customer to send the instant notification to?

The endpoint URL contains a unique identifier. This definition is used by Payment service To route the received push notification to the correct device. When the notification is processed by the browser, the service operator (step 10) that should handle the request is determined by push event.

Application server keys

Before a user subscribes to a push notification, you must create a set of Application Server Keys. Application server keys, also known as VAPID keys, are unique to the server. It enables the push service to know which server the user has subscribed to. The keys ensure that it is the same server that sends push notifications to that user.

Push subscription configuration

Listing 6 shows how to configure Push Subscription and how to send PushSubscription to the server.


To activate the function below (menu 6) you need:

1. Activate configPushSubscription () in the askForNotificationPermission() function (list 1).

2. Also, Removal the displayConfirmNotification() call function.

Add src / js / pushapi.js

const configurePushSubscription = () => {
   if ('serviceWorker' in navigator && "PushManager" in window) {
       let serviceWorkerRegistration;
        // Service worker registratie (step 4)
           .then(registration => {
               serviceWorkerRegistration = registration;
               return registration.pushManager.getSubscription();
           .then(subscription => {
               if (subscription === null) {
                   // Create a new Push Subscription (step 5 and 6)
                   return serviceWorkerRegistration.pushManager.subscribe({
                       userVisibleOnly: true,
                       applicationServerKey: urlBase64ToUint8Array(
            // Verzenden Push Subscription naar de server (step 7)
           .then(pushSubscription => {
               return fetch(`${SERVER_URL}/subscriptions`, {
                   method: 'POST',
                   headers: {
                       'Content-Type': 'application/json',
                       'Accept': 'application/json'
                   body: JSON.stringify(pushSubscription)
           .then(response => {
               if (response.ok) {
           .catch(error => console.log(error));


Menu 6

First, the above code checks if push notifications and service factor are supported in the browser, using conditions: if (‘serviceWorker’ in navigator && “PushManager” in window) {}

If the service worker is registered and active (Navigator. Service worker. Ready …), we check if the payment subscription is present via the call: registration.pushManager.getSubscription().

If it is null, we call registration.pushManager.subscribe() To get a new paid subscription via Payment service. For this, enter applicationServerKey.

How to generate application server keys

You can create a public and private set of applicationServerKeys from the root of the server. To do this, first clone a file server via:

git clone 

go to main folder From This server Via the terminal and run the following command to generate the keys:

npm i && npm run web-push 

  1. After generating the keys, make sure that Replace the public key On the front end, on the job configPushSubscription () in a src / js / pushpi.js.
  2. Also you are replacing the public and private keys in a file server side In the ways / ways. js File (List 7).
const VAPID_PUBLIC_KEY = 'plak hier je public key'; 

const VAPID_PRIVATE_KEY = 'plak hier je private key'; 



7 . menu

Steps 6 and 7: Send Push Subscription to Server

Once the user subscribes to push notifications and I got Subscription payment back from Payment service, the payment subscription is sent to the server (List 6). Finally, on the server, you store this payment subscription in a file Subscriptions Database.

Step 8: Receive Payment Subscriptions on the Server

In the previous steps, you have already cloned the server.

Then go to The root directory of this server In your terminal, install the dependencies and start the server with:

The server is running on Localhost: 3000.

In the Progressive web application server / tracks / tracksthe code is already waiting for us to receive payment subscriptions and oblige them to node-json-db Call Subscriptions. This is a simple database for storing information in a JSON file. Payment subscriptions come via the POST . URL `/ Subscriptions(List 8).'/subscriptions', (req, res) => { 

  const subscription = req.fields; = uuid.v4(); 

  subscriptionsDb.push(`subscriptions/${}`, subscription, false); 

  res.status(200).send('subscription saved'); 


Menu 8

Step 9: Send Push Notifications by Web Push to the User

From now on, we can send notifications to the user. In our example, a push notification is sent to the relevant user via webpush API when “Photograph ” It was received on the server. How to send “selfies” with your PWA is described in my previous lessons.

Pre-existing code in route.js:

{if (subscription.endpoint && subscription) {webpush.sendNotification (subscription, JSON.stringify ({title: ‘New Selfie added!’, content: `${post.title}}@${post.location}`), imageUrl: post.selfieUrl, openUrl: ‘help’})). catch(error => console.log(error) ); }}); res.status (200).send({message: ‘Selfie storage’, id:}); }); … “data-lang =” text / javascript “>'/selfies', (req, res) => {
   const post = {title: req.fields.title, location: req.fields.location};
   const selfieFileName = path.basename(req.files.selfie.path);
   post.selfieUrl = `${req.protocol}://${req.get('host')}/images/${selfieFileName}`; =;

   selfiesDb.push(`selfies/${}`, post, false);

   const subscriptions = subscriptionsDb.getData("");
   Object.values(subscriptions).forEach(subscription => {
     if (subscription.endpoint && subscription) {
        webpush.sendNotification(subscription, JSON.stringify({
         title: 'New Selfie Added!',
         content: `${post.title} @ ${post.location}`,
         imageUrl: post.selfieUrl,
         openUrl: 'help'
     })).catch(error => console.log(error));
 res.status(200).send({message: 'Selfie stored', id:});


Menu 9

In the above code (List 9), “Personal Pictures” sent via the POST . URL arrive/ Selfie“.

These profile pictures are stored in a file node-json-db Call Personal Photos. Then subscriptions Removal From SubscriptionsUtilization SubscriptionsDb.getData (“”). Finally, for every subscription found, a push notification is sent with webpush.sendNotification ().

Step 10: Receive notifications via the service worker

To receive push notifications as a user, we need to add the following code in our service operator (list 10):

Add this code to the list sw.js:

self.addEventListener('push', event => {
  const data = JSON.parse(;
   const options = {
       body: data.content,
       icon: 'src/images/icons/app-icon-96x96.png',
       badge: 'src/images/icons/app-icon-96x96.png',
       data: {
           url: data.openUrl
       self.registration.showNotification(data.title, options)


10 . menu

The above code listens to push event It reads the payload of data sent from server. With this payload data, you can then display a push notification in the browser (Picture 3) using self.registration.showNotification().

    A new profile picture has been addedpicture 3


To test push notifications, you need to send a “Selfie” via your PWA. This can of course be done by localhost: 8080.

However, if you want to test on your mobile phone or tablet, you can use skirt to public URL.

Installations skirt Utilization:

Why don’t you get push notifications?

  • Enable push notifications in your browser.
  • Before sending a “Selfie”, you must click on the “Enable Notifications” button (Picture 2). Click to grant permission.
  • Application server keys are not set.
  • Only under localhost: Manually “unregister” the service agent via development tools (Chrome) and reload your PWA.


After completing the above steps, you still need to perform steps 11 and 12. These steps are already implemented in the final version: pwa-app-native-features-push-api-final.


Leave a Comment