Web Push Notifications: A Beginner's Guide

Push notifications are popular for mobile applications that want to keep their users informed of updates, incoming messages, and more. They've been popular since the release of smartphones and will continue to play a major role in mobile applications for a long time ahead.

One new(er) feature, web push notifications, allows users to receive and display real-time notifications within their web browsers. This article will go over what they are and how to set them up within a website.

What Are Web Push Notifications?

Web push notifications are real-time notifications submitted to a user's desktop or mobile browser through either a server-side application or web push service.

These types of notifications are generally used to engage or re-engage a user in a website's content or provide personalized messages, notifications, or alerts.

These notifications generally pop up from the right side of the screen, either the top-right or bottom-right, on desktops and from the top of the screen on supported mobile devices, depending on the user's browser and device, or operating system.

Let's walk through how to set these notifications up through Google Firebase and some JavaScript code.

Step 1: Set Up a Google Firebase Project

If you don't have a Google account, we'll need to set this up first. If you do have a Google account, make sure you're logged in so you can proceed.

The next thing we'll need to do is create a Firebase project in the Google Firebase Console.

Project creation is easy. Click on the big "+ Add Project" button from the Firebase console:

Firebase console add project button

Give our project a name:

Firebase console add project name

Once the project is created, we'll need to add a web platform:

Firebase console add platform

And then provide a name for our platform. This can be the same name as our project to keep things consistent:

Firebase console platform name

Finally, click the "Register App" button to create our new web platform within our Firebase project.

Step 2: Create the Service Worker File

The service worker file is needed to register the Firebase dependencies for notification initialization and handling, and for background notification event handling when the browser window is inactive.

The first thing we'll need to do here is to create a file named firebase-messaging-sw.js that is placed in the root directory of our website.

In the file, we need to import the required Firebase dependencies using JavaScript's importScripts() method.

importScripts("https://www.gstatic.com/firebasejs/x.xx.x/firebase-app.js");
importScripts("https://www.gstatic.com/firebasejs/x.xx.x/firebase-messaging.js");
Notice the version number is redacted from the Firebase include scripts. The latest Firebase core and messaging script versions will come pre-populated instead of showing "x.xx.x" as the version number. You will not need to manually figure this out on your own. I just redacted them to prevent confusion with the versioning.

Next, we need to define our Firebase configuration variables using the values provided from the Firebase console, and then initialize Firebase:

var firebaseConfig = {
apiKey: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
authDomain: "auth.domain.com",
databaseURL: "https://authdomain.firebaseio.com",
projectId: "authdomain",
storageBucket: "authdomain.appspot.com",
messagingSenderId: "0123456789",
appId: "1:0123456789:web:xxxxxxxxxxxxxxxxxxxxxx",
measurementId: "G-XXXXXXXXXX"
};

firebase.initializeApp(firebaseConfig);
Again, this is just an example to show you the format. All configuration code will come pre-populated with the values of our Firebase project. All we'll need to do is copy and paste that code into our website and Firebase should initialize successfully on page load.

Finally, we need to create a messaging object and setBackgroundMessageHandler() method for background notification retrieval and display. The payload data within this method will be used to generate the notification display:

const messaging = firebase.messaging();

messaging.setBackgroundMessageHandler(function(payload) {
const notification = JSON.parse(payload.data.notification);

const title = notification.title;
const options = {
body: notification.body
};

return self.registration.showNotification(
title,
options
);
});

Step 3: Initialize Firebase in Our Website

Once we've created our new web platform and set up our service worker file, we'll need to initialize Firebase within our website for foreground message handling.

Foreground messaging allows our web browser to receive real-time notifications when our web browser is active, or in the foreground.

The remaining code examples will not be in our service worker file. I would suggest placing the remainder of the code in a separate JavaScript file for organization purposes and cleanliness.

First, we need to include our Firebase dependencies somewhere in our project. These files should be included before any other Firebase-specific functions:

<script src="https://www.gstatic.com/firebasejs/x.xx.x/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/x.xx.x/firebase-messaging.js"></script>

Second, we need to register the firebase-messaging-sw.js service worker file that we created earlier, and assign it to the registration object:

navigator.serviceWorker.register("firebase-messaging-sw.js");
var registration = null;

navigator.serviceWorker.ready.then(function(reg) {
registration = reg;
});

And, third, we'll import the same configuration and initialization we used in the service worker file:

var firebaseConfig = {
apiKey: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
authDomain: "auth.domain.com",
databaseURL: "https://authdomain.firebaseio.com",
projectId: "authdomain",
storageBucket: "authdomain.appspot.com",
messagingSenderId: "0123456789",
appId: "1:0123456789:web:xxxxxxxxxxxxxxxxxxxxxx",
measurementId: "G-XXXXXXXXXX"
};

firebase.initializeApp(firebaseConfig);

Step 4: Register a Web Push Token

To generate a valid web push token, the user will need to be presented with a native permission popup and accept those permissions.

The native permission popup will look something like this on a desktop browser:

Web Push permissions native popup

However, it's best practice to show a more user-friendly version of the permissions you're requesting before showing this native popup. This is something that you can customize on your own, providing some details about what the user is subscribing and agreeing to and what types of notifications and frequency of notification submissions they should expect.

Here's an example of a custom popup shown to the user first before the native permission popup:

Web Push permissions custom popup

Once the user clicks the "Allow" button in our new custom popup, we can show the native popup.

The native permission popup can be invoked with the following code:

const messaging = firebase.messaging();

messaging
.requestPermission()
.then(function() {
return messaging.getToken();
})
.then(function(token) {
console.log(token);
})
.catch(function(error) {
console.error("No permission to send push ", error);
}
);

Just like the service worker file, this internal script will also create a messaging object linked to the Firebase library, which we'll use in a bit to attach event handlers and permission requests to.

These two messaging objects created have no relation to each other as the service worker file runs separately from client-side script files included within a web page.

This example uses the messaging object to invoke the requestPermission() method, which displays the native permission popup to the user for their final decision.

If permissions are accepted by the user, then a web push token is generated and can be stored on the web application server. If permissions are denied by the user, an error is thrown.

Once the user approves or denies permission for notifications, they will no longer see the native popup unless they manually clear their saved preference from their browser settings.

Step 5: Create a Foreground Notification Event Handler

Next, we'll need a way to handle incoming notifications when the browser window is in the foreground, or when a browser tab is active.

We'll use the messaging object again to assign an onMessage event handler, which will listen for any incoming messages in the foreground:

messaging.onMessage(function(payload) {
if ("serviceWorker" in navigator) {
if (typeof(payload.notification.options) === "undefined") {
payload.notification.options = {};
}

payload.notification.options = {
body: payload.notification.body,
icon: payload.notification.icon
};

return navigator.serviceWorker.showNotification(
payload.notification.title,
payload.notification.options
);
}
});

The event handler returns one parameter, payload, which contains the data we'll use to display in the user's notification popup on their screen. This payload data is prepared and submitted from a server-side application or web push service.

We then check to make sure the serviceWorker property is supported by the user's browser.

If service workers are supported and the options object is not defined, we create an empty options object to prevent error. Options could include an icon, device vibration sequence, and more. We'll get more into that later.

We then proceed with displaying the notification popup to the user with the showNotification() method. In this example, we're passing the payload notification title and any options that may exist for display and user interaction.

Step 6: Send a Web Push Notification

Once a user has accepted web push permissions and a valid token has been generated, they can begin receiving notifications.

These tokens can be saved somewhere within a database or other storage means.

We'll also need our Firebase server key to grant authentication from Google's servers to submit the notifications through FCM.

The Firebase server key can be found in our Firebase project settings > Cloud Messaging tab > Server Key value:

Firebase project server key

Here's how to generate a web push notification with a user token using cURL:

curl --request POST 'https://fcm.googleapis.com/fcm/send'
--header 'Content-Type: application/json'
--header 'Authorization: Key=[firebase-server-key]'
--data-raw [payload]

With payload data:

{
"notification": {
"title": "Orangeable",
"body": "Your first web push notification!",
"icon": "[url-to-icon]"
},
"registration_ids": [
[array-of-push-tokens]
]
}

Successfully received notifications will appear like this:

Web push notification browser

This is a Chrome browser notification. Other browsers and devices may show these notifications differently, but the overall concept remains the same.

Notification Options

There are four noteworthy options you can use when displaying notifications:

  • body: Notification description shown below the notification title. This should give the user enough information to decide how to act on the notification. Make it useful to our users or you may miss out on subscription opportunities.
  • icon: Attaches an image to the notification to make it more appealing and relevant to our site and the user. You could make this our site icon, a user profile image, or any other type of image that uniquely identifies our website.
  • vibrate: This one's fun to play around with. Here, you can specify a vibration pattern for a mobile device receiving the notification. This is done using an array of values. For example, [100, 50, 100] would vibrate for 100 milliseconds, pause for 50 milliseconds, then vibrate again for another 100 milliseconds.
  • data: Any additional custom data you would like to pass into the browser when the user clicks on the incoming notification. This is an object that can accept a set of key/value pairs.

Some Useful Tidbits

  • The HTTPS protocol is required. You can only use web push notifications within a secure connection. Learn how to secure your website with HTTPS here.
  • It's better to use a custom popup with a friendly message and details about what they'll be subscribing to versus just showing the native "Allow" or "Block" popup in the corner initially. Doing so can help gain user trust and give them a heads up of what they're subscribing to ahead of time, allowing them to make a more informed decision. It may be a good idea to include the notification frequency; how many times we'll be submitting notifications per day, week, or month.
  • If you're going to implement this feature, it's best to use a timed popup delay or wait until the user has scrolled down a certain amount on our web page before showing them a popup. There's nothing worse than visiting a web page and getting bombarded with tons of popups and flyouts on the get-go. Make sure to keep our user's best interests in mind.

Browser Support

At the time of this writing, Chrome, Firefox, Opera, Edge, and Safari support these types of notifications.

The notifications will vary in appearance and position between the different browsers and operating systems.

Chrome for Android currently supports notifications, but Safari and Chrome for iOS do not. They don't work on iOS devices at all and there currently is no roadmap provided by Apple for this feature.

Conclusion

Web push notifications are a fantastic solution to keeping our users informed of new content or updates within our website or web application.

Just remember to keep your user's best interests in mind when implementing this feature. Don't spam them with needless messages. And make sure permission requests and popups aren't providing an overall bad user experience.

Published: January 08, 2021