Our experience with implementing Web Notifications using Firebase Cloud Messaging

Filip Procházka
Oct 24, 2016 · 5 min read

Downstream cloud messaging has been here for quite a long time, for me as a Google-ecosystem-oriented developer, mostly in the form of Google Cloud Messaging. With the release of Firebase platform at Google I/O 2016, FCM was introduced. It is basically GCM under a yellow coat. Unfortunately, for web developers it was available only for Android and iOS, but this week at the Polymer summit they released FCM library for the web. We were collaborating with Google prior to release and have already implemented FCM in our app Settle Up. Let’s see how easy it is.

Vanilla JS

First, let’s see how to implement FCM with pure Javascript, next we will look at how it can be simplified with Polymerfire, an awesome set of Polymer Web Components.

I will assume you have already set up the Firebase JS SDK and have updated to the latest version so you can use FCM. If not, Google has made a good tutorial about this, available here.

The next step is to make sure you have gcm_sender_id in your manifest.json. Be aware that this ID is fixed and the value at the time of writing is: “103953800507”. After this we can move to the Service Worker part. In the root of your app, create a new file called firebase-messaging-sw.js with following contents:

/*
Give the service worker access to Firebase Messaging.
Note that you can only use Firebase Messaging here, other Firebase libraries are not available in the service worker.
*/
importScripts('https://www.gstatic.com/firebasejs/3.5.0/firebase-app.js')
importScripts('https://www.gstatic.com/firebasejs/3.5.0/firebase-messaging.js')

/*
Initialize the Firebase app in the service worker by passing in the messagingSenderId.
*/
firebase.initializeApp({
'messagingSenderId': 'YOUR-SENDER-ID'
})

/*
Retrieve an instance of Firebase Messaging so that it can handle background messages.
*/
const messaging = firebase.messaging()
messaging.setBackgroundMessageHandler(function(payload) {
console.log('[firebase-messaging-sw.js] Received background message ', payload);
// Customize notification here
const notificationTitle = 'Background Message Title';
const notificationOptions = {
body: 'Background Message body.',
icon: '/firebase-logo.png'
};

return self.registration.showNotification(notificationTitle,
notificationOptions);
});

This way, when an FCM message is received, a generic notification will be displayed (if permission was granted by user).

App Implementation

Let’s move to implementing the flow of registering notifications in your app. You need to get through the following steps:

  1. Request user permission (good practice to show your custom UI first).
  2. Retrieve obtained FCM token.
  3. Send FCM token to your server.
  4. Receive notifications while your app is in the foreground (OPTIONAL).

User’s permission

We need to get the user’s permission in order to start sending them notifications.

function showNotificationPermission () {
messaging.requestPermission()
.then(() => {
console.log('Notification permission granted.')
})
.catch((err) => {
console.log('Unable to get permission to notify. ', err)
})
}

This may seem as the simplest of all but you must understand how important this is to your app. Let’s look at the notification permission prompt in Chrome.

In this example, Facebook is showing the prompt without asking you first

There are two main problems with it. First, it does not explain why you want that, so the user may easily skip it. Second and maybe even more serious problem is that upon clicking “Block” in the notification prompt, don’t ever believe the user will enable notifications later because from now on, you can’t show this prompt and for the user to allow this prompt to show, they would have to click on the icon in the address bar before the domain name.

The result? Annoying your users with this notification prompt will result in large amounts of users blocking notifications for good.

Solution? A custom prompt shown in your app before showing the browser prompt.

Here you can see our custom notification prompt

Retrieving FCM token and sending it to your server

So now that you have the user’s permission you need to save the FCM token on your backend to send notifications to users.

messaging.getToken()
.then((currentToken) => {
if (currentToken) {
sendTokenToServer(currentToken)
} else {
// you don't have permission to show notifications
// detect whether they are blocked or not, then show your custom UI
}
})
.catch((err) => {
// retrieving token failed, analyze the error
})

As you can see, it can be also used as a detection method for whether the user granted you the permission for notifications. Also, it’s important to make sure you are monitoring the tokenRefresh to update the token on your server (you can find this in official documentation here).

Receiving notifications in foreground

The last part, which is optional but in my opinion really important, is to also show notifications in your UI when the user is using your app. It may have different forms or you may just use it to sync with the server and then update the UI.

messaging.onMessage((payload) => {
// message received
})

Background sync

In our app, in order to show customized notifications, not just the generic one (which extremely decreases user engagement), we need to sync with our backend before showing it which is painful. However awesome, Service Workers are also quite limited in many things. For example, you can’t access cookies and localstorage (thankfully, Indexed DB is accessible) and there are some limitations on how to handle network requests.

The best practice here is to send the notification content with FCM so that you don’t have to sync data before showing a notification but due to some limitations on our server we couldn’t do it that way all the time.

Our notification

Polymerfire

The VanillaJS implementation is quite long and you have to solve a lot of things, how about a much simpler way?

Firebase + Polymer = Polymerfire

If you haven’t heard of Polymer (you probably still live in a cave) be sure to check it out (link). Basically it’s a library built on top of the new Web Components standard to simplify the development of apps on the web. With this awesome way to build web apps, we can utilize the awesome set of components that Google prepared for Firebase called Polymerfire.

The implementation of FCM using Polymerfire is super easy, you just need your Service Worker to show notifications (can be the same as in VanillaJS) and then only add the “firebase-messaging” component in your app. You then simply call requestPermission() as you need to request the permission from the user. Everything else is handled automatically and you are ready to go. The fcm token is then available as a property of the component.

The component

<firebase-messaging
id="messaging"
on-message="_onFcmMessage"
token="{{token}}">
</firebase-messaging>

Requesting permission

// messaging is firebase-messaging web component
messaging.requestPermission()

You still have to persist the token to the database, you can use firebase-document for that

<firebase-document
path="/path/to/store/the/token"
data="[[token]]">
</firebase-document>

Receiving messages

_onFcmMessage (message) {
// handle your message here
}

So that’s it!

Push notifications are really useful to drive user engagement as we learned from implementing them. Make sure to A/B test and also think first about your users and how they will react when designing your notifications and prompts.

Step Up Labs

Company blog of Step Up Labs, developers of Settle Up.

Thanks to David Vávra and Bára Drbohlavová.

Filip Procházka

Written by

Czech, love travelling, cooking, developing mobile apps at Ubiquiti Networks

Step Up Labs

Company blog of Step Up Labs, developers of Settle Up.