0

Is it possible to send FCM notifications through Firebase Cloud Functions, when a Firestore data field changes, but for a website, not an app. There is lots of guidance out there for Android and iOS but nothing for simply web apps, outside of sending notifications from the Firebase Console).

I've been trying to find out how to trigger a notification from Cloud Functions but can't find anything useful.

As an example, my database has the following structure:

  • Collection: users
  • Documents: documents named using userID
  • Data Fields: Fields 1 through 5. Field 5 stores the FCM Token. Field 1 stores their status (online, offline, offline pending messages).

I would like to ensure that when Data Field 1 changes (to 'offline pending messages), that the relevant user gets notified (based on the Doc ID).

Edit: adding code below for reference

const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.sendNotification = functions.database.ref('/users/{doc}/{Hears}')
    .onUpdate(async (change, context) => {

        const db = admin.firestore();
        db.collection('users').doc(context.params.userId)  // get userId
        .get()
        .then(doc => {
            //this is intended to get the FCM token stored in the user's document
           const fcmToken = doc.data().usrTkn;
           // Notification details
            const payload = {
            notification: {
                title: 'You have a new message.',
                body: 'Open your app'
            }
        };
     })
    //This should send a notification to the user's device when web app is not in focus. 
    //FCM is set up in service worker
     const response = await admin.messaging().sendToDevice(fcmToken, payload);
     console.log(response);

    });
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
user3385829
  • 117
  • 1
  • 9

1 Answers1

2

Sending messages to a web app is no different from sending it to a native mobile app, so the sending part of guidance you've found is equally applicable. The Firebase documentation even contains an example of sending notifications on a Realtime Database trigger, and doing the same for Firestore would not be much different.

If you're having a specific problem sending messages, I recommend showing what you tried, and what isn't working about it.


Update: your code doesn't work (no matter what sort of device you send the notification to), because you're not handling the asynchronous nature of get() in your code.

The simplest way to fix that is to use await there too, just like you do when calling sendToDevice. So:

const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.sendNotification = functions.database.ref('/users/{doc}/{Hears}')
    .onUpdate(async (change, context) => {
        const db = admin.firestore();
        const doc = await db.collection('users').doc(context.params.userId).get();
        const fcmToken = doc.data().usrTkn;
        const payload = {
          notification: {
            title: 'You have a new message.',
            body: 'Open your app'
          }
        };
        const response = await admin.messaging().sendToDevice(fcmToken, payload);
        console.log(response);
    })

I highly recommend spending some time on learning about asynchronous calls, closures, async/await, and how to debug something like this by adding logging.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • Thank you for looking into this, Frank. I gave it a shot and the function got deployed but I don't get the intended notification I was hoping for when I test out an update on the user doc ('Hear' data field). Not even a console log when I'm in the window (I tested the FCM notifications through the firebase console and it works just fine there). – user3385829 Jun 07 '21 at 02:35
  • It's going to be hard to help further with that here. Did you check the links I provided. Do they explain at least why the code in my answer solves some of the problems with the code in your question? – Frank van Puffelen Jun 17 '21 at 04:03
  • I ended up sending data to cloud functions to send to FCM (payload and device token). The async/await stuff I have to put more time into but my main takeaway was understanding the 'sendToDevice' part and this helped a lot. Thanks! – user3385829 Jun 18 '21 at 13:33
  • Great to hear that you got it work @user3385829 – Frank van Puffelen Jun 18 '21 at 14:26