-
Notifications
You must be signed in to change notification settings - Fork 987
Closed
Description
Operating System
Windows 11
Environment (if applicable)
132.0.6834.159
Firebase SDK Version
10.14.0
Firebase SDK Product(s)
Messaging
Project Tooling
Javascript
Detailed Problem Description
In the serviceWorker of a webpush, if a tab of the site where the webpush is open, when clicking on the notification it only goes to the tab, but does not redirect to the push link.
If I put notificationclick before const messaging = firebase.messaging();, it works, but then I don't have data on the correct push URL.
It has already been tested on SDK 11.2.0 as well and the error is the same.
// Firebase Cloud Messaging Service Worker
importScripts('https://www.gstatic.com/firebasejs/10.14.0/firebase-app-compat.js');
importScripts('https://www.gstatic.com/firebasejs/10.14.0/firebase-messaging-compat.js');
// Consistent unique identifier
const SERVICE_WORKER_ID = 'XYZ';
// Firebase configuration
const firebaseConfig = {
apiKey: "XYZ_XYZ",
authDomain: "XYZ.firebaseapp.com",
projectId: "XYZ",
storageBucket: "pXYZ.firebasestorage.app",
messagingSenderId: "XYZ",
appId: "1:XYZ:web:XYZ"
};
// Initialize Firebase
firebase.initializeApp(firebaseConfig);
const messaging = firebase.messaging();
// Advanced duplicate prevention with localStorage
const NOTIFICATION_STORAGE_KEY = 'pushbase_recent_notifications';
const ACTIVE_SW_KEY = 'pushbase_active_service_worker';
// Ensure only one service worker is active
function checkServiceWorkerSingleton() {
const now = Date.now();
const activeWorker = JSON.parse(localStorage.getItem(ACTIVE_SW_KEY) || '{}');
// If no active worker or worker is old, claim this one
if (!activeWorker.id || (now - activeWorker.timestamp > 60000)) {
localStorage.setItem(ACTIVE_SW_KEY, JSON.stringify({
id: SERVICE_WORKER_ID,
timestamp: now
}));
return true;
}
// If another worker is active, do not process
return activeWorker.id === SERVICE_WORKER_ID;
}
function storeNotification(notificationKey) {
try {
const now = Date.now();
const recentNotifications = JSON.parse(localStorage.getItem(NOTIFICATION_STORAGE_KEY) || '[]');
// Remove old notifications (older than 5 minutes)
const filteredNotifications = recentNotifications.filter(
item => now - item.timestamp < 5 * 60 * 1000
);
// Add new notification
filteredNotifications.push({
key: notificationKey,
timestamp: now
});
localStorage.setItem(NOTIFICATION_STORAGE_KEY, JSON.stringify(filteredNotifications));
} catch (error) {
console.error('Error storing notification:', error);
}
}
function isDuplicateNotification(payload) {
try {
const now = Date.now();
const notificationKey = JSON.stringify({
title: payload.notification?.title,
body: payload.notification?.body,
data: payload.data
});
const recentNotifications = JSON.parse(localStorage.getItem(NOTIFICATION_STORAGE_KEY) || '[]');
// Check for duplicate within last 5 minutes
const isDuplicate = recentNotifications.some(
item => item.key === notificationKey && now - item.timestamp < 5 * 60 * 1000
);
return isDuplicate;
} catch (error) {
console.error('Error checking duplicate notification:', error);
return false;
}
}
// Intercept and filter background messages
messaging.onBackgroundMessage((payload) => {
// Ensure only one service worker processes the message
if (!checkServiceWorkerSingleton()) {
console.log('Skipping notification - another service worker is active');
return;
}
console.log('Raw payload received:', payload);
// Check for duplicate notification across all browser contexts
if (isDuplicateNotification(payload)) {
console.log('Blocked duplicate notification');
return;
}
// Store notification to prevent duplicates
const notificationKey = JSON.stringify({
title: payload.notification?.title,
body: payload.notification?.body,
data: payload.data
});
storeNotification(notificationKey);
// Extract notification details
const notification = payload.notification || {};
const data = payload.data || {};
const fcmOptions = payload.webpush.fcm_options || {};
// Prepare notification options
const notificationOptions = {
body: notification.body || data.body || 'New notification',
icon: notification.icon || data.icon || '/public/assets/pushbase.svg',
badge: notification.badge || data.badge || '/public/assets/pushbase.svg',
tag: SERVICE_WORKER_ID, // Use consistent tag
// Advanced configuration
requireInteraction: notification.requireInteraction || data.requireInteraction || false,
renotify: false, // Prevent renotification
silent: notification.silent || data.silent || false,
// Additional metadata
data: {
url: fcmOptions.link || notification.click_action || data.url,
campaignId: data.campaignId,
segmentId: data.segmentId,
type: data.type,
swId: SERVICE_WORKER_ID
}
};
// Optional image
if (notification.image || data.image) {
notificationOptions.image = notification.image || data.image;
}
// Show unique notification
self.registration.showNotification(
notification.title || data.title || 'PushBase Notification',
notificationOptions
);
});
// Notification click handler
self.addEventListener('notificationclick', (event) => {
event.notification.close();
const notificationData = event.notification.data;
// Open URL or default
event.waitUntil(
clients.openWindow(
notificationData.url || '/teste2'
)
);
});
// Ensure single service worker instance
self.addEventListener('install', (event) => {
self.skipWaiting(); // Take over immediately
});
self.addEventListener('activate', (event) => {
event.waitUntil(self.clients.claim());
});
Steps and code to reproduce issue
Send push, receive push, click and not open correct url!