Progressive Web App Push Notifications: Making the Web App more Native in Nature

Tarique Ejaz
Nov 5, 2017 · 9 min read

Note: This implementation of native and web push notifications makes use of version 4.0.0-rc.1 of AngularFire2 library.

Beyond The Rack push notifications example (Courtesy Google Developers)

Progressive Web Apps are here to stay. If you have been one of those people living under a shell, oblivious of what PWAs (as it is fondly referred to) are, you need to check up on it at the earliest. As described in this article
https://www.smashingmagazine.com/2016/08/a-beginners-guide-to-progressive-web-apps/.

A progressive web application takes advantage of the latest technologies to combine the best of web and mobile apps. Think of it as a website built using web technologies but that acts and feels like an app.

That should be enough to whet your appetite for the evolving voodoos of web technologies. The main purpose I decided to talk about PWAs in particular was to help one and all struggling with implementing push notifications on mobile as well as web interfaces through a Progressive Web App.

Push Notifications

Push. Push. Back upon now. (Courtesy Enrique Iglesias)

Push notifications help to engage users to an application and it is this very feature that compels you and I to keep checking out our WhatsApp account for a new message or two or maybe more, every now and then. We are all aware of push notifications being a thing for native applications built on Android or iOS. But what about the ones meant for a website that refuses to discriminate between the devices it happens to be called upon? Well, with the presence of service workers, native notification experience has become an easy reality and you can just as easily call it a thing for web apps like I had mentioned earlier for the more native platforms.

Have I caught your interest already? Let’s try and implement this feature for a small application and make an attempt to get ourselves engaged. (Not in the marital sense, of course)

How it Works

  • The web app asks the user to subscribe to the notifications
  • Using the Firebase Cloud Messaging APIs or a similar service, a unique token for each device and session is generated
  • The service worker’s push manager is responsible for handling the subscription
  • The unique token is used whenever a message is posted from the application, either through an action or event
  • The service worker, with the help of the push listens and is ready to receive any message coming in

Sounds easy-peasy. Enough theory for now, let’s make an app.


Making a Push Happen

I won’t go into the nitty-gritty of angular applications. Let us leave that for some other time. You can find the code here but an ‘important’ key is missing from the app, thereby, preventing it from running. Muahahaha. Pardon the mock laughter. You can find the code here, like seriously.
https://github.com/tarique93102/angular-concepts/tree/master/pwa-push-firebase-app

Let’s start.

  1. Firebase Configuration

Setting up your project in Firebase in a simple process and I am going to walk you through it.

You first visit the Firebase console website at https://console.firebase.google.com and sign in or sign up with your Google account.

Having completed the log in/sign up process, you will be redirected to the dashboard page. Create a new project named anything you want or a name that aptly refers to your project, for example: my-pwa-first-notification. See. I am pretty jazzy with names by the way.

Firebase Console Dashboard

Once you open up your Firebase project, you need to procure the API configurations for your web application. You can find it by clicking on the ‘Add Firebase to Your Web App’ option in the project overview page.

Firebase Project Overview
Firebase API configuration for my Web App named my-pwa-first-notification

Make a note, memorize or just save the details somewhere since it would come in handy soon as we start configuring our application for generating notifications. I have kept my API key hidden for security reasons, of course, since I am an insecure person at times.

We need to do two more things before we start configuring our Angular application. First, we procure the server key to be used later on for sending requests.

We click on the tiny gear icon next to the Project Overview tab on the left side panel. Then we click on Project Settings and navigate to the Cloud Messaging tab to obtain the Server Key.

Server Key is obtained from here

All we have to do now is alter the Firebase Database rules to enable us to write into and read tokens while the push notification operation happens. In order to do so, navigate to Develop > Database > Rules, starting from the left side panel. In the rules, just change the property values for the keys ‘.read’ and ‘.write’ to true.

Database rules needs to be changed

Voila! We are done setting up our Firebase application. Lets jump into configuring our angular application.

2. Angular Application Configuration

After creating the basic structure of the app through ng new <app-name> keyword, you need to first install the AngularFire2 library and firebase module. (As mentioned earlier we will be using the version 4.0.0-rc.1)

npm install --save angularfire2@4.0.0 firebase@4.3.0

Create a service worker named firebase-messaging-sw.js in the /src directory and add the following code.

Okay. So we have our service worker in place. Go ahead and add the service worker file in the .angular-cli.json of the application.

"assets": [
"assets",
"favicon.ico",
"firebase-messaging-sw.js"
],

In tsconfig.json, add a types array with firebase as an element

"types":[
"firebase"
]

Go ahead and create a manifest.json file in the /src directory and add the browser sender ID as is provided. Note: Do not use any other ID for browser sender apart from the one mentioned.

{
"name": "PWA-Push-Firebase-App",
"gcm_sender_id": "103953800507"
}

Call the manifest.json file in the index.html page with a script tag to register it. Take the Firebase API configuration for Web App as mentioned earlier and add it to a new file called firebase.config.ts, created in the /src/environments folder. Your firebase config would appear something like mine, mentioned below.

export const firebaseConfig = {
apiKey: '<enter you api key here>',
authDomain: 'my-pwa-first-notification.firebaseapp.com',
databaseURL: 'https://my-pwa-first-notification.firebaseio.com',
projectId: 'my-pwa-first-notification',
storageBucket: 'my-pwa-first-notification.appspot.com',
messagingSenderId: "1019013830321"
}

Psst! I have not mentioned my API Key. So use yours. Okay? Good Boy!

Make a call to the firebase.config.ts file in your app.module.ts file in /src directory.

We will call the messaging API through AngularFire2 library in app.component.ts as follows

Now we call the separate functions for token ID instance generation, duplication check and Firebase database operations. All these operations are called in the app.component.ts. The points at which they are called are mentioned. (These functions are called for a smooth operation to happen and for you to visualize and understand how the keys are being used and generated)

2.1. Check for Token Refresh (constructor())

2.2. Obtaining Firebase Data and extracting to an Array (constructor())

2.3. Check for Existing Tokens (AppComponent Class)

2.4. Request for Permission, Token Fetch, Check and Store (ngOnInit())

2.5. Handle Incoming Messages and Payload (ngOnInit())

That was quite a lot of code there. Phew! Trust me when I say that we are almost done. Just the main part is left. The part we had been eagerly waiting for. The part where we PUSH.

3. Push Generation

Oh Yeah.

After completing the configuration for connecting firebase to your Angular application, we are now more than ready to configure the main push requirements. Yaay!

We start off by creating a push service, lets call it push.service.ts for example and add the service as a Provider in the main App module. (app.module.ts) Then we create a notification object, which looks something like this.

pushData: any = {
'notification': {
"title": "Background Message Title",
"body": "Background Message Body"
},
"to": ""
}

We have decided to call the object as pushData but you can choose to call it anything you feel which suits your need. The ‘to’ key refers to the device specific token to which the push is triggered to.

Create a method in the push.service.ts file to refer to the push being triggered and the message being sent using Angular’s http service. You need to provide your respective server key in the headers. This key is required to hit the Firebase API and is obtained from Firebase Console as shown earlier.

generatePush(pushData) {
let headers = new Headers({ 'Content-Type': 'application/json', 'Authorization': 'key=<add your server key here>'});
let options = new RequestOptions({ headers: headers });
return this.http.post('https://fcm.googleapis.com/fcm/send', pushData, options)
.map(data => {console.log("Successfully Sent")});
}

Now, we make a call to the generatePush function in app.component.ts by invoking the push.service.ts file and trigger the push notification.

generatePush() {
if (this.pushData.to === "") {
console.log("No token available");
return;
}
this.pushService.generatePush(this.pushData)
.subscribe(data => { console.log("Succesfully Posted") }, err => console.log(err));
}

We have setup our application for triggering push notifications. It is properly configured (which I am pretty sure of) and now we will make use of something called Postman to trigger the notification and see the magic happen. We will also trigger the push notification directly from the application to make sure that the functions we have linked and the push cloud API of firebase actually works.

Postman — The Delivery Application (Chrome Extension)

If we run the angular application using ng serve we would see something like this come up on http://localhost:4200

The application works. This is how it appears.

4. Getting The Deed Done

Let’s test first whether the push is working and our application is ready to handle it. In the Angular application, click on the Generate Push button to see the notification appear as a payload in the console.

The message appears in the console. It works!

Next up, we open up Postman and put in the following headers in the Headers section.
1. ‘Content-Type’: ‘application/json’
2. ‘Authorization’: ‘key=<add your server key here>

Add the object to be sent via POST request in the Body section in the following manner.

And the object is keyed in

Click on the SEND button and see the magic happen.

TAN TA DAN!

You can also trigger a push notification by using the curl command in Git Bash or any Linux based terminal. You have to use the following command.

curl -H "Content-Type: application/json" -H "Authorization: key=<enter your server key>" -X POST -d '{"notification": {"title": "Yo Yo PWA Singh", "body": "Push notification works!!"}, "to": "<enter device token>"}' https://fcm.googleapis.com/fcm/send

This command will trigger a notification as shown earlier.

Note: The notification will come up separately by the right bottom of the screen if and only if the tab containing the application is minimized. And yes, it works like a native notification on a mobile device.

Now you know the mantra to trigger a push notification. If you have followed the article to the tee, I doubt you would have any issues. STILL if your application happens to break at any point you can easily refer the Github code or you can comment your concern and I will try to get back to you.


Push notification is an essential feature of native applications and with Progressive Web Apps coming in, web applications have gained the ability to function like native applications. We can only await and see what lies in store for this technology and its future applications.

The future looks bright

For now, it sure does appear bright.

Tarique Ejaz

Written by

I code, read, write and simply aspire to be a better individual than the one I am today.