5

I am testing out the Firebase Cloud Messaging function in my React app which was bootstrapped with create-react-app. Note that I have already intialized firebase (including admin SDK on server-side) properly and my client side is deployed on https. What I did so far was to:

  1. Initialize firebase messaging in firebase.js, and also request for notification permission and listen out for onMessage event
const messaging = firebase.messaging();
messaging
  .requestPermission()
  .then(() => {
    console.log("Permission granted!");
  })
  .catch(() => {
    console.log("Permission denied!");
  });

messaging.onMessage(payload => {
  console.log("onMessage: ", payload);
});
  1. Create service worker file firebase-messaging-sw.js in public directory
importScripts("https://www.gstatic.com/firebasejs/4.8.1/firebase-app.js");
importScripts("https://www.gstatic.com/firebasejs/4.8.1/firebase-messaging.js");

var config = {
  messagingSenderId: <messageID hidden>
};
firebase.initializeApp(config);

const messaging = firebase.messaging();

  1. I read from another Stackoverflow post that with create-react-app post that this was also necessary to include in index.js
if ("serviceWorker" in navigator) {
  navigator.serviceWorker
    .register("../firebase-messaging-sw.js")
    .then(function(registration) {
      console.log("Registration successful, scope is:", registration.scope);
    })
    .catch(function(err) {
      console.log("Service worker registration failed, error:", err);
    });
}
  1. To test out the messaging easily, I added a button in Main.js that will send to my server the token on click (and then the server will proceed to send the message)
const handlePushButtonClick = () => {
    messaging.getToken().then(token => {
      axios.post(<Server link hidden>, {
        token
      });
    });
  };
  1. I then set up the necessary route in my express server like this
app.post("/api/push", async (req, res) => {
    const registrationToken = req.body.token;
    var message = {
      data: {
        score: "850",
        time: "2:45"
      },
      token: registrationToken
    };
    fb.admin
      .messaging()
      .send(message)
      .then(response => {
        console.log("Successfully sent message:", response);
        res.sendStatus(200);
      })
      .catch(error => {
        console.log("Error sending message:", error);
      });
  });

Here's the issue, I have verified that my server is successfully receiving the token and in fact has successfully sent the message but on my client-side, I am not receiving the onMessage payload object at all.

Recall from my code that what I expect to receive on my client side dev console is a console.log with onMessage and the payload.

messaging.onMessage(payload => {
  console.log("onMessage: ", payload);
});
halfer
  • 19,824
  • 17
  • 99
  • 186
agreatkid
  • 93
  • 2
  • 4

3 Answers3

4

Simple solution to this is update your Firebse to latest versions.

eg.

importScripts('https://www.gstatic.com/firebasejs/7.8.0/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/7.8.0/firebase-messaging.js');

Note: Once you have updated your firebase libraries versions then messagingSenderId will not work in your firebase-messaging-sw.js file. You have to provide all other params eg. apiKey, projectId, appId along with messagingSenderId.

Eg.

Replace this in your firebase-messaging-sw.js

firebase.initializeApp({
    messagingSenderId: "Sender ID"
});

With this

firebase.initializeApp({
        apiKey: "api-key",
        authDomain: "project-id.firebaseapp.com",
        databaseURL: "https://project-id.firebaseio.com",
        projectId: "project-id",
        storageBucket: "project-id.appspot.com",
        messagingSenderId: "sender-id",
        appId: "app-id",
});
  • If still not work. Clean your browser cache and re-register service worker.
Maheshvirus
  • 6,749
  • 2
  • 38
  • 40
  • But background notifications from the service worker **do work** with the messagingSenderId alone. – andreszs Feb 18 '20 at 06:15
  • 2
    @andreszs If you update your firebase sdk to latest(firebasejs/7.8.0/firebase-app.js' & firebasejs/7.8.0/firebase-messaging.js). It will show you error. Kind of project id is missing in SW. To fix that you need to add rest of the details. And it is tested. – Maheshvirus Feb 19 '20 at 06:06
  • And to trigger onMessage event you must update your Firebase SDK. – Maheshvirus Feb 19 '20 at 06:08
  • same issue on 9.6.1 – Aadam Jan 06 '22 at 22:52
  • Can you please answer this? https://stackoverflow.com/questions/73019796/initialize-firebase-config-inside-the-service-worker-file-in-public-folder – Inaara Kalani Jul 22 '22 at 06:18
0

I have figured out my mistake. I was initially following this guide: https://firebase.google.com/docs/cloud-messaging/js/topic-messaging. My mistake was previously not very clear to me as I followed the tutorial, but that's probably because I am quite unfamiliar with the notifications and push web APIs.

The tutorial's message object had a data object inside it:

var message = {
  data: {
    score: '850',
    time: '2:45'
  },
  token: registrationToken
};

Turns out that if I wanted to send a data payload in the message, I needed to include this bunch of code in my firebase-messaging-sw.js (this bit wasn't shown in the tutorial I linked):

messaging.setBackgroundMessageHandler(payload => {
  const title = payload.data.title;
  const options = {
    body: payload.data.score
  };
  return self.registration.showNotification(title, options);
});

Note that the above code in the service worker file is only necessary if you want to send a data payload (which you can thereafter flexibly manipulate in the service worker file). If all you need is to send a notification, your message object should instead simply include a notification object (that can accept only some fixed keys):

var message = {
  notification: {
    title: '850',
    body: '2:45'
  },
  token: registrationToken
};
agreatkid
  • 93
  • 2
  • 4
  • There should be same payload for both foreground and background.You are suggesting two different solutions for Notification. As per your logic if you want to send foreground messages needs to use notification payload. And for background messages needs to use data payload. But this solution is not ideal. Go with above solution you will achieve both by only data payload. – Maheshvirus Feb 19 '20 at 06:47
0

In case the answer provided by Maheshvirus doesn't work for someone, here is the latest version for Firebase that worked for me.

importScripts('https://www.gstatic.com/firebasejs/9.0.0/firebase-app-compat.js');
importScripts('https://www.gstatic.com/firebasejs/9.0.0/firebase-messaging-compat.js');

Again, you'll have to initialize Firebase App with all the details for this to work.

Inaara Kalani
  • 265
  • 7
  • 24