Firebase JavaScript library for web and Node.js applications providing authentication, databases, storage, analytics, messaging, and other backend services
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Push notification service for web and mobile applications. Supports targeted messaging, topic subscriptions, and rich notifications.
/**
* Gets the Messaging service instance for the given app
* @param app - Firebase app instance, uses default if not provided
* @returns Messaging service instance
*/
function getMessaging(app?: FirebaseApp): Messaging;
/**
* Checks if Messaging is supported in the current environment
* @returns Promise resolving to boolean indicating support
*/
function isSupported(): Promise<boolean>;
interface Messaging {
/** Firebase app instance */
readonly app: FirebaseApp;
}Manage FCM registration tokens for targeting devices.
/**
* Gets the FCM registration token for the current device
* @param messaging - Messaging service instance
* @param options - Optional token request options
* @returns Promise resolving to FCM token
*/
function getToken(messaging: Messaging, options?: GetTokenOptions): Promise<string>;
/**
* Deletes the FCM registration token
* @param messaging - Messaging service instance
* @returns Promise resolving to boolean indicating success
*/
function deleteToken(messaging: Messaging): Promise<boolean>;
interface GetTokenOptions {
/** VAPID key for web push */
vapidKey?: string;
/** Service worker registration for notifications */
serviceWorkerRegistration?: ServiceWorkerRegistration;
}Usage Examples:
import { getMessaging, getToken, deleteToken, isSupported } from 'firebase/messaging';
// Check if messaging is supported
const messagingSupported = await isSupported();
if (!messagingSupported) {
console.log('Messaging not supported in this environment');
return;
}
const messaging = getMessaging();
// Get FCM token
try {
const token = await getToken(messaging, {
vapidKey: 'BKxYxBI...' // Your VAPID key from Firebase Console
});
if (token) {
console.log('FCM token:', token);
// Send token to server for targeting
await sendTokenToServer(token);
} else {
console.log('No registration token available');
}
} catch (error) {
console.error('Error getting token:', error);
}
// Delete token when user signs out
await deleteToken(messaging);
console.log('Token deleted');Handle incoming messages in the foreground.
/**
* Adds a listener for foreground messages
* @param messaging - Messaging service instance
* @param nextOrObserver - Message handler function or observer
* @returns Function to unsubscribe the listener
*/
function onMessage(
messaging: Messaging,
nextOrObserver: NextOrObserver<MessagePayload>
): Unsubscribe;
interface MessagePayload {
/** Collapse key for message grouping */
readonly collapseKey: string;
/** Custom data payload */
readonly data?: { [key: string]: string };
/** Sender ID */
readonly from: string;
/** Message ID */
readonly messageId: string;
/** Notification payload */
readonly notification?: NotificationPayload;
/** Message priority */
readonly priority: string;
/** Time to live */
readonly ttl: number;
/** FCM options */
readonly fcmOptions?: FcmOptions;
}
interface NotificationPayload {
/** Notification title */
readonly title?: string;
/** Notification body */
readonly body?: string;
/** Notification icon URL */
readonly icon?: string;
/** Notification image URL */
readonly image?: string;
/** Click action URL */
readonly click_action?: string;
/** Notification badge */
readonly badge?: string;
/** Notification sound */
readonly sound?: string;
/** Notification tag */
readonly tag?: string;
/** Notification color */
readonly color?: string;
}
interface FcmOptions {
/** Analytics label */
readonly analyticsLabel?: string;
/** Link for notification click */
readonly link?: string;
}
type NextOrObserver<T> = ((value: T) => void) | Observer<T>;
type Unsubscribe = () => void;
interface Observer<T> {
next?: (value: T) => void;
error?: (error: Error) => void;
complete?: () => void;
}Usage Examples:
import { getMessaging, onMessage } from 'firebase/messaging';
const messaging = getMessaging();
// Listen for foreground messages
const unsubscribe = onMessage(messaging, (payload) => {
console.log('Message received in foreground:', payload);
// Handle data payload
if (payload.data) {
console.log('Data payload:', payload.data);
}
// Handle notification payload
if (payload.notification) {
const { title, body, icon, image } = payload.notification;
// Show custom notification
showCustomNotification({
title: title || 'New Message',
body: body || 'You have a new message',
icon: icon || '/default-icon.png',
image: image,
data: payload.data
});
}
});
// Custom notification display
function showCustomNotification(options: {
title: string;
body: string;
icon?: string;
image?: string;
data?: { [key: string]: string };
}) {
// Create and display custom notification UI
const notificationElement = document.createElement('div');
notificationElement.className = 'notification';
notificationElement.innerHTML = `
<div class="notification-content">
<h4>${options.title}</h4>
<p>${options.body}</p>
${options.image ? `<img src="${options.image}" alt="Notification">` : ''}
</div>
`;
document.body.appendChild(notificationElement);
// Auto-remove after 5 seconds
setTimeout(() => {
notificationElement.remove();
}, 5000);
}
// Clean up listener
unsubscribe();Handle background messages using service worker.
// Import from messaging/sw for service worker context
import { getMessaging, onBackgroundMessage } from 'firebase/messaging/sw';
/**
* Adds a listener for background messages (service worker only)
* @param messaging - Messaging service instance
* @param nextOrObserver - Message handler function or observer
* @returns Function to unsubscribe the listener
*/
function onBackgroundMessage(
messaging: Messaging,
nextOrObserver: NextOrObserver<MessagePayload>
): Unsubscribe;Service Worker Example:
// firebase-messaging-sw.js
import { initializeApp } from 'firebase/app';
import { getMessaging, onBackgroundMessage } from 'firebase/messaging/sw';
const firebaseConfig = {
// Your config
};
const app = initializeApp(firebaseConfig);
const messaging = getMessaging(app);
// Handle background messages
onBackgroundMessage(messaging, (payload) => {
console.log('Background message received:', payload);
const notificationTitle = payload.notification?.title || 'Background Message';
const notificationOptions = {
body: payload.notification?.body || 'You have a new message',
icon: payload.notification?.icon || '/firebase-logo.png',
image: payload.notification?.image,
badge: payload.notification?.badge,
tag: payload.notification?.tag || 'default',
data: {
click_action: payload.notification?.click_action || '/',
...payload.data
},
actions: [
{
action: 'open',
title: 'Open App'
},
{
action: 'dismiss',
title: 'Dismiss'
}
]
};
self.registration.showNotification(notificationTitle, notificationOptions);
});
// Handle notification click
self.addEventListener('notificationclick', (event) => {
event.notification.close();
if (event.action === 'open' || !event.action) {
const clickAction = event.notification.data?.click_action || '/';
event.waitUntil(
clients.openWindow(clickAction)
);
}
});Request and check notification permissions.
// Request notification permission
async function requestNotificationPermission(): Promise<boolean> {
if ('Notification' in window) {
const permission = await Notification.requestPermission();
return permission === 'granted';
}
return false;
}
// Check current permission status
function getNotificationPermission(): NotificationPermission {
if ('Notification' in window) {
return Notification.permission;
}
return 'default';
}
// Usage
const hasPermission = await requestNotificationPermission();
if (hasPermission) {
// Get FCM token
const token = await getToken(messaging);
console.log('FCM token:', token);
} else {
console.log('Notification permission denied');
}Subscribe to topics for targeted messaging (server-side operation).
// Client-side: Send token to server for topic subscription
async function subscribeToTopic(token: string, topic: string) {
await fetch('/api/subscribe-to-topic', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ token, topic })
});
}
// Server-side example (Node.js)
// const admin = require('firebase-admin');
//
// app.post('/api/subscribe-to-topic', async (req, res) => {
// const { token, topic } = req.body;
//
// try {
// await admin.messaging().subscribeToTopic([token], topic);
// res.json({ success: true });
// } catch (error) {
// res.status(500).json({ error: error.message });
// }
// });Send messages from server to clients (server-side operation).
// Server-side example (Node.js with Firebase Admin SDK)
const admin = require('firebase-admin');
// Send to specific device
async function sendToDevice(token, notification, data) {
const message = {
token: token,
notification: {
title: notification.title,
body: notification.body,
imageUrl: notification.image
},
data: data,
webpush: {
notification: {
icon: '/firebase-logo.png',
click_action: 'https://myapp.com'
},
fcm_options: {
link: 'https://myapp.com'
}
}
};
try {
const response = await admin.messaging().send(message);
console.log('Message sent successfully:', response);
} catch (error) {
console.error('Error sending message:', error);
}
}
// Send to topic
async function sendToTopic(topic, notification, data) {
const message = {
topic: topic,
notification: notification,
data: data
};
const response = await admin.messaging().send(message);
console.log('Topic message sent:', response);
}
// Send to multiple devices
async function sendToMultipleDevices(tokens, notification, data) {
const message = {
tokens: tokens,
notification: notification,
data: data
};
const response = await admin.messaging().sendMulticast(message);
console.log('Multicast message sent:', response);
}import { getAuth, onAuthStateChanged } from 'firebase/auth';
import { getMessaging, getToken, deleteToken } from 'firebase/messaging';
const auth = getAuth();
const messaging = getMessaging();
// Manage FCM token based on auth state
onAuthStateChanged(auth, async (user) => {
if (user) {
// User signed in - get FCM token
try {
const token = await getToken(messaging);
if (token) {
// Associate token with user account
await associateTokenWithUser(user.uid, token);
}
} catch (error) {
console.error('Error getting FCM token:', error);
}
} else {
// User signed out - delete FCM token
try {
await deleteToken(messaging);
console.log('FCM token deleted on sign out');
} catch (error) {
console.error('Error deleting FCM token:', error);
}
}
});
async function associateTokenWithUser(userId: string, token: string) {
await fetch('/api/associate-token', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ userId, token })
});
}import { getAnalytics, logEvent } from 'firebase/analytics';
import { getMessaging, onMessage } from 'firebase/messaging';
const analytics = getAnalytics();
const messaging = getMessaging();
// Track notification events
onMessage(messaging, (payload) => {
// Log notification received event
logEvent(analytics, 'notification_received', {
notification_id: payload.messageId,
notification_title: payload.notification?.title,
has_data: payload.data ? 'yes' : 'no'
});
// Handle message
handleForegroundMessage(payload);
});
// Track notification interactions
function trackNotificationClick(messageId: string, action: string) {
logEvent(analytics, 'notification_click', {
notification_id: messageId,
action: action
});
}