Firebase Cloud Messaging: Send Push Notifications to Web & Mobile
In this tutorial, you will learn about Firebase Cloud Messaging: Send Push Notifications to Web & Mobile. We cover key concepts, practical examples, and best practices to help you master this topic.
Firebase Cloud Messaging (FCM) sends push notifications and data messages to web, Android, and iOS devices through platform-specific push services with Firebase-managed delivery.
What You'll Learn
How to send push notifications with FCM, target specific devices or topics, handle notification interactions, send data-only messages, and measure notification performance.
Why It Matters
Push notifications re-engage users with timely information. DodaTech's Antivirus Pro sends push alerts for threat detections, scan completions, and subscription reminders — achieving 4x higher engagement than email.
Real-World Use
When Cloud Functions detects a critical threat on a user's device, it sends an FCM notification to the user's phone. The user taps the notification, opens the app, and sees the threat details.
flowchart LR
A["Event Trigger\nThreat Detected"] --> B["Cloud Functions\nSend FCM"]
B --> C["FCM Server"]
C --> D["Android\nDevice"]
C --> E["iOS\nDevice"]
C --> F["Web\nBrowser"]
D --> G["App Opens\nThreat Details"]
style A fill:#dbeafe,stroke:#2563eb
style B fill:#fef3c7,stroke:#d97706
style C fill:#bbf7d0,stroke:#16a34a
Web Client Setup
// In web app — request permission and get token
import { getMessaging, getToken, onMessage } from "firebase/messaging";
const messaging = getMessaging();
async function requestNotificationPermission() {
try {
const permission = await Notification.requestPermission();
if (permission === "granted") {
const token = await getToken(messaging, {
vapidKey: "YOUR_VAPID_KEY"
});
console.log("FCM Token:", token);
// Save token to Firestore for targeting
await saveTokenToUserProfile(token);
} else {
console.log("Notification permission denied");
}
} catch (error) {
console.error("FCM setup error:", error);
}
}
// Handle foreground messages
onMessage(messaging, (payload) => {
console.log("Foreground notification:", payload);
// Show custom in-app notification
showInAppNotification(payload.notification);
});
// Expected output: FCM Token: fCMToken: abc123...xyz
Sending Notifications via Admin SDK
const admin = require("firebase-admin");
// Send to a specific device
async function sendToDevice(userToken) {
const message = {
notification: {
title: "Threat Detected",
body: "A malware threat was found on your device"
},
data: {
scanId: "scan_abc123",
severity: "high",
clickAction: "OPEN_SCAN"
},
token: userToken
};
const response = await admin.messaging().send(message);
console.log("Notification sent:", response);
}
// Expected output: Notification sent: projects/durga-antivirus/messages/msg123
// Send to topic
async function sendToTopic() {
const message = {
notification: {
title: "Weekly Security Report",
body: "Your weekly scan report is ready"
},
topic: "security-reports"
};
const response = await admin.messaging().send(message);
console.log("Topic message sent:", response);
}
Topic Management
// Subscribe devices to topics from client
import { getMessaging, subscribeToTopic, unsubscribeFromTopic } from "firebase/messaging";
const messaging = getMessaging();
async function subscribeToAlerts(token) {
await subscribeToTopic(messaging, token, "alerts");
console.log("Subscribed to alerts topic");
}
async function unsubscribeFromPromotions(token) {
await unsubscribeFromTopic(messaging, token, "promotions");
console.log("Unsubscribed from promotions topic");
}
// Admin SDK: manage subscriptions server-side
async function adminSubscribeUser(uid, topic) {
const userDoc = await admin.firestore()
.collection("users")
.doc(uid)
.get();
const fcmToken = userDoc.data().fcmToken;
await admin.messaging().subscribeToTopic(fcmToken, topic);
console.log("Admin subscribed user to topic:", topic);
}
Conditional Messages
// Send different notifications based on conditions
async function sendConditionalAlert(threatLevel, userToken) {
let title, body;
if (threatLevel === "critical") {
title = "Critical Security Alert";
body = "Immediate action required: malware detected";
} else if (threatLevel === "high") {
title = "Threat Detected";
body = "A potential threat was found. Scan now.";
} else {
title = "Scan Complete";
body = "No threats found on your device";
}
const message = {
notification: { title, body },
data: { threatLevel, timestamp: Date.now().toString() },
token: userToken,
android: { priority: "high", ttl: 86400000 },
apns: { payload: { aps: { sound: "default" } } },
webpush: { fcmOptions: { link: "/scans" } }
};
const response = await admin.messaging().send(message);
console.log("Conditional notification sent:", response);
}
Common Mistakes
1. Not Handling Notification Permission Denials
Users can deny notification permission. Always check Notification.permission and degrade gracefully by using in-app notifications.
2. Sending Notifications Without User Consent
On iOS and recent Android, notification permission must be requested explicitly. Request permission at an appropriate time, not immediately on first launch.
3. Using Wrong Platform-Specific Config
Android and iOS require platform-specific configurations (APNs cert for iOS, sender ID for Android). Missing these causes silent delivery failures.
4. Not Handling Token Refresh
FCM tokens change periodically and when users reinstall apps. Listen for onTokenRefresh and update the token in your database.
5. Unsubscribing from Topics on Client Only
Unsubscribing from topics on the client doesn't guarantee server-side cleanup. Use Admin SDK for critical subscription management.
Practice Questions
- How does FCM deliver messages to different platforms?
- What is the difference between notification and data messages?
- How do you target specific user segments with FCM?
- How do you handle when a user taps a notification?
Answers:
- FCM uses platform-specific push services: APNs for iOS, FCM transport for Android, and Service Workers for web.
- Notification messages display automatically (title + body). Data messages are delivered to the app for custom handling. Use notification + data combined when you need both.
- Use topics (subscribe users to topics like "alerts" or "promotions"), device groups, or send to individual tokens stored in Firestore.
- Set
data.clickActionorwebpush.fcmOptions.linkto specify the destination URL. The app reads this on notification tap.
Challenge: Build a notification system: Cloud Function triggers on critical threat detection, sends FCM notification to the user's device with scan ID, handles notification tap to open scan details, and subscribes users to weekly report topics.
FAQ
Mini Project
Build a push notification system: FCM setup in a web app (permission request, token storage), Cloud Function that triggers on threat writes and sends notifications, topic subscriptions for alert categories, and click handling that navigates to threat details.
What's Next
Firebase Dynamic Links — create smart links that work across platforms and persist through installs.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro