Adding Push Notifications to Progressive Web App (PWA) with Ionic and Firebase Hosting.

Ankit Maheshwari
7 min readDec 13, 2019

--

We can make our product or service more re-engage-able by adding push notifications…

👨‍💻 Before adding Push Notifications I recommend you to create Ionic PWA.


To Create Ionic PWA, Click this link
👉 Build a Progressive Web App (PWA) with Ionic Framework and Firebase Hosting.

After creating Ionic PWA.

Let’s start adding Push Notifications to our Ionic PWA

We can make our product or service more re-engage-able by adding push notifications. We will add push notifications to the @ionic/angular app we created earlier. For this purpose we are going to use Firebase Cloud Messaging (FCM) as a push server to handle the delivery of notifications across platforms and devices.

The other thing that completes the push notifications implementation is an application server that will tells FCM about what notification and to whom should be delivered. There are many ways we can build that.

If we already have a backend API, then we can easily integrate Firebase SDK and problem solved.

Otherwise, if we decided to go server-less (not using a centralized server), we can use a function-as-a-service, offering like Firebase Cloud Functions that will let us run a piece of JavaScript code in the cloud, without having to care about where and how it’s executed.

For now we will just test it by hitting Firebase Cloud Messaging directly using cURL or Postman and cover later in the future articles with backend API and FCM server-less.

#1 Adding Firebase to an Angular project

First of all, we need to set up Firebase configuration in our project.
Follow the link to add Firebase — Click here 👇👇

After adding Firebase to an Angular project —

Finish the setup by importing the corresponding AngularFire modules (AngularFireMessagingModule) in our app.module.ts file:

import { AngularFireModule } from '@angular/fire';
import { AngularFireMessagingModule } from '@angular/fire/messaging';
...imports: [
BrowserModule,
AngularFireModule.initializeApp(environment.firebase),
AngularFireMessagingModule
],
...

#2 Setting up the Firebase Cloud Messaging Service Worker

Push Notifications only make sense if we are able to receive them in the background. This is possible to achieve in modern web applications using service workers — thanks to service workers.

A service worker is a piece of JavaScript code which can be run in the background, independently of the website which loaded it.

Service workers are used mostly for two things:

  • Providing caching and offline access
  • Push Notifications

In our case, we are using @angular/service-worker that comes with @angular/pwa to handle caching and offline stuff in our Ionic PWA.

Although the @angular/service-worker has utilities to handle push notifications, but instead of that we will use @angular/fire push utilities because they are specifically build to work with Firebase Cloud Messaging.

As you may know, we gets the Angular Service Worker auto-generated at build time and outputs the ngsw-worker.js (one worker) in our /dist folder.

On the other hand, by following Angular Fire documentation: we created a service worker ( firebase-messaging-sw.js ) that will just hang out in the background (even after the Ionic app has been closed by the user) waiting to detect new messages to notify the user.
To do this create and open-up your YOUR-PROJECT-DIRECTORY/src/firebase-messaging-sw.js file and add this code (second worker):

importScripts('https://www.gstatic.com/firebasejs/5.4.1/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/5.4.1/firebase-messaging.js');
firebase.initializeApp({
'messagingSenderId': ‘YOUR_SENDER_ID’
});
const messaging = firebase.messaging();

You can find your project specific SENDER_ID under your Firebase project next to Project Overview Click over Settings icon (Project Settings) Cloud Messaging look for Sender ID

Next to solve the restriction that forces us to install just one worker per application, we created a simple worker that combines the previous two (combined-sw.js).
To do this create and open-up your YOUR-PROJECT-DIRECTORY/src/combined-sw.js file and add this code (combined worker):

importScripts('ngsw-worker.js');
importScripts('firebase-messaging-sw.js');

Finally, update your app.module.ts file and register that combined worker instead:
(simply replace ngsw-worker.js with combined-sw.js in your imports property within @NgModule of app.module.ts file)

ServiceWorkerModule.register('combined-sw.js', {enabled: environment.production})

Keep in mind that we will also need to add the two new service workers manually to the project inside the production build section of our angular.json file.

"assets": [
...
"src/combined-sw.js",
"src/firebase-messaging-sw.js"
]

(This will ensure those files get copied to the output folder when building our project.)

#3 Adding required Push Notifications configuration to the Web Manifest

We will also need to add extra configuration in our web app manifest specifying the gcm_sender_id which is a hard-coded value that indicates that FCM is authorized to send messages to this app. Make sure to add the browser sender ID in your manifest.json file or manifest.webmanifest file exactly as shown (do not change the value).

{
...
"gcm_sender_id": "103953800507",
...
}

(Note: Please don’t confuse between the value of “browser sender ID” with the “project-specific sender ID” shown in your Firebase project settings. The browser sender ID for the manifest.json is a fixed value, common among all FCM JavaScript clients.) and
(
The project specific sender-id is the one we used in the previous step inside the firebase-messaging-sw.js file to initialize the firebase app. )

#4 Configure “VAPID” keys with FCM

Wait, what is VAPID?

VAPID stands for Voluntary Application Server Identification for Web Push protocol, and is a way to let publishers (like FCM) to optionally identify themselves. A VAPID key is a cryptographic public/private key pair that is used in the following way:

  • The public key is used as a unique server identifier for subscribing the user — so that notifications can be sent by the server.
  • The private key needs to be kept secret (unlike the public key) and its used by the application server to sign messages, before sending them to the Push Service for delivery.

To subscribe your Ionic framework app to push notifications, you need to associate a pair of keys with your Firebase project. To do so, open the Cloud Messaging tab of the Firebase console Settings page then scroll to the Web configuration section. Then in the Web Push certificates tab, click Generate Key Pair.
Finally, the Firebase console displays a notice that the key pair was generated, and displays the public key pair string and date added. (that’s it!)

# Requesting users permission to send them notifications…

Now we have the Firebase Messaging Service Worker setup and installed, it’s time to ask the user if he wants to receive notifications from our App. By default, the browser will popup a UI for you, but it’s highly recommend to ask the user for permission with a custom UI and only ask when it makes sense. If you blindly ask for permissions you have an extremely high chance of being rejected.

This is why we are not going to request push notifications permissions immediately after our Ionic PWA loads. We will add a button to trigger the permissions request.

Open-up and add this code in home.page.html

<ion-button (click)="requestPushNotificationsPermission()">
Enable notifications!
</ion-button>

We will use the AngularFireMessaging service to request user permission.
To do this open-up and add this code in home.page.ts

Notice that the AngularFireMessaging service requestToken function combines requesting permission and getting tokens. We need to get a token for each user in order to send them notifications.

# Finally, Sending push notifications to our Ionic PWA!

As we mentioned earlier, there are many ways you can send notifications to users from an Ionic progressive web app.

For simplicity, we will just test everything is working by hitting Firebase Cloud Messaging directly using cURL or Postman.

#1 Using cURL : Go to your terminal console and run:

$ curl -X POST \
https://fcm.googleapis.com/fcm/send \
-H 'Authorization: key=YOUR-SERVER-KEY' \
-H 'Content-Type: application/json' \
-d '{
"notification": {
"title": "Hello World",
"body": "This is Message from Admin"
},
"to" : "USER-REQUESTED-TOKEN"
}'

(You can find YOUR-SERVER-KEY under your Firebase project Cloud Messaging Settings. Next to Project Overview Click over Settings icon (Project Settings) Cloud Messaging look for Server key)

(You will get USER-REQUESTED-TOKEN from function requestPushNotificationsPermission() under home.page.ts file.)

#2 Using Postman : Install then Open Postman and enter details to call APIs:

  • Add POST URL — https://fcm.googleapis.com/fcm/send
  • Add Headers — Authorization: key=YOUR-SERVER-KEY and Content-Type: application/json
  • Add Body — Inside the body object add ‘title' and 'body' of 'notification' object
  • Add To — In ‘to' add USER-REQUESTED-TOKEN
This is how you can ‘Add POST URL’ and ‘Add Headers’
This is how you can ‘Add Body’

After doing all this — You will receive notifications when you are not active on that app page tab → that is when you are in any other tab of browser or browser is closed. Enjoy coding…!!

Sending… Receiving… Push Notification in PWA
👨‍💻 To deploy your PWA App with Push Notifications.
Click here 👉 Build a Progressive Web App (PWA) with Ionic Framework and Firebase Hosting.

Feel free to comment down in the comment box… If I missed anything or anything is incorrect or anything does not works for you :)

Stay connected for more articles:
https://medium.com/@AnkitMaheshwariIn

If you wouldn’t mind giving it some claps 👏 👏 since it helped, I’d greatly appreciate it :) Help others find the article, so it can help them!

Always be clapping…

Learn More

--

--

Ankit Maheshwari

Frontend/Backend Engineer (Angular, React Native, NodeJS, MongoDB)