How to Implement Push Notification in React.js

Summarize this article with:
Users forget about your app the moment they close the tab. Push notifications bring them back.
Learning how to implement push notification in React.js gives your application direct access to users through their browser, even when they’re not actively browsing your site.
This guide covers the complete implementation process: service worker registration, the Web Push API, permission handling, and message delivery from a Node.js backend.
You’ll also learn to integrate Firebase Cloud Messaging, handle common errors, and test across different browsers.
By the end, you’ll have a working notification system that boosts user engagement and retention.
How Do Push Notifications Work in Web Browsers
The browser acts as an intermediary between your web application and the push service provider.
When a user grants notification permission, the browser creates a unique push subscription endpoint tied to that specific device and browser combination.
Here’s the basic flow:
- User visits your site and the service worker registers
- Browser requests permission via the Notification API
- Upon approval, the Push Manager creates a subscription object
- Your server stores this subscription endpoint
- Server sends encrypted messages to the push service
- Push service delivers the message to the browser
- Service worker wakes up and displays the notification
Google Chrome uses Firebase Cloud Messaging as its push service. Firefox has its own Mozilla Push Service. Each browser vendor maintains separate infrastructure.
The entire process relies on the Web Push Protocol (RFC 8030) for standardized message encryption and delivery.
What is the Web Push API

The Web Push API is a W3C specification that enables servers to send messages to web applications regardless of whether the app is active.
It works alongside two other browser APIs: the Service Worker API and the Notification API.
The Push Manager interface handles subscription management, letting you subscribe users, retrieve existing subscriptions, and check the current permission state.
All push messages must be encrypted using VAPID (Voluntary Application Server Identification) keys for security and authentication.
MDN Web Docs and Google Developers provide comprehensive documentation on implementation specifics across different browser environments.
What is a Service Worker in React.js

A service worker is a JavaScript file that runs separately from your main React application thread.
It intercepts network requests, manages caching strategies, and handles background push events when the browser tab is closed.
According to caniuse.com, service workers are supported by approximately 87% of all internet users and virtually all major web browsers in 2025.
In React projects created with Create React App or Vite, you’ll need to manually create and register this worker file since it operates outside the normal React component lifecycle.
Service workers are a core requirement for building progressive web apps that deliver native-like experiences. The global PWA market reached $3.53 billion in 2024 and is projected to grow to $21.44 billion by 2033 at a 18.98% CAGR, according to Straits Research.
Service worker implementation checklist:
- Register the service worker in your main application file
- Handle installation, activation, and fetch events
- Implement cache-first or network-first strategies based on content type
- Update service workers when deploying new versions
- Test offline functionality thoroughly
How Does a Service Worker Handle Push Events
The worker listens for push events using self.addEventListener('push', callback).
When a message arrives, the callback extracts the notification payload and calls self.registration.showNotification() to display it.
The waitUntil() method keeps the worker alive until the notification renders completely.
Push notification best practices:
- Request permission at the right moment (not on page load)
- Provide clear value proposition before requesting permission
- Handle permission denial gracefully
- Include actionable buttons in notifications
- Track click-through rates and adjust messaging
What is the Service Worker Lifecycle
Three phases: installing, waiting, and active.
During installation, the worker downloads and caches resources. The waiting phase occurs when a previous version still controls the page. Once active, the worker intercepts fetch requests and handles push events.
Updates trigger automatically when the browser detects byte-level changes in the worker file.
Lifecycle management steps:
- Install event: Cache critical assets during first installation
- Activate event: Clean up old caches from previous versions
- Fetch event: Serve cached content or fetch from network
- Update flow: Skip waiting phase with
self.skipWaiting()when needed - Claim clients: Use
clients.claim()to control pages immediately
What Libraries Support Push Notifications in React.js
Several popular React libraries simplify push notification implementation by abstracting the underlying browser APIs.
Your choice depends on whether you need a full Backend as a Service/) solution or just client-side notification display.
What is Firebase Cloud Messaging for React

Firebase Cloud Messaging (FCM) is Google’s cross-platform messaging solution included in the Firebase SDK.
It handles token generation, subscription management, and message delivery across web and mobile platforms. Free tier supports unlimited notifications.
FCM implementation steps:
- Set up Firebase project in Firebase Console
- Add Firebase config to your React app
- Request notification permission from users
- Subscribe to FCM topics for targeted messaging
- Handle foreground and background notifications separately
FCM quota limits:
- Default rate: 600,000 requests per minute per Firebase project
- Adjust request timing to avoid load-balancing issues
- Implement exponential backoff for failed requests
- Monitor delivery rates using FCM Aggregate Delivery Data API
What is OneSignal for React Push Notifications

OneSignal provides a managed push notification service with built-in analytics, segmentation, and A/B testing.
Their React SDK reduces setup to a few lines of code. The free plan covers up to 10,000 subscribers.
OneSignal setup process:
- Create OneSignal account and app
- Install OneSignal React SDK (
react-onesignal) - Initialize with app ID in your root component
- Configure notification prompts and timing
- Set up user segments for targeted campaigns
- Track conversion metrics in OneSignal dashboard
When to choose OneSignal:
- Need pre-built analytics and segmentation tools
- Want A/B testing capabilities out of the box
- Require detailed delivery and engagement metrics
- Prefer managed service over DIY implementation
What is React-Toastify for In-App Notifications

React-Toastify handles foreground notifications displayed inside your application UI, not system-level push alerts.
Use it alongside FCM or OneSignal when you need to show messages while users actively browse your site.
React-Toastify configuration:
import { ToastContainer, toast } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';
// In root component
<ToastContainer position="top-right" autoClose={5000} />
// Trigger notification
toast.success('Action completed successfully');
toast.error('Something went wrong');
toast.info('New message received');
In-app notification strategy:
- Use for immediate feedback on user actions
- Show completion messages for async operations
- Display errors without disrupting user flow
- Combine with push notifications for multi-channel approach
- Customize position, duration, and styling per use case
How to Set Up Push Notifications in a React.js Project

Setup requires both front-end development work in React and back-end development for message delivery.
You’ll need a service worker file, VAPID keys, and a server endpoint to store subscriptions.
Push notification performance benchmarks:
- Average opt-in rate: 60% overall (Android: 67%, iOS: 56%)
- Average click-through rate: 4.6% on Android, 3.4% on iOS
- Open rate: 45-90% (compared to 15-30% for email)
- ROI: 3,500% for push notifications vs 122% for newsletters
How to Register a Service Worker in React
Create a file named sw.js in your public folder, then register it in your main component using navigator.serviceWorker.register('/sw.js').
Wrap the registration call in a check for 'serviceWorker' in navigator to handle unsupported browsers gracefully.
Service worker registration template:
useEffect(() => {
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js')
.then(registration => {
console.log('Service Worker registered:', registration);
})
.catch(error => {
console.error('Service Worker registration failed:', error);
});
}
}, []);
How to Request Notification Permission from Users
Call Notification.requestPermission() and await the response: granted, denied, or default.
Trigger this only after user interaction (button click), never on page load. Browsers block automatic permission requests.
Permission request best practices:
- Show value proposition before requesting (explain benefits)
- Request after user completes meaningful action (not on first visit)
- Provide context with a custom pre-permission modal
- Track permission flow: 95% of first-time visitors aren’t ready to purchase, but push notifications bring them back
Optimal timing for permission requests:
- After user adds item to cart
- Following successful account creation
- When user returns for second visit
- During checkout process (for order updates)
How to Subscribe Users to Push Notifications
After permission is granted, use registration.pushManager.subscribe() with your VAPID public key.
The method returns a PushSubscription object containing the endpoint URL and encryption keys.
Subscription implementation:
const subscribeUser = async (registration) => {
const vapidPublicKey = 'YOUR_PUBLIC_KEY';
const convertedKey = urlBase64ToUint8Array(vapidPublicKey);
try {
const subscription = await registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: convertedKey
});
await sendSubscriptionToServer(subscription);
} catch (error) {
console.error('Subscription failed:', error);
}
};
How to Generate and Store Push Subscription Data
Send the subscription object to your server via a POST request using API integration.
Store the endpoint, p256dh key, and auth secret in your database. Each subscription is unique per browser and device combination.
Subscription storage checklist:
- Create database table with fields: endpoint, p256dh, auth, userId, createdAt
- Index endpoint field for fast lookups during removal
- Associate subscriptions with user accounts
- Handle duplicate subscriptions (same user, multiple devices)
- Implement cleanup for expired subscriptions (inactive >270 days per FCM policy)
How to Send Push Notifications to a React Application
Message delivery happens server-side using the web-push npm package in Node.js or equivalent libraries in other languages.
Your server authenticates with VAPID credentials, encrypts the payload, and sends it to the browser’s push service endpoint.
Push notification engagement benchmarks by type:
- Contextual (triggered) campaigns: 14.4% open rate
- Generic broadcast campaigns: 4.19% open rate
- Transactional notifications: 69% open rate
- Personalized messages: 59% more engagement than generic
- Rich media notifications: 56% higher open rate
What is VAPID Authentication for Web Push
VAPID (Voluntary Application Server Identification) uses a public/private key pair to identify your server to push services.
Generate keys once using web-push generate-vapid-keys and store them securely as environment variables.
VAPID setup steps:
- Install web-push:
npm install web-push - Generate keys:
npx web-push generate-vapid-keys - Store in .env:
VAPID_PUBLIC_KEY=...andVAPID_PRIVATE_KEY=... - Never commit private key to version control
- Use same keys across all environments (production, staging)
How to Create a Backend Endpoint for Push Notifications
Build a RESTful API endpoint that accepts the notification title, body, and target subscription data.
The endpoint calls the web-push library’s sendNotification() method with the encrypted payload.
Backend endpoint structure:
app.post('/api/send-notification', async (req, res) => {
const { userId, title, body, url } = req.body;
// Fetch user subscriptions from database
const subscriptions = await getUserSubscriptions(userId);
const payload = JSON.stringify({ title, body, url });
const sendPromises = subscriptions.map(sub =>
webpush.sendNotification(sub, payload)
.catch(err => {
// Remove invalid subscriptions
if (err.statusCode === 410) {
removeSubscription(sub.endpoint);
}
})
);
await Promise.all(sendPromises);
res.json({ success: true });
});
How to Trigger Push Notifications from Node.js
Import web-push, set your VAPID details, then call webpush.sendNotification(subscription, payload).
Handle the promise rejection for expired or invalid subscriptions by removing them from your database.
Complete server setup:
const webpush = require('web-push');
webpush.setVapidDetails(
'mailto:your-email@example.com',
process.env.VAPID_PUBLIC_KEY,
process.env.VAPID_PRIVATE_KEY
);
// Send notification
const payload = JSON.stringify({
title: 'New Message',
body: 'You have a new notification',
icon: '/icon.png',
badge: '/badge.png',
data: { url: '/messages' }
});
await webpush.sendNotification(subscription, payload);
Push notification optimization strategies:
- Timing: Send between 9-11 AM or 6-9 PM for peak engagement
- Frequency: Space campaigns 1-2 days apart (46% opt-out after 2-5 messages/week)
- Personalization: Use user preferences for 4x higher engagement
- Segmentation: Currently only 20% of pushes are segmented (opportunity for improvement)
- A/B testing: Test send times for 40% increase in reaction rates
- Rich media: Add images for 33% engagement boost
How to Display Push Notifications in React
The service worker handles all notification rendering, not your React components.
React only manages foreground message handling when users actively browse your application.
How to Listen for Push Events in Service Workers
Add self.addEventListener('push', event => {...}) in your sw.js file.
Extract the payload with event.data.json() and pass title, body, icon, and badge to showNotification().
Service worker push handler:
self.addEventListener('push', event => {
const data = event.data.json();
const options = {
body: data.body,
icon: data.icon || '/icon-192x192.png',
badge: '/badge-72x72.png',
vibrate: [100, 50, 100],
data: {
dateOfArrival: Date.now(),
primaryKey: 1,
url: data.url
},
actions: [
{action: 'explore', title: 'View'},
{action: 'close', title: 'Close'}
]
};
event.waitUntil(
self.registration.showNotification(data.title, options)
);
});
How to Handle Notification Click Events
Listen for notificationclick events to control what happens when users tap the alert.
Use clients.openWindow(url) to redirect users to specific pages in your React application.
Click handler implementation:
self.addEventListener('notificationclick', event => {
event.notification.close();
if (event.action === 'explore') {
event.waitUntil(
clients.openWindow(event.notification.data.url)
);
} else if (event.action === 'close') {
// Notification closed, track dismissal
event.waitUntil(
fetch('/api/track-dismiss', {
method: 'POST',
body: JSON.stringify({ id: event.notification.data.primaryKey })
})
);
}
});
Action button best practices:
- Limit to 2 actions per notification (browser support varies)
- Use clear, action-oriented labels (“View Order”, not “Click Here”)
- Track both opens and dismissals for engagement metrics
- Implement deep linking to specific app sections
How to Show Foreground Notifications in React
When using Firebase, the onMessage() callback fires for messages received while the app is open.
Display these using React-Toastify, a custom notification component, or by calling the browser’s Notification constructor directly with React hooks.
Foreground message handling:
import { useEffect } from 'react';
import { onMessage } from 'firebase/messaging';
import { toast } from 'react-toastify';
useEffect(() => {
const unsubscribe = onMessage(messaging, (payload) => {
toast.info(
<div>
<strong>{payload.notification.title}</strong>
<p>{payload.notification.body}</p>
</div>,
{
onClick: () => window.location.href = payload.data.url
}
);
});
return () => unsubscribe();
}, []);
What Are Common Push Notification Errors in React
Most failures stem from service worker registration issues, permission denials, or expired subscriptions.
Proper defect tracking helps identify patterns across different browsers and devices.
Common error categories:
- Registration failures: 15-20% of cases
- Permission denials: 40% of users (browser-dependent)
- Expired subscriptions: 270-day inactivity threshold (FCM policy)
- Network issues: 5-10% during delivery
- VAPID authentication errors: 8-12% during setup
How to Fix Service Worker Registration Failures
Check that your sw.js file is served from the root path with correct MIME type (application/javascript).
HTTPS is required in production; localhost works for development only.
Registration troubleshooting checklist:
- Verify sw.js is at root domain (not in subdirectory)
- Check server returns
Content-Type: application/javascript - Confirm HTTPS on production (HTTP only works on localhost)
- Clear browser cache and re-register
- Check console for CORS errors
- Verify service worker scope matches expected path
Error handling pattern:
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js')
.then(registration => {
console.log('SW registered:', registration.scope);
})
.catch(error => {
console.error('SW registration failed:', error);
// Log to error tracking service
trackError('sw_registration_failed', { error: error.message });
});
}
How to Handle Denied Notification Permissions
Once denied, users must manually enable notifications in browser settings. Your code cannot re-prompt.
Store the permission state and show instructions for enabling notifications when status is “denied”.
Permission denial handling:
const handlePermissionDenied = () => {
// Store state to avoid repeated requests
localStorage.setItem('notification_permission', 'denied');
// Show instructional UI
setShowPermissionInstructions(true);
};
// Check permission before attempting subscription
const checkPermission = async () => {
const permission = await Notification.permission;
if (permission === 'denied') {
handlePermissionDenied();
return false;
}
return true;
};
User guidance for re-enabling:
- Chrome: Settings > Privacy and security > Site Settings > Notifications
- Firefox: Site Information (lock icon) > Permissions > Receive Notifications
- Safari: Safari > Settings for This Website > Allow Notifications
- Edge: Settings > Cookies and site permissions > Notifications
How to Debug Push Notification Delivery Issues
Use Chrome DevTools Application tab to inspect service worker status and test push messages manually.
Check for 410 (Gone) or 404 responses indicating expired or invalid subscription endpoints.
Debugging workflow:
- Open Chrome DevTools > Application > Service Workers
- Verify service worker is “activated and running”
- Use “Push” button to send test notification
- Monitor Network tab for push endpoint responses
- Check subscription endpoint validity (not 410/404)
- Verify VAPID keys match between client and server
- Test in incognito mode to rule out cache issues
Subscription validation:
const validateSubscription = async (subscription) => {
try {
// Test send to verify endpoint is valid
const response = await fetch('/api/test-subscription', {
method: 'POST',
body: JSON.stringify(subscription),
headers: { 'Content-Type': 'application/json' }
});
if (response.status === 410) {
// Subscription expired, remove and re-subscribe
await subscription.unsubscribe();
return false;
}
return response.ok;
} catch (error) {
console.error('Subscription validation failed:', error);
return false;
}
};
What Are the Browser Compatibility Requirements for Push Notifications
The Push API works in Google Chrome 50+, Mozilla Firefox 44+, Microsoft Edge 17+, and Opera 42+.
Safari requires a different implementation using Apple Push Notification service until Safari 16, which added standard Web Push support.
Browser support statistics (2025):
- Chrome: 95% of browser notification subscribers worldwide
- Safari desktop: 19.5% market share with push support
- Safari iOS: Supported from iOS 16.4+ (requires home screen installation)
- Firefox: Full support on desktop and Android
- Edge: Full support using Chrome’s infrastructure
Mobile browser support varies:
- Chrome on Android: full support
- Firefox on Android: full support
- Safari on iOS: supported from iOS 16.4+ (requires adding to home screen)
- Samsung Internet: full support
iOS-specific requirements:
- User must add website to home screen as PWA
- Web push only works when launched from home screen icon
- Standard Web Push API (same as Chrome/Firefox)
- iOS 17.4 briefly removed support in EU (later reinstated)
Device usage breakdown:
- 90% of push notification subscribers use mobile devices
- 10% use desktop devices
- 72.8% of web push traffic comes from mobile
- 85.1% of desktop opt-ins use Google Chrome
Always check navigator.serviceWorker and window.PushManager existence before attempting registration.
Feature detection:
const isPushSupported = () => {
if (!('serviceWorker' in navigator)) {
console.warn('Service Workers not supported');
return false;
}
if (!('PushManager' in window)) {
console.warn('Push API not supported');
return false;
}
if (!('Notification' in window)) {
console.warn('Notifications not supported');
return false;
}
return true;
};
// iOS PWA detection
const isIOSPWA = () => {
return ('standalone' in window.navigator) &&
window.navigator.standalone === true;
};
Run integration testing across target browsers to verify consistent behavior before deployment.
Cross-browser testing checklist:
- Test service worker registration on all target browsers
- Verify notification display styling (icons, badges, actions)
- Confirm click handlers work correctly
- Test permission request flow on each platform
- Validate iOS PWA home screen installation
- Check notification delivery with offline/online states
- Measure delivery success rates per browser (target >85%)
FAQ on How To Implement Push Notification in React.js
Do push notifications work without a service worker?
No. The Service Worker API is required for receiving push messages when the browser tab is closed. The worker runs in the background, listens for push events, and displays notifications independently of your React application.
Is HTTPS required for push notifications?
Yes. Browsers enforce HTTPS for service worker registration and the Push API in production environments. Localhost is the only exception during development. This security requirement protects the encrypted communication between your server and the push service.
How do I generate VAPID keys for web push?
Run npx web-push generate-vapid-keys in your terminal. Store the public and private keys as environment variables. The public key goes to your React app; the private key stays on your Node.js server for VAPID authentication.
Why are my push notifications not showing on mobile?
Mobile browsers have stricter requirements. Chrome on Android needs the site added to home screen for reliable delivery. Safari on iOS requires iOS 16.4+ and PWA installation. Check mobile application development patterns for platform-specific handling.
Can I send push notifications to specific users?
Yes. Store each user’s push subscription endpoint in your database linked to their account. When triggering notifications, query subscriptions by user ID and send targeted messages only to those endpoints.
How do I handle expired push subscriptions?
Monitor for 410 (Gone) or 404 responses when sending notifications. These indicate invalid subscriptions. Remove them from your database immediately. Implement a cleanup routine as part of your software development process.
What is the maximum payload size for web push?
The Web Push Protocol limits payload to 4KB. Keep your notification data minimal: title, body, icon URL, and a click action URL. Store additional data on your server and fetch it when the user clicks the notification.
How do I test push notifications locally?
Use Chrome DevTools Application tab. Navigate to Service Workers, then click “Push” to simulate incoming messages. You can also use the web-push library’s sendNotification() method pointed at your localhost subscription endpoint.
Can Firebase Cloud Messaging work with other backends?
Yes. FCM provides REST APIs that any backend can call. Your server sends HTTP requests to Firebase’s endpoint with the device token and message payload. Python, PHP, Ruby, and Go all have compatible libraries available.
How do I add action buttons to push notifications?
Include an actions array in your notification options with title and action identifiers. Handle clicks in the service worker’s notificationclick event by checking event.action to determine which button the user tapped.
Conclusion
Knowing how to implement push notification in React.js transforms your web application into a real-time communication channel with users.
The setup requires coordination between your service worker, the Notification API, VAPID keys, and a server using the web-push npm package.
Test your implementation across Chrome, Firefox, and Edge to ensure cross-browser compatibility. Mobile requires extra attention, particularly Safari on iOS.
Monitor your notification opt-in rate and push delivery rate to measure effectiveness. Remove expired subscriptions promptly to maintain a clean database.
Start with basic text notifications, then expand to include action buttons, images, and notification badges as your codebase matures.
The result: higher user retention and direct access to your audience.
- Feature-Driven Development vs Agile: Key Differences - March 12, 2026
- Agile vs DevOps: How They Work Together - March 11, 2026
- Ranking The Best Mapping Software by Features - March 11, 2026







