Select Page

In this post, I’d like to show you how to start sending notifications with Firebase Cloud Messaging from node.js and Typescript. A basic knowledge about push notifications and Firebase might help you in better understanding this article. However, if you aren’t familiar with FCM I recommend checking out my previous post: Introduction to Firebase Cloud Messaging

Node.js & FCM

The easiest way to send your first push notification is by using the Firebase Console. Let’s skip this point in order to show how to do that from node.js and Typescript. By the way, I’d like to outline a few more aspects that may be valuable for you.

We can send a push notification manually via HTTP request or we can utilise a ready to use NPM package. I personally chose the node-gcm package.

On NPM (https://www.npmjs.com/) we can find a lot of ready to use plugins for FCM. In this particular case, I believe that choosing the most popular package would be the best choice and won’t end with abandoning the package in future.

Ok, let’s install it by calling:

npm install node-gcm --save

You can also install typings for Typescript if you wish to have it:

typings install node-gcm --save // for Typescript v. 1.x
npm install @types/node-gcm --save // for Typescript 2.x

To send the first message just copy the below code, change your firebase cloud messaging token (it’s located in the project settings) and then, run it.

/// <reference path="typings/tsd.d.ts" />
import gcm = require("node-gcm");

let sender = new gcm.Sender("Your_Firebase_Cloud_Messaging_token");

let message = new gcm.Message({
    notification: {
        title: "Hello World! ",
        icon: "your_icon_name",
        body: "Here is a notification's body."
    },
});

let recipients: gcm.IRecipient = { to: "/topics/all" };

sender.sendNoRetry(message, recipients, (err, response) => {
    if (err) console.error(err);
    else console.log(response);
});

If everything went fine you should get a message ID in the response. The above code sends a “Hello World” message to all devices which have been connected to the Firebase project.

Sending strategies

Firebase sending strategies image

Firebase allows you to send messages to:

  • a particular device token (generated on application start)
  • a topic (a group of devices’ tokens, each token of the device may be subscribed or unsubscribed to a topic)
  • a user segment (all users of application “X” who might be filtered by language or/and app’s version)

a) Sending a message to device token

It’s a basic option which allows sending messages directly to one or multiple devices. All what we need to do is pass an array with registration tokens as a second argument to send a message function:

let message = new gcm.Message({
    notification: {
        title: "Hello World! ",
        icon: "your_icon_name",
        body: "Here is a notification's body."
    },
});

sender.sendNoRetry(message, ["device_token_1", "device_token_2", "device_token_3"], (err, response) => {
    if (err) console.error(err);
    else console.log(response);
});

However, what to do when each of the devices from the above picture belong to the same user? The first idea may be storing each user’s device’s token in your system, but probably after some time you will have a lot of expired tokens in the database.

b) Sending a message to a single topic

The easier solution is subscribing a user’s tokens to a topic. By default, Firebase contains three predefined topics:

  • all
  • ios
  • android

We can also create our own topics as we wish without any limitations. Subscribing to topic is very easy on mobile devices, for example on Android you only need to call:

FirebaseMessaging.getInstance().subscribeToTopic("topic_name");

On iOS and hybrid applications it’s very similar process. If a specified topic doesn’t exist it will be created. Every token can be subscribed to multiple topics (ex. news, updates etc.).

This approach allows us to send messages to multiple devices via one call to Firebase API.

sender.sendNoRetry(message, { to: "/topics/news" }, (err, response) => {
    if (err) console.error(err);
    else console.log(response);
});

Unfortunately, on the web application, subscribing a token to the topic is not so convenient as on mobile apps. We need to subscribe it manually by sending a HTTP request to Google Instance ID API.

POST
https://iid.googleapis.com/iid/v1/{TOKEN}/rel/topics/{topic}
Content-Type:application/json
Authorization:key=your_server_key

With the InstanceID API you can also check all token details.

GET
https://iid.googleapis.com/iid/info/{TOKEN}/?details=true
Authorization:key=your_server_key

In response you should get something like this:

{
  "connectDate": "2016-11-28",
  "application": "wp:http://localhost:9000/#1316547-600F-4D90-B297-1959551DAA52",
  "authorizedEntity": "321312312",
  "rel": {
    "topics": {
      "news": {
        "addDate": "2016-11-24"
      },
      "updates": {
        "addDate": "2016-11-28"
      },
      "alerts": {
        "addDate": "2016-11-25"
      }
    }
  },
  "connectionType": "WIFI",
  "platform": "WEBPUSH"
}

 c) Sending a message to multiple topics

We are also able to send a message to multiple topics at the same time. In order to so, we need to specify a condition parameter:

sender.sendNoRetry(message,
    { condition: "'news' in topics && 'updates' in topics && 'ios' in topics" },
    (err, response) => {
        if (err) console.error(err);
        else console.log(response);
    });

The condition parameter supports two logical operators:

  • and (&&)
  • or (||)

The code above sends a message to ios devices which are subscribed to news and updates and topics. The single expression could contain maximum 2 logical operators.

The Firebase documentation recommends using a Group Device in order to gother multiple tokens for one user. I recommend checking it.

However, it seems that using topics has more advantages. For example, it’s not possible to subscribe group of devices to a topic. So you will need to handle that on your server side.

If you decide to use topics as a solution for sending messages to a single user. You need to keep in mind that this device’s token is generated once and then reused if it’s possible. Basically, token is refreshed not very often. So, when a device is used by more than one user it’s possible that a single token would be subscribed to multiple topics. For example, token #123 might be subscribed to topics: user_A, user_B_ user_C. In this case things may end up badly.

To prevent this situation, you need to make sure that you unsubscribed the previous user from all topics.

d) Sending a message to a single application

It’s possible that multiple applications would be subscribed to the same topic. However, sometimes we may want to still send a message to the topic but restrict it to only one application. To do this, we need to set a restrictedPackageName property in the message object:

let message = new gcm.Message({
    notification: {
        title: "Hello World! ",
        icon: "your_icon_name",
        body: "Here is a notification's body.",
    },
    restrictedPackageName: "your.application.package.name",
});

Here we’ve specified a package name during application adding to our project in the Firebase Console.

Summary

I tried to cover the most important aspects of the Firebase Cloud Messaging which may be useful to you, especially at the beginning of your journey with FCM and node.js. The node-gcm package supports much more options, so I recommend checking their documentation and reference for Firebase HTTP protocol. For example, we haven’t discussed sending an additional data with the message, but it’s very easy. If you wish to know how to do that and then receive the notification on the web or Ionic application, please check my other posts.

shares