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.

Hostinger image

Get n8n VPS hosting 3x cheaper than a cloud solution

Get fast, easy, secure n8n VPS hosting from $4.99/mo at Hostinger. Automate any workflow using a pre-installed n8n application and no-code customization.

Start now

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay