DEV Community

Pato for This Dot

Posted on • Originally published at labs.thisdot.co on

PWA Push Notifications with Firebase (Cloud Messaging)-Part 1

Push Notification In Your PWA

Have you ever wondered how to add the famous/annoying push notifications to your app? Well, in this tutorial, I'm going to show you how to do it using Firebase Cloud Messaging.

Note: This tutorial requires some basic knowledge on PWAs and Service Workers.

You can take a look at my Intro to PWA and Service Workers here

and about PWA and notifications here.

Before we begin, I need to clarify that the Notification API and the Push API are not the same. People get them confused all of the time.

Push API: The Push API gives web applications the ability to receive messages pushed to them from a server whether or not the web app is in the foreground or currently loaded on a user agent. This lets developers deliver asynchronous notifications and updates to users that opt in resulting in better engagement with timely new content.

Let's do it!!

The final code is in the FINAL branch inside of the repo.

  1. Clone this repo: https://github.com/devpato/pwa-FCM-notifications-tutorial

As you can see, I already have the basic structure of the app created for you because we are only going to worry about how to send the messages via push notifications using the Firebsae Cloud Messaging service.

  1. Navigate to the index.html file. Notice I imported Firebase for you:
<script src="https://www.gstatic.com/firebasejs/7.6.1/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/7.6.1/firebase-messaging.js"></script>

Enter fullscreen mode Exit fullscreen mode


javascript

  1. Navigate to Firebase.com and create an account if you don't have one.
  2. Once you are in the Firebase console, navigate to project settings (in case you don't have a project yet - just create it there)

pwa

  1. Inside of project setting, under the General tab scroll all the way down to find your Firebase SDK snippet (if it's not there yet - this means that you've created a new project and need to add an app there. Either way, this can be done at the same place where you will have your SDK snippet - under the General tab ). Copy/paste it in a safe place. The snippet should look like this:

pwa1

  1. Go to your index.js file and copy/paste the following after the global variables that I have declared for you. Replace it with your project's customized code - the snippet from step 4.
const config = {
  apiKey: "XXXXXXXXXXXXXXX",
  authDomain: "XXXXXXXXXXXXXXX",
  databaseURL: "XXXXXXXXXXXXXXX",
  projectId: "XXXXXXXXXXXXXXX",
  storageBucket: "XXXXXXXXXXXXXXX",
  messagingSenderId: "XXXXXXXXXXXXXXX",
  appId: "XXXXXXXXXXXXXXX",
  measurementId: "XXXXXXXXXXXXXXX"
};

Enter fullscreen mode Exit fullscreen mode


javascript

  1. Right after - initialize the firebase instance.
firebase.initializeApp(config);

Enter fullscreen mode Exit fullscreen mode
  1. Then, we are going to create a constant called messaging and will set it to firebase messaging service.
const messaging = firebase.messaging();

Enter fullscreen mode Exit fullscreen mode
  1. Time to request permission from firebase cloud messaging. Once we get the thumbs up, they will give us a token as a promise.
messaging
  .requestPermission()
  .then(() => {
    message.innerHTML = "Notifications allowed";
    return messaging.getToken();
  })
  .then(token => {
    tokenString.innerHTML = "Token Is : " + token;
  })
  .catch(err => {
    errorMessage.innerHTML = errorMessage.innerHTML + "; " + err;
    console.log("No permission to send push", err);
  });

Enter fullscreen mode Exit fullscreen mode
  1. Then, we are going to use the messaging.onMessage() method. This is used for receiving data and notification payloads by all users that are currently viewing the page (the page is in the foreground).

To do so, we add the following code:

messaging.onMessage(payload => {
  console.log("Message received. ", payload);
  const { title, ...options } = payload.notification;
});

Enter fullscreen mode Exit fullscreen mode
  1. Notice a firebase-messaging-sw.js file. This file name is going to be searched by the Firebase SDK. The file needs to be in the ROOT of your project. The Firebase SDK will do some magic in the background to register the file as a service worker.
  2. Inside of your firebase-messaging-sw.js, initialize the Firebase app by passing in the messagingSenderId. The sender ID can be found inside of your project settings as the following image shows.

Screenshot 2020-01-28 at 1.35.19 AM

firebase.initializeApp({
  messagingSenderId: "XXXXXXX"
});

Enter fullscreen mode Exit fullscreen mode
  1. Retrieve an instance of Firebase Messaging so that it can handle background messages.
const messaging = firebase.messaging();

Enter fullscreen mode Exit fullscreen mode


javascript

  1. Background message handler (this one will be invoked when the page is in the background)
messaging.setBackgroundMessageHandler(payload => {
  const notification = JSON.parse(payload.data.notification);
  const notificationTitle = notification.title;
  const notificationOptions = {
    body: notification.body
  };
  //Show the notification :)
  return self.registration.showNotification(
    notificationTitle,
    notificationOptions
  );
});

Enter fullscreen mode Exit fullscreen mode

Test The Notification

  1. Run the app using any http server
  2. Inside of your Cloud Messaging settings (a tab in the Firebase Console > Project Settings) copy the server key.

Screenshot 2020-01-28 at 1.35.19 AM

  1. If you have a Postman http client, do the following:

Screenshot 2020-01-28 at 1.40.09 AM

POST URL:* https://fcm.googleapis.com/fcm/send *

HEADERS:
Content-Type - application/json

Authorization - key=server_key

BODY:

{
    "notification": {
        "title": "Testing Notification!",
        "body": "Firebase is awesome",
        "click_action": "http://127.0.0.1:5501/index.html",
        "icon": "http://the-link-to-image/icon.png"
    },
    "to": "YOUR TOKEN GOES HERE"
}

Enter fullscreen mode Exit fullscreen mode

Then, click the Send button. At this point, if our app is in the foreground (it is currently opened tab in your browser) then you'll see the message we've sent in the console - handled by messaging.onMessage.

But if it is in the background, it will be handled by messaging.setBackgroundMessageHandler in the service worker and you'll see something like this:

Screenshot 2020-01-28 at 1.45.48 AM

Test your app on a real device by deploying to Firebase or any other hosting provider. If you want to host your app on the Firebase - take a look at my other tutorial.

In the next tutorials, I will show you how to successfully subscribe to notifications and push them using the Firebase console.

This Dot Inc. is a consulting company which contains two branches: the media stream, and labs stream. This Dot Media is the portion responsible for keeping developers up to date with advancements in the web platform. This Dot Labs provides teams with web platform expertise, using methods such as mentoring and training.

Top comments (8)

Collapse
 
joakflores profile image
Joak

Hi, thanks for share.
I have some issues, could you help me please?

I have tried with CDN

In the line
firebase.initializeApp(config);

I have gotten the error "firebase is not defined

So, I copied the 2 files (firebase-apps.js & firebase-messaging.js into my carpet js and I have gotten the same error.

what's wrong?

Collapse
 
devpato profile image
Pato

Can you send me a link to your repo?

Collapse
 
joakflores profile image
Joak

Maybe I found the error, please give me if I'm right ....

1) This code has to be on service worker, right?
var firebaseConfig = {
apiKey: "xxxxx",
authDomain: "xxxxx",
databaseURL: "xxxxx",
projectId: "xxxxx",
storageBucket: "xxxxx",
messagingSenderId: "xxxxx",
appId: "xxxxx",
measurementId: ""
};
firebase.initializeApp(firebaseConfig);

2) Firebase seek a specific service worker name in the app? , I have one with the name sw.js, that name works?

Regards

Collapse
 
_nsvetlanav_ profile image
Наговицына Светлана • Edited

Help me please. I did everything according to the instructions. A window appears with the text allow or block notifications. I click on allow or block, an error appears in the console
dev-to-uploads.s3.amazonaws.com/i/...

Collapse
 
akattack profile image
AkAttack

you need to check your html file and make sure that the -->



is present, then check your index.js file and make sure you see -->

const errorMessage = document.getElementById("error");
Collapse
 
orimdominic profile image
Orim Dominic Adah • Edited

Thanks man! I got stressed at one other tutorial I was using. This was well explained. I was able to achieve my goal reading and following through with this.
Thanks again.

One thing though, you can style the code in your markdown by typing the language e.g javascript, typescript, after the first triple quotes. For example
'''javascript. It helps with readability

Collapse
 
after_ui profile image
After UI

Hi, I have two environment staging and production, how do I make this service worker use the correct firebase config based on environment? i try with import xxx from '../myFirebaseConfig' and process.env but it doesnt work in a public folder.

importScripts('gstatic.com/firebasejs/7.14.5/fire...)
importScripts('gstatic.com/firebasejs/7.14.5/fire...)

firebase.initializeApp({
apiKey: ‘xxx’,
authDomain: ‘xxx’,
databaseURL: ‘xxxx’,
projectId: ‘xxx’,
storageBucket: ‘xxxx’,
messagingSenderId: ‘xxxx’,
appId: ‘xxxxx’,
measurementId: ‘xxxx’
})

const messaging = firebase.messaging()
..

…. other code

Some comments may only be visible to logged-in visitors. Sign in to view all comments.