Firebase

Web app push notification with Firebase

Push Notifications with Firebase

Firebase platform offers various services for mobile and web  applications to help developers to build apps quickly with lots of features. We will use Cloud Messaging service provided by Firebase platform which allows us to send messages to any device using HTTP requests.

Setup

To start using Firebase, we first need to have a Firebase account and create a new project or use existing project within it.
Here we are build web app with React Js using create-react-app.
After React app has been created, we need to add Firebase library to the project.

npm install firebase --save

Dive in

After the project has been setup, we will now start coding notification module.
For that, create new file called pushNotification.js and add a function to initialize Firebase in our project.

import firebase from 'firebase/app';
import 'firebase/messaging'

const config = {
apiKey: "Firebase-App-API-KEY",
authDomain: "YOUR-APP.firebaseapp.com",
databaseURL: "YOUR-APP.firebaseio.com",
projectId: "YOUR-APP-ID",
storageBucket: "YOUR-APP.appspot.com",
messagingSenderId:"MESSAGING-ID"
};

export const initFirebase = () => {
firebase.initializeApp(config);
}

You can get the config details from Firebase Console in the project settings. Under General tab, click on Add Firebase to your web app

Now we need to call this method at the entry point of our project. In my case, I included this in my index.js file as it is the entry point to my project.

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { BrowserRouter } from 'react-router-dom';
import {initFirebase } from './pushNotification';

initFirebase();
ReactDOM.render(<BrowserRouter>
<App />
</BrowserRouter>, document.getElementById('root'));

Requesting permissions to send notification

As a user, it may feel annoying for some to get popup message notifications while accessing web apps. So we will let the user to choose weather or not to receive notifications. For that we will add a function that will request user’s permission to receive push notification and request and return user’s token after getting approval from the user. We will add that function to pushNotification.js

export const permissionToReceiveNotification = async () => {
try {
const messaging = firebase.messaging();
await messaging.requestPermission();
const token = await messaging.getToken();
return token;
} catch (error) {
console.error(error);
}
}

We  need to call this function so that we will be able to push notification to the app. Here I have called this function after the App component have been mounted. In App.js include and call this method.

import {permissionToReceiveNotification } from './pushNotification';

componentDidMount(){
permissionToReceiveNotification()
}

Now lets test our app. Start our app and you must get a popup requesting for the permission to receive push notifications. On accepting the request, browser will request and return the user token.

Service Workers

Before being able to receive message notifications,  our app needs a service worker to receive the onMessage event. By default, on start up, Firebase looks for the file called firebase-messaging-sw.js. It will import the scripts needed to show the notifications when our app in in background.

We need to create a file called firebase-messaging-sw.js, with the folowing content

importScripts('https://www.gstatic.com/firebasejs/4.8.1/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/4.8.1/firebase-messaging.js');
firebase.initializeApp({
messagingSenderId: "your messagingSenderId again"
});
const messaging = firebase.messaging();

Sending notifications

To send notification, we have to make request to the Firebase API with the token of the user who will receive the notification
We have to make a POST request to https://fcm.googleapis.com/fcm/send with JSON request body.
The structure of the JSON body will be like below

{
"notification": {
"title": "Firebase Notification",
"body": "Firebase notification content",
"click_action": "http://localhost:3000/",
"icon": "http://localhost:3000/favicon.ico"
},
"to": "USER-TOKEN"
}

And we must pass server key in our request header along with content type.

POST https://fcm.googleapis.com/fcm/send
Content-Type: application/json
Authorization: key=SERVER-KEY

We can find server key in the project settings in the Firebase Console under Cloud Messaging tab.

Send Notifications to group

We just sent notification to a single user. But its not always the single user we need to send the notification. In practical world, there won’t be only one or few users to send notification. There will be large number of users to  whom we have to send notifications which becomes impractical and not feasible to send notifications individually.

For that, Firebase has a feature called topic which accept multiple tokens and send same notifications to all of them in single request. To send notification based on topic, user must first subscriber to the topic. For subscription, user needs to subscribe to the topic after requesting the token. We will create a function that sends a POST request to https://iid.googleapis.com/iid/v1/USER_TOKEN/rel/topics/TOPIC-NAME with user token and topic to subscribe along with server key in request header.

export const subscriberToTopic = (token,topic) =>{
    fetch('https://iid.googleapis.com/iid/v1/'+token+'/rel/topics/'+topic, {
        method: 'POST',
        headers: new Headers({
            'Authorization': 'key=AAA.......gKlGH'
        })
    }).then(response => {
        if (response.status < 200 || response.status >= 400) {
            throw 'Error subscribing to topic: '+response.status + ' - ' + response.body;
        }
        console.log('Subscribed to "'+topic+'"');
    }).catch(error => {
        console.error(error);
    })
}

And call this functin after the token is returned after token request inside permissionToReceiveNotification() function.

export const permissionToReceiveNotification = async () => {
try {
const messaging = firebase.messaging();
await messaging.requestPermission();
const token = await messaging.getToken();
subscriberToTopic(token,'some-topic');
return token;
} catch (error) {
console.error(error);
}
}

It will subscribe the user to a topic after a user requests a token.
Sending notifications to the users subscribed to specific topic is similar to sending notifications to specific user. Only difference is that we pass topic name in to parameter instead of user token.

{
    "notification": {
        "title": "Message Title",
        "body": "Message body",
        "click_action": "http://localhost:3000/",
        "icon": "http://localhost:3000/favicon.ico"
    },
    "to": "/topics/"
}
POST https://fcm.googleapis.com/fcm/send
Authorization:key= SERVER KEY
Content-Type:application/json