How to Use Firebase Cloud Messaging

How to Use Firebase Cloud Messaging Firebase Cloud Messaging (FCM) is Google’s cross-platform messaging solution that lets you reliably deliver messages at no cost to Android, iOS, and web applications. Built on top of Google’s infrastructure, FCM enables developers to send notifications and data payloads to devices, whether the app is in the foreground, background, or completely closed. Its seaml

Nov 10, 2025 - 08:57
Nov 10, 2025 - 08:57
 0

How to Use Firebase Cloud Messaging

Firebase Cloud Messaging (FCM) is Google’s cross-platform messaging solution that lets you reliably deliver messages at no cost to Android, iOS, and web applications. Built on top of Google’s infrastructure, FCM enables developers to send notifications and data payloads to devices, whether the app is in the foreground, background, or completely closed. Its seamless integration with the Firebase platform, combined with real-time delivery, scalability, and rich targeting capabilities, makes it the go-to choice for modern mobile and web applications seeking to engage users through timely, personalized communication.

Whether you’re building a social media app that needs to notify users of new messages, an e-commerce platform aiming to promote flash sales, or a productivity tool requiring background sync updates, FCM provides the infrastructure to deliver those messages efficiently. Unlike traditional push notification systems that require complex server setups and platform-specific APIs, FCM abstracts much of the complexity, offering a unified API across platforms and handling message routing, device registration, and delivery optimization automatically.

With over 2 billion active Android devices and a growing iOS and web user base, leveraging FCM ensures your application can reach users across ecosystems with minimal overhead. Moreover, FCM supports advanced features like topic-based messaging, device group targeting, and analytics integration with Firebase Analytics, allowing you to measure message effectiveness and refine your engagement strategies.

This guide will walk you through every step of implementing Firebase Cloud Messaging—from setting up your Firebase project to sending your first message—while highlighting best practices, essential tools, real-world use cases, and answers to common challenges. By the end of this tutorial, you’ll have a comprehensive, production-ready understanding of how to use FCM effectively in your applications.

Step-by-Step Guide

1. Create a Firebase Project

To begin using Firebase Cloud Messaging, you must first create a Firebase project in the Firebase Console. Navigate to console.firebase.google.com and click “Add project.” Follow the prompts to name your project, accept the terms, and optionally enable Google Analytics. Analytics integration is highly recommended as it allows you to track message delivery rates, open rates, and user engagement metrics.

Once your project is created, you’ll be taken to the project overview dashboard. From here, click on the “Gear” icon in the top left, select “Project settings,” and then navigate to the “Cloud Messaging” tab. This is where you’ll find your Server Key and Sender ID—these credentials are essential for authenticating your backend server when sending messages.

2. Register Your Application

After creating the project, you need to register your application with Firebase. Click “Add app” and choose your platform: Android, iOS, or Web.

For Android: Enter your app’s package name (e.g., com.example.myapp). You can find this in your AndroidManifest.xml or in Android Studio under the app module’s build.gradle file. Optionally, upload a debug signing certificate if you want to test push notifications during development. Click “Register app.” Firebase will generate a google-services.json file. Download it and place it in the app/ directory of your Android project.

For iOS: Enter your iOS bundle ID (found in Xcode under General > Identity). You may also upload a Push Notification certificate or APNs authentication key if you plan to send notifications to iOS devices. After registration, download the GoogleService-Info.plist file and add it to your Xcode project root directory. Ensure the file is added to your target under “General > Embedded Binaries.”

For Web: Enter your site’s URL. Firebase will generate a web configuration object containing your API key, project ID, and sender ID. Copy this configuration for later use in your JavaScript code.

3. Add Firebase SDK to Your Application

Next, integrate the Firebase SDK into your application.

Android: In your project-level build.gradle, add the Google Services plugin:

dependencies {

classpath 'com.google.gms:google-services:4.3.15'

}

In your app-level build.gradle, apply the plugin and add the FCM dependency:

apply plugin: 'com.google.gms.google-services'

dependencies {

implementation 'com.google.firebase:firebase-messaging:23.4.0'

}

iOS: If you’re using CocoaPods, add the following to your Podfile:

pod 'Firebase/Messaging'

Then run pod install. If you’re using Swift Package Manager, add Firebase Messaging via Xcode’s package dependencies.

Web: Include the Firebase SDK via CDN or npm. For npm:

npm install firebase

Then initialize Firebase in your JavaScript file:

import { initializeApp } from "firebase/app";

import { getMessaging } from "firebase/messaging";

const firebaseConfig = {

apiKey: "YOUR_API_KEY",

authDomain: "YOUR_PROJECT.firebaseapp.com",

projectId: "YOUR_PROJECT",

storageBucket: "YOUR_PROJECT.appspot.com",

messagingSenderId: "YOUR_SENDER_ID",

appId: "YOUR_APP_ID"

};

const app = initializeApp(firebaseConfig);

const messaging = getMessaging(app);

4. Configure Push Notification Permissions

Before your app can receive notifications, users must grant permission. This step varies by platform.

Android: In AndroidManifest.xml, declare the necessary permissions and services:

<uses-permission android:name="android.permission.INTERNET" />

<uses-permission android:name="android.permission.WAKE_LOCK" />

<service

android:name=".MyFirebaseMessagingService"

android:exported="false">

<intent-filter>

<action android:name="com.google.firebase.MESSAGING_EVENT" />

</intent-filter>

</service>

Create a service class extending FirebaseMessagingService:

public class MyFirebaseMessagingService extends FirebaseMessagingService {

@Override

public void onMessageReceived(RemoteMessage remoteMessage) {

super.onMessageReceived(remoteMessage);

// Handle both notification and data payloads

if (remoteMessage.getNotification() != null) {

sendNotification(remoteMessage.getNotification().getTitle(),

remoteMessage.getNotification().getBody());

}

if (remoteMessage.getData().size() > 0) {

// Handle data payload

String data = remoteMessage.getData().get("custom_key");

Log.d("FCM", "Data payload: " + data);

}

}

private void sendNotification(String title, String body) {

NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "default")

.setSmallIcon(R.drawable.ic_notification)

.setContentTitle(title)

.setContentText(body)

.setAutoCancel(true);

NotificationManagerCompat manager = NotificationManagerCompat.from(this);

manager.notify(1, builder.build());

}

}

iOS: In your AppDelegate.swift, import Firebase and request authorization:

import Firebase

import UserNotifications

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

FirebaseApp.configure()

UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) { granted, error in

if granted {

DispatchQueue.main.async {

application.registerForRemoteNotifications()

}

}

}

return true

}

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {

let tokenParts = deviceToken.map { data in String(format: "%02.2hhx", data) }

let token = tokenParts.joined()

print("Device Token: \(token)")

// Send token to your backend server

sendTokenToServer(token)

}

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {

print("Received notification: \(userInfo)")

completionHandler(.newData)

}

Web: Request permission and retrieve the token:

Notification.requestPermission().then(function(permission) {

if (permission === "granted") {

getToken(messaging).then((currentToken) => {

if (currentToken) {

console.log("Token:", currentToken);

sendTokenToServer(currentToken);

} else {

console.log("No registration token available. Request permission to generate one.");

}

}).catch((err) => {

console.log("An error occurred while retrieving token. ", err);

});

}

});

5. Send Your First Message

Now that your app is configured, you can send your first message.

Using Firebase Console: Go to the Firebase Console, select your project, and navigate to “Cloud Messaging.” Click “Create notification.” Enter a title and message body, select your target (by app, topic, or device token), and click “Review.” Then click “Publish.” The message will be delivered instantly to all registered devices.

Using HTTP API: For programmatic sending, use the FCM HTTP v1 API. First, generate a service account key from Firebase Project Settings > Service Accounts. Download the JSON file and use it to authenticate your server.

Example cURL request:

curl -X POST \

https://fcm.googleapis.com/v1/projects/YOUR_PROJECT_ID/messages:send \

-H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \

-H 'Content-Type: application/json' \

-d '{

"message": {

"token": "DEVICE_TOKEN_HERE",

"notification": {

"title": "Hello from FCM",

"body": "This is your first push notification!"

},

"data": {

"click_action": "OPEN_ACTIVITY",

"custom_param": "value"

}

}

}'

To obtain an access token, use the Google OAuth2 library or service account credentials. Libraries like Firebase Admin SDK (Node.js, Python, Java, etc.) simplify this process.

6. Handle Messages in Foreground and Background

FCM behaves differently depending on whether the app is in the foreground, background, or terminated.

Android: When the app is in the foreground, onMessageReceived() is always called. If the app is in the background or terminated, and the message contains a notification payload, Android handles it automatically and displays the notification. Data payloads are delivered to onMessageReceived() regardless of state.

iOS: Similar behavior: notifications are handled by the system when the app is backgrounded or terminated. To handle data payloads in the background, you must enable “Background Modes > Remote notifications” in your app capabilities and implement didReceiveRemoteNotification.

Web: Messages are handled by the service worker. Create a firebase-messaging-sw.js file in your public directory:

importScripts("https://www.gstatic.com/firebasejs/9.22.0/firebase-app-compat.js");

importScripts("https://www.gstatic.com/firebasejs/9.22.0/firebase-messaging-compat.js");

firebase.initializeApp({

apiKey: "YOUR_API_KEY",

authDomain: "YOUR_PROJECT.firebaseapp.com",

projectId: "YOUR_PROJECT",

messagingSenderId: "YOUR_SENDER_ID",

appId: "YOUR_APP_ID"

});

const messaging = firebase.messaging();

messaging.onBackgroundMessage((payload) => {

const notificationTitle = payload.notification.title;

const notificationOptions = {

body: payload.notification.body,

icon: "/firebase-logo.png"

};

self.registration.showNotification(notificationTitle, notificationOptions);

});

7. Test and Debug

Use the Firebase Console’s message history to verify delivery. For Android and iOS, check Logcat and Xcode console respectively for token generation and message receipt. Ensure your device is registered and the token is correctly sent to your backend.

Common debugging tips:

  • Verify that the package name/bundle ID matches exactly between your app and Firebase project.
  • Ensure your device has internet access and Google Play Services are updated (Android).
  • Confirm that your APNs certificate or key is valid and properly configured for iOS.
  • Check that your server is using the correct authentication method (OAuth2 token vs legacy server key).

Best Practices

Use Data Payloads for Custom Behavior

While notification payloads are convenient for simple alerts, data payloads give you full control. Use data payloads to trigger custom logic in your app—such as refreshing content, opening a specific screen, or syncing data. Always include a click_action parameter in data payloads for web and Android to define which activity or route to open when the user taps the notification.

Implement Token Refresh Logic

Device tokens can change due to app reinstallations, OS updates, or security events. Always listen for token refresh events and update your server accordingly.

Android: Override onNewToken() in your FirebaseMessagingService:

@Override

public void onNewToken(@NonNull String token) {

Log.d("FCM", "Refreshed token: " + token);

sendTokenToServer(token);

}

iOS: Implement didReceiveRegistrationToken in FIRMessagingDelegate.

Web: Use onTokenRefresh():

messaging.onTokenRefresh(() => {

getToken(messaging).then((refreshedToken) => {

sendTokenToServer(refreshedToken);

});

});

Optimize Message Timing and Frequency

Overloading users with notifications leads to opt-outs and uninstalls. Segment your audience and send messages during peak engagement hours. Use Firebase Analytics to analyze user behavior and tailor message timing accordingly. Avoid sending promotional messages during late-night hours unless your app’s context justifies it (e.g., travel alerts).

Personalize Messages Using User Data

Use custom attributes (like user preferences, location, or purchase history) stored on your backend to personalize notifications. For example, “Hi Sarah, your favorite brand just dropped a new collection!” increases open rates significantly compared to generic messages.

Use Topics for Broad Targeting

Topics allow you to send messages to users who have subscribed to a specific subject, such as “sports_news” or “flash_sales.” Subscribe users programmatically:

// Android

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

// Web

messaging.subscribeToTopic('sports_news');

Topics are ideal for broadcast messages to large, loosely defined groups. Avoid creating too many topics—Firebase limits the number of topics per app.

Implement Message Acknowledgment and Retry Logic

When sending messages via HTTP API, always check the response. FCM returns a message ID on success or an error code on failure. Implement retry logic with exponential backoff for transient errors (e.g., network timeouts). Do not retry on permanent errors like “InvalidRegistration” or “MismatchSenderId.”

Respect User Privacy and Permissions

Always request notification permissions in context. Don’t prompt users immediately on app launch. Instead, wait until they’ve engaged with a feature that benefits from notifications (e.g., after they save a favorite item). Provide clear value propositions: “Get alerts when your favorite player scores.”

Monitor Delivery Metrics

Enable Firebase Analytics and link it to FCM. Monitor key metrics: delivery rate, notification open rate, and conversion rate from notification to action. Use these insights to refine message content, timing, and targeting.

Handle Doze Mode and Battery Optimization (Android)

On Android 6.0+, Doze mode can delay or block background messages. To ensure timely delivery:

  • Use high-priority messages for critical alerts (e.g., chat messages).
  • Set priority: "high" in your message payload.
  • Inform users to disable battery optimization for your app if needed.

Tools and Resources

Firebase Console

The Firebase Console is your central hub for managing FCM. Use it to compose and send messages, view delivery reports, and manage topics. The interface is intuitive and requires no coding for basic use cases.

Firebase Admin SDK

For server-side message sending, use the Firebase Admin SDK. Available for Node.js, Python, Java, Go, and .NET, it handles authentication automatically and provides a clean API for sending messages to tokens, topics, or conditions.

Example in Node.js:

const admin = require("firebase-admin");

admin.initializeApp();

const message = {

token: "DEVICE_TOKEN",

notification: {

title: "New Message",

body: "You have a new message!"

},

data: {

type: "chat"

}

};

admin.messaging().send(message)

.then((response) => {

console.log("Successfully sent message:", response);

})

.catch((error) => {

console.log("Error sending message:", error);

});

Postman or cURL

For testing FCM API endpoints without writing code, use Postman or cURL. You’ll need a valid OAuth2 access token generated from your service account key. This is useful for debugging payloads and response codes.

FCM HTTP v1 API Documentation

Always refer to the official FCM HTTP v1 API Reference for up-to-date message structure, error codes, and payload options. This is the most reliable source for technical specifications.

FCM Testing Tools

Third-party tools like Pushwoosh, OneSignal, and Appcues offer visual interfaces and advanced segmentation, but they often layer on top of FCM. For full control and cost efficiency, stick with native FCM.

GitHub Repositories and Code Samples

Google maintains official sample apps on GitHub:

These repositories provide fully working examples and are invaluable for troubleshooting.

Stack Overflow and Firebase Community

For troubleshooting, search Stack Overflow using tags like firebase-cloud-messaging and android-push-notification. The Firebase community is active and helpful. Always include your platform, SDK version, and error logs when asking for help.

Real Examples

Example 1: E-Commerce Flash Sale Notification

An online retailer uses FCM to notify users of limited-time sales. When inventory for a popular product drops below 5 units, a backend script triggers an FCM message to users who have shown interest in that category.

Message payload:

{

"token": "user_device_token",

"notification": {

"title": "🚨 Flash Sale: 70% Off Running Shoes!",

"body": "Only 3 left! Sale ends in 2 hours."

},

"data": {

"product_id": "shoes-001",

"action": "open_product_detail"

}

}

On notification tap, the app opens the product page directly. Analytics show a 22% increase in conversion from FCM notifications compared to email.

Example 2: Social Media Direct Message Alert

A messaging app sends real-time alerts for new DMs. Even when the app is killed, FCM wakes it up via high-priority messages.

Android service handles the data payload and displays a rich notification with sender profile image and quick reply options using Android’s NotificationCompat.Builder.

By using topic subscription (/topics/user_12345), the app efficiently targets only the recipient, reducing server load and bandwidth usage.

Example 3: News App Breaking News

A news publisher uses FCM to deliver breaking news alerts. Subscribers opt into topics like “Politics,” “Sports,” or “Tech.” When a journalist publishes a story, a backend function triggers a message to all subscribed users.

Message includes a deep link to the article and a “Read More” CTA. The publisher tracks open rates by topic and finds that “Tech” notifications have a 41% open rate, while “Politics” has 32%—leading to content strategy adjustments.

Example 4: Travel App Flight Status Update

A travel app sends automated FCM alerts when flight status changes. Users register their flight numbers, and the backend monitors airline APIs. When a delay occurs, a message is sent with updated arrival time and gate info.

Message includes a data payload with flight code and timestamp. The app uses this to auto-update the UI even if the user hasn’t opened the app in hours.

FAQs

Is Firebase Cloud Messaging free?

Yes, FCM is free to use with no monthly fees. Google offers generous free quotas for message delivery. Paid tiers are available for enterprise-level usage, but most apps never exceed the free limits.

Can I send messages without a server?

You can send test messages directly from the Firebase Console without a server. However, for dynamic, user-triggered, or scheduled messaging (e.g., “send when a user completes a task”), you need a backend server to trigger FCM via HTTP API or Admin SDK.

Why are my notifications not appearing on iOS?

Common causes include: missing APNs certificate, incorrect bundle ID, background modes not enabled, or the device token not being sent to your server. Verify your provisioning profile and ensure you’ve registered for remote notifications.

How do I handle messages when the app is closed on Android?

If the message contains a notification payload, Android displays it automatically. If you need to execute custom code when the app is closed, use a data payload and implement a broadcast receiver or job scheduler to handle it on app launch.

What’s the difference between notification and data payloads?

Notification payloads are handled by the system and displayed automatically. Data payloads are delivered to your app and must be handled programmatically. Use notification payloads for simple alerts; use data payloads for custom logic.

Can I send messages to multiple devices at once?

Yes. Use topic messaging to send to users subscribed to a topic, or use multicast messaging (up to 1000 tokens per request) via the HTTP v1 API.

How secure is FCM?

FCM uses HTTPS and OAuth2 for authentication. Messages are encrypted in transit. However, you must securely store device tokens on your server and validate them before sending sensitive data. Never send personal data in unencrypted payloads.

Does FCM work on Huawei devices without Google Play Services?

On Huawei devices without Google Mobile Services (GMS), FCM won’t work. Use Huawei Mobile Services (HMS) Push Kit as an alternative. You can implement both in parallel using conditional logic based on device capabilities.

Can I schedule messages for future delivery?

FCM doesn’t natively support scheduling. Use a backend scheduler (e.g., Cloud Functions for Firebase, AWS Lambda, or cron jobs) to send messages at a future time by storing the target timestamp and triggering the FCM API when the time arrives.

How do I unsubscribe users from notifications?

Call unsubscribeFromTopic() on the client side or remove the device token from your server’s database. You can also prompt users to disable notifications via system settings.

Conclusion

Firebase Cloud Messaging is a powerful, scalable, and cost-effective solution for delivering push notifications across Android, iOS, and web platforms. Its seamless integration with the Firebase ecosystem, combined with robust APIs and real-time delivery, makes it indispensable for modern applications aiming to maintain user engagement and deliver timely updates.

By following the step-by-step guide in this tutorial, you’ve learned how to set up FCM, configure your app for different platforms, handle message payloads, and send targeted notifications. You’ve also explored best practices for personalization, performance, and privacy, along with real-world examples that demonstrate FCM’s versatility in e-commerce, social media, news, and travel apps.

Remember: the key to successful push notifications lies not in volume, but in relevance and timing. Use data to understand your users, respect their preferences, and deliver value with every message. Combine FCM with Firebase Analytics to measure impact and continuously refine your strategy.

As mobile usage continues to grow and user expectations for real-time communication rise, mastering FCM positions your application to thrive in an increasingly connected world. Whether you’re a startup or an enterprise, FCM provides the infrastructure to build meaningful, scalable user engagement—without the complexity of managing multiple notification systems.

Start small, test rigorously, iterate based on data, and scale with confidence. Your users are waiting for your next message—make it count.