DEV Community

Cover image for Send FCM Event to All Opened Client Windows Instead of Focused (FCM Default)
Mofajjal Rasul
Mofajjal Rasul

Posted on

Send FCM Event to All Opened Client Windows Instead of Focused (FCM Default)

Enhancing Multi-Tab Synchronization with Custom FCM Handling in Service Workers

Firebase Cloud Messaging (FCM) delivers push notifications by default to a browser’s focused tab. This article presents a service worker implementation that broadcasts FCM events to all active client windows, enabling real-time synchronization in multi-tab applications.

Core Implementation Strategy

The service worker employs the following key functionalities:

  1. Immediate Service Worker Activation

    • Uses skipWaiting() during installation and clients.claim() during activation to control pages instantly.
  2. Broadcasted Push Event Handling

    • Intercepts FCM push events, extracts payload data, and distributes messages to all open tabs via clients.matchAll(), ensuring universal event propagation.
  3. Notification Click Management

    • Captures notification clicks, encodes payload data into URL parameters, and directs users to a relevant page.
  4. Firebase Initialization

    • Configures Firebase with placeholder values to prevent initialization errors while maintaining custom push handling.

Optimized Service Worker Code

self.addEventListener('install', () => self.skipWaiting());  
self.addEventListener('activate', (event) => event.waitUntil(self.clients.claim()));  

self.importScripts('/firebase/firebase-app-compat.js', '/firebase/firebase-messaging-compat.js');  

self.addEventListener('notificationclick', (event) => {  
  event.notification.close();  
  const data = event.notification.data.FCM_MSG?.data;  
  if (data) {  
    const url = `/?pnBgClick=${btoa(JSON.stringify(data))}`;  
    event.waitUntil(self.clients.openWindow(url));  
  }  
});  

self.addEventListener('push', async (event) => {  
  const payload = event.data.json().data;  
  if (!payload) return;  
  const clients = await self.clients.matchAll({ type: 'window', includeUncontrolled: true });  
  clients.forEach(client => client.postMessage({ type: 'push-notification', payload }));  
});  

firebase.initializeApp({ apiKey: true, projectId: true, messagingSenderId: true, appId: true });  
firebase.messaging();  
Enter fullscreen mode Exit fullscreen mode

Client-Side Integration Example (React):

useEffect(() => {  
  const handler = (event) => { /* Handle message */ };  
  navigator.serviceWorker.addEventListener('message', handler);  
  return () => navigator.serviceWorker.removeEventListener('message', handler);  
}, []);  
Enter fullscreen mode Exit fullscreen mode

Key Advantages

  • Cross-Tab Consistency: Ensures simultaneous updates across all active tabs for unified user experiences.
  • Customization Flexibility: Extends beyond FCM defaults, enabling tailored event handling.
  • Enhanced Engagement: Delivers real-time updates to all sessions, improving responsiveness.

Conclusion

This implementation addresses FCM’s default single-tab targeting by leveraging service workers to broadcast events universally. Ideal for collaborative tools, chat applications, or any multi-tab interface requiring real-time synchronization, this approach guarantees consistent user experiences across all active sessions.

Top comments (0)