About FCM Messages

Firebase Cloud Messaging (FCM) offers a broad range of messaging options and capabilities. The information in this page is intended to help you understand the different types of FCM messages and what you can do with them.

Message types

With FCM, you can send two types of messages to clients:

  • Notification messages, sometimes thought of as "display messages." These are handled by the FCM SDK automatically.
  • Data messages, which are handled by the client app.

Notification messages contain a predefined set of user-visible keys. Data messages, by contrast, contain only your user-defined custom key-value pairs. Notification messages can contain an optional data payload.

Use scenario How to send
Notification message FCM automatically displays the message to end-user devices on behalf of the client app. Notification messages have a predefined set of user-visible keys and an optional data payload of custom key-value pairs.
  1. In a trusted environment such as Cloud Functions or your app server, use the Admin SDK or the FCM Server Protocols: Set the notification key. May have optional data payload. Always collapsible.
  2. Use the Notifications composer: Enter the Message Text, Title, etc., and send. Add optional data payload by providing Custom data.
Data message Client app is responsible for processing data messages. Data messages have only custom key-value pairs. In a trusted environment such as Cloud Functions or your app server, use the Admin SDK or the FCM Server Protocols: Set the data key only.

Use notification messages when you want FCM to handle displaying a notification on your client app's behalf. Use data messages when you want to process the messages on your client app.

FCM can send a notification message including an optional data payload. In such cases, FCM handles displaying the notification payload, and the client app handles the data payload.

Notification messages

For testing or for marketing and user re-engagement, you can send notification messages using the Firebase console.

To programmatically send notification messages using the Admin SDK or the FCM protocols, set the notification key with the necessary predefined set of key-value options for the user-visible part of the notification message. For example, here is a JSON-formatted notification message in an IM app. The user can expect to see a message with the title "Portugal vs. Denmark" and the text "great match!" on the device:

{
  "message":{
    "token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
    "notification":{
      "title":"Portugal vs. Denmark",
      "body":"great match!"
    }
  }
}

Notification messages are delivered to the notification tray when the app is in the background. For apps in the foreground, messages are handled by these callbacks:

  • didReceiveRemoteNotification: on iOS
  • onMessageReceived() on Android. The notification key in the data bundle contains the notification.
  • onMessage() on web/JavaScript.

See the reference documentation for for the full list of predefined keys available for building notification messages:

Data messages

Set the appropriate key with your custom key-value pairs to send a data payload to the client app. Data messages can have a 4KB maximum payload.

For example, here is a JSON-formatted message in the same IM app as above, where the information is encapsulated in the common data key and the client app is expected to interpret the content:

{
  "message":{
    "token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
    "data":{
      "Nick" : "Mario",
      "body" : "great match!",
      "Room" : "PortugalVSDenmark"
    }
  }
}

The above example shows usage of the top-level, or common data field, which is interpreted by clients on all platforms that receive the message. On each platform, the client app receives the data payload in the corresonding callback:

  • On Android, a client app receives a data message in onMessageReceived() and can handle the key-value pairs accordingly. The data payload can be retrieved in the Intent used to launch your activity. See Receive Messages in an Android App.

  • On iOS, the data payload is found in didReceiveRemoteNotification: . See Receive Messages in a iOS Client.

  • For Web/JavaScript clients, the data payload is received in onMessage() when the page is in the foreground. When the web app is in the background, the payload is delivered to the service worker's background message handler. See Receive Messages in a JavaScript Client.

Notification messages with optional data payload

Both programmatically or via the Firebase console, you can send notification messages that contain an optional payload of custom key-value pairs. In the Notifications composer, use the Custom data fields in Advanced options.

App behavior when receiving messages that include both notification and data payloads depends on whether the app is in the background or the foreground—essentially, whether or not it is active at the time of receipt.

  • When in the background, apps receive the notification payload in the notification tray, and only handle the data payload when the user taps on the notification.
  • When in the foreground, your app receives a message object with both payloads available.

Here is a JSON-formatted message containing both the notification key and the data key:

{
  "message":{
    "token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
    "notification":{
      "title":"Portugal vs. Denmark",
      "body":"great match!"
    },
    "data" : {
      "Nick" : "Mario",
      "Room" : "PortugalVSDenmark"
    }
  }
}

Customizing a message across platforms

Messages sent by the FCM v1 HTTP protocol can contain two types of JSON key pairs:

  • a common set of keys to be interpreted by all app instances that receive the message.
  • platform-specific blocks of keys interpreted only by app instances running on the specified platform.

Platform-specific blocks give you flexibility to customize messages for different platforms to ensure that they are handled correctly when received. In many scenarios, it makes sense to use both common keys and platform-specific keys in a given message.

When to use common keys

  • Whenever you're targeting app instances on all platforms — iOS, Android, and web
  • When you are sending messages to topics

The common keys that are interpreted by all app instances regardless of platform are message.notification.title, message.notification.body, and message.data.

When to use platform-specific keys

  • When you want to send fields only to particular platforms
  • To send platform-specific fields in addition to the common keys

Whenever you want to send values to specific platforms only, don't use common keys; use platform-specific key blocks. For example, to send a notification to only iOS and web but not Android, you must use two separate blocks of keys, one for iOS and one for web.

When you are sending messages with specific delivery options, use platform-specific keys to set them. You can specify different values per platform if you want; but even when you want to set essentially the same value across platforms, you must use platform-specific keys. This is because each platform may interpret the value slightly differently — for example, time-to-live is set on Android as an expiration time in seconds, while on iOS it is set as an expiration date.

Example: notification message with platform-specific delivery options

The following v1 send request sends a common notification title and content to all platforms, but also sends some platform-specific overrides. Specifically, the request:

  • sets a long time-to-live for Android and Web platforms, while setting the APNs (iOS) message priority to a low setting
  • sets the appropriate keys to define the result of a user tap on the notification on Android and iOS — click_action, and category, respectively.
{
  "message":{
     "token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
     "notification":{
       "title":"Match update",
       "body":"Arsenal goal in added time, score is now 3-0"
     },
     "android":{
       "ttl":"86400s",
       "notification"{
         "click_action":"OPEN_ACTIVITY_1"
       }
     },
     "apns": {
       "headers": {
         "apns-priority": "5",
       },
       "payload": {
         "aps": {
           "category": "NEW_MESSAGE_CATEGORY"
         }
       }
     },
     "webpush":{
       "headers":{
         "TTL":"86400"
       }
     }
   }
 }

See the HTTP v1 reference documentation for complete detail on the keys available in platform-specific blocks in the message body. For more information about building send requests that contain the message body, see Build Send Requests.

Delivery options

FCM provides a specific set of delivery options for messages sent to Android devices, and allows for similar options on iOS and web. For example, "collapsible" message behavior is supported on Android via FCM's collapse_key, on iOS via apns-collapse-id, and on JavaScript/Web via Topic. For details, see descriptions in this section and related reference documentation.

Non-collapsible and collapsible messages

A non-collapsible message denotes that each individual message is delivered to the device. A non-collapsible message delivers some useful content, as opposed to a collapsible message like a content-free "ping" to the mobile app to contact the server to fetch data.

Some typical use cases of non-collapsible messages are chat messages or critical messages. For example, in an IM app, you would want to deliver every message, because every message has different content.

For Android there is a limit of 100 messages that can be stored without collapsing. If the limit is reached, all stored messages are discarded. When the device is back online, it receives a special message indicating that the limit was reached. The app can then handle the situation properly, typically by requesting a full sync from the app server.

A collapsible message is a message that may be replaced by a new message if it has yet to be delivered to the device.

A common use cases of collapsible messages are messages used to tell a mobile app to sync data from the server. An example would be a sports app that updates users with the latest score. Only the most recent message is relevant.

To mark a message as collapsible on Android, include the collapse_key parameter in the message payload. FCM allows a maximum of four different collapse keys per Android device to be used by the app server at any given time. In other words, the FCM server can simultaneously store four different collapsible messages per device, each with a different collapse key. If you exceed this number, FCM only keeps four collapse keys, with no guarantees about which ones are kept.

Which should I use?

Collapsible messages are a better choice from a performance standpoint, provided your app doesn't need to use non-collapsible messages. However, if you use collapsible messages, remember that FCM only allows a maximum of four different collapse keys to be used by the FCM connection server per registration token at any given time. You must not exceed this number, or it could cause unpredictable consequences.

Use scenario How to send
Non-collapsible Every message is important to the client app and needs to be delivered. Except for notification messages, all messages are non-collapsible by default.
Collapsible When there is a newer message that renders an older, related message irrelevant to the client app, FCM replaces the older message. For example: messages used to initiate a data sync from the server, or outdated notification messages. Set the appropriate parameter in your message request:
  • collapseKey on Android
  • apns-collapse-id on iOS
  • Topic on Web
  • collapse_key in legacy protocols (all platforms)

Setting the priority of a message

You have two options for assigning delivery priority to downstream messages on Android: normal and high priority. Delivery of normal and high priority messages works like this:

  • Normal priority. This is the default priority for data messages. Normal priority messages won't open network connections on a sleeping device, and their delivery may be delayed to conserve the battery. For less time-sensitive messages, such as notifications of new email or other data to sync, choose normal delivery priority.
  • High priority. This is the default priority for notification messages. FCM attempts to deliver high priority messages immediately, allowing the FCM service to wake a sleeping device when possible and open a network connection to your app server. Apps with instant messaging, chat, or voice call alerts, for example, generally need to open a network connection and make sure FCM delivers the message to the device without delay. Set high priority if the message is time-critical and requires the user's immediate interaction, but beware that setting your messages to high priority contributes more to battery drain compared with normal priority messages.

Here is an example of a normal priority message sent via the FCM HTTP v1 protocol to notify a magazine subscriber that new content is available to download:

{
  "message":{
    "topic":"subscriber-updates",
    "notification":{
      "body" : "This week's edition is now available.",
      "title" : "NewsMagazine.com",
    },
    "data" : {
      "volume" : "3.21.15",
      "contents" : "http://www.news-magazine.com/world-week/21659772"
    },
    "android":{
      "priority":"normal"
    },
    "apns":{
      "headers":{
        "apns-priority":"5"
      }
    },
    "webpush": {
      "headers": {
        "Urgency": "high"
      }
    }
  }
}

For more platform-specific detail on setting message priority:

Setting the lifespan of a message

FCM usually delivers messages immediately after they are sent. However, this might not always be possible. For example, if the platform is Android, the device could be turned off, offline, or otherwise unavailable. Or FCM might intentionally delay messages to prevent an app from consuming excessive resources and negatively affecting battery life.

When this happens, FCM stores the message and delivers it as soon as it's feasible. While this is fine in most cases, there are some apps for which a late message might as well never be delivered. For example, if the message is an incoming call or video chat notification, it is meaningful only for a short period of time before the call is terminated. Or if the message is an invitation to an event, it is useless if received after the event has ended.

On Android and Web/JavaScript, you can specify the maximum lifespan of a message. The value must be a duration from 0 to 2,419,200 seconds (28 days), and it corresponds to the maximum period of time for which FCM stores and attempts to deliver the message. Requests that don't contain this field default to the maximum period of four weeks.

Here are some possible uses for this feature:

  • Video chat incoming calls
  • Expiring invitation events
  • Calendar events

Another advantage of specifying the lifespan of a message is that FCM never throttles messages with a time-to-live value of 0 seconds. In other words, FCM guarantees best effort for messages that must be delivered "now or never." Keep in mind that a time_to_live value of 0 means messages that can't be delivered immediately are discarded. However, because such messages are never stored, this provides the best latency for sending notification messages.

Here is an example of a request that includes TTL:

{
  "message":{
    "token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
    "data":{
      "Nick" : "Mario",
      "body" : "great match!",
      "Room" : "PortugalVSDenmark"
    },
    "apns":{
      "headers":{
        "apns-expiration":"1604750400"
      }
    },
    "android":{
      "ttl":"4500s"
    },
    "webpush":{
      "headers":{
        "TTL":"4500"
      }
    }
  }
}

Receiving messages from multiple senders

FCM allows multiple parties to send messages to the same client app. For example, suppose the client app is an article aggregator with multiple contributors, and each of them should be able to send a message when they publish a new article. This message might contain a URL so that the client app can download the article. Instead of having to centralize all sending activity in one location, FCM gives you the ability to let each of these contributors send its own messages.

To enable this feature, make sure you have each sender's sender ID. When requesting registration, the client app fetches the token multiple times, each time with a different sender ID in audience field, using the token retrieval method for the given platform:

Finally, share the registration token with the corresponding senders, and they'll be able to send messages to the client app using their own authentication keys.

Note that there is limit of 100 multiple senders.

Lifetime of a message

When an app server posts a message to FCM and receives a message ID back, it does not mean that the message was already delivered to the device. Rather, it means that it was accepted for delivery. What happens to the message after it is accepted depends on many factors.

In the best-case scenario, if the device is connected to FCM, the screen is on and there are no throttling restrictions, the message is delivered right away.

If the device is connected but in doze mode, a low priority message is stored by FCM until the device is out of doze mode. And that's where the collapse_key flag plays a role: if there is already a message with the same collapse key (and registration token) stored and waiting for delivery, the old message is discarded and the new message takes its place (that is, the old message is collapsed by the new one). However, if the collapse key is not set, both the new and old messages are stored for future delivery.

If the device is not connected to FCM, the message is stored until a connection is established (again respecting the collapse key rules). When a connection is established, FCM delivers all pending messages to the device. If the device never gets connected again (for instance, if it was factory reset), the message eventually times out and is discarded from FCM storage. The default timeout is four weeks, unless the time_to_live flag is set.

To get more insight into the delivery of a message:

  • For Android: If you'd like to be notified when the application successfully receieves a message, you can use delivery_receipt_requested functionality following the guidelines. This requires you to setup an XMPP server.
  • For Android, iOS and Web: You can use InstanceID APIs to check the most recent date that the device you're targeting through the FCM registration token has established a connection with FCM.

If the device has not connected to FCM for more than one month, FCM still accepts the message but immediately discards it. If the device connects within four weeks of the last data message you sent to it, your client receives the onDeletedMessages() callback. The app can then handle the situation properly, typically by requesting a full sync from the app server.

Finally, when FCM attempts to deliver a message to the device and the app was uninstalled, FCM discards that message right away and invalidates the registration token. Future attempts to send a message to that device results in a NotRegistered error.

FCM ports and your firewall

If your organization has a firewall that restricts the traffic to or from the Internet, you need to configure it to allow connectivity with FCM in order for your Firebase Cloud Messaging client apps to receive messages. FCM typically only uses 5228, but it sometimes uses 5229 and 5230.

For outgoing connections, FCM doesn't provide specific IPs, so you should allow your firewall to accept outgoing connections to all IP addresses contained in the IP blocks listed in Google's ASN of 15169.

Ports to open for incoming messages:

  • 5228
  • 5229
  • 5230

Ports to allow outgoing connections:

  • All IP addresses contained in the IP blocks listed in Google's ASN of 15169.

Credentials

Depending on which FCM features you implement, you may need the following credentials from your Firebase project:

Project ID A unique identifier for your Firebase project, used in requests to the FCM v1 HTTP endpoint. This value is available in the Firebase console Settings pane.
Registration token An ID generated by the FCM SDK for each client app instance. Required for single device and device group messaging. Note that registration tokens must be kept secret.
Sender ID A unique numerical value created when you create your Firebase project, available in the Cloud Messaging tab of the Firebase console Settings pane. The sender ID is used to identify each sender that can send messages to the client app.
Access token A short-lived OAuth 2.0 token that authorizes requests to the HTTP v1 API. This token is associated with a service account that belongs to your Firebase project. To create and rotate access tokens, follow the steps described in Authorize Send Requests.
Server key (for legacy protocols)

A server key that authorizes your app server for access to Google services, including sending messages via the Firebase Cloud Messaging legacy protocols. You obtain the server key when you create your Firebase project. You can view it in the Cloud Messaging tab of the Firebase console Settings pane.

Important: Do not include the server key anywhere in your client code. Also, make sure to use only server keys to authorize your app server. Android, iOS, and browser keys are rejected by FCM.

Send feedback about...

Need help? Visit our support page.