Web Push Notifications: Notifications API & Service Worker Integration

A user leaves the site — we lose them. Push notifications (using the Notifications API and Push API) bring back up to 30% of visitors, but implementing has pitfalls: browser blocking, Service Worker errors, incompatibility with some devices. We have implemented notifications for 15+ projects over 5+

Development and maintenance of all types of websites:

Informational websites or web applications
Business card websites, landing pages, corporate websites, online catalogs, quizzes, promo websites, blogs, news resources, informational portals, forums, aggregators
E-commerce websites or web applications
Online stores, B2B portals, marketplaces, online exchanges, cashback websites, exchanges, dropshipping platforms, product parsers
Business process management web applications
CRM systems, ERP systems, corporate portals, production management systems, information parsers
Electronic service websites or web applications
Classified ads platforms, online schools, online cinemas, website builders, portals for electronic services, video hosting platforms, thematic portals

These are just some of the technical types of websites we work with, and each of them can have its own specific features and functionality, as well as be customized to meet the specific needs and goals of the client.

Our competencies:

Frequently Asked Questions

Latest works

  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1285
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1241
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    982
  • image_crm_chasseurs_493_0.webp
    CRM development for Chasseurs
    1033
  • image_website-sbh_0.webp
    Website development for SBH Partners
    1104
  • image_website-_0.webp
    Website development for Red Pear
    554

A user leaves the site — we lose them. Push notifications (using the Notifications API and Push API) bring back up to 30% of visitors, but implementing has pitfalls: browser blocking, Service Worker errors, incompatibility with some devices. We have implemented notifications for 15+ projects over 5+ years and know how to do it without pain. On one large e-commerce site, integrating push notifications with a custom Service Worker increased return rate by 28% in the first month. At the same time, we avoided typical mistakes: requesting permission after a click, correct handling of notificationclick, and a fallback for iOS.

Why Notifications API Needs a Service Worker?

The Notifications API and Push API are distinct. The former shows a notification through the browser, the latter delivers an event from the server. For notifications when the tab is closed, you need both. A Service Worker is mandatory: it runs in the background and intercepts push events. Without it, notifications only appear when the page is open. The Notifications API allows web pages to display system notifications (MDN). Over 95% of browsers support the API, but for push notifications you also need the Push API. Our React hook for Notifications API and Push API reduces code by half compared to manual implementation.

How to Request Permission and Not Get Blocked?

The main rule is to request permission only after an explicit user action, otherwise the browser will automatically block the request:

async function requestNotificationPermission(): Promise<NotificationPermission> { if (!('Notification' in window)) { throw new Error('Notifications API not supported') } if (Notification.permission === 'granted') return 'granted' if (Notification.permission === 'denied') return 'denied' // Call only from event handler (click, submit, etc.) return Notification.requestPermission() } 

Displaying a Notification: On the Page and via Service Worker

For displaying a notification on an open page, use new Notification():

interface NotificationOptions { title: string body?: string icon?: string badge?: string tag?: string // Grouping — new notification replaces old one with same tag requireInteraction?: boolean // Do not auto-close data?: unknown actions?: NotificationAction[] // Buttons in notification (Service Worker only) } function showNotification(options: NotificationOptions): Notification | null { if (Notification.permission !== 'granted') return null const { title, ...rest } = options const notification = new Notification(title, rest) notification.onclick = (event) => { event.preventDefault() window.focus() notification.close() // Navigate based on notification.data } return notification } 

For notifications when the tab is closed — only through Service Worker:

// service-worker.ts self.addEventListener('push', (event: PushEvent) => { const data = event.data?.json() ?? {} event.waitUntil( self.registration.showNotification(data.title ?? 'New notification', { body: data.body, icon: '/icons/notification-icon-192.png', badge: '/icons/badge-72.png', tag: data.tag ?? 'default', data: { url: data.url }, actions: [ { action: 'open', title: 'Open' }, { action: 'dismiss', title: 'Close' }, ], }) ) }) self.addEventListener('notificationclick', (event: NotificationEvent) => { event.notification.close() if (event.action === 'dismiss') return const url = event.notification.data?.url ?? '/' event.waitUntil( clients.matchAll({ type: 'window' }).then((windowClients) => { const existingClient = windowClients.find((c) => c.url === url) if (existingClient) return existingClient.focus() return clients.openWindow(url) }) ) }) 

React Integration

React Hook for Easy Integration (click to expand)
function useNotifications() { const [permission, setPermission] = useState<NotificationPermission>( typeof Notification !== 'undefined' ? Notification.permission : 'denied' ) const [supported] = useState(() => 'Notification' in window) const request = useCallback(async () => { if (!supported) return const result = await requestNotificationPermission() setPermission(result) }, [supported]) const notify = useCallback( (options: NotificationOptions) => { if (permission !== 'granted') return null return showNotification(options) }, [permission] ) return { supported, permission, request, notify } } 
Handling Permission States in UI (click to expand)
function NotificationSettings() { const { supported, permission, request, notify } = useNotifications() if (!supported) { return <p>Notifications are not supported by your browser</p> } return ( <div> {permission === 'default' && ( <button onClick={request}>Enable notifications</button> )} {permission === 'granted' && ( <button onClick={() => notify({ title: 'Test', body: 'Notifications work' })}> Test </button> )} {permission === 'denied' && ( <p>Notifications are blocked. Enable in browser settings.</p> )} </div> ) } 

Push API and Comparison

Comparison: With Push API vs Without
Criteria Only Notifications API Notifications + Push API
Works when tab is closed No Yes
Requires Service Worker No Yes
Implementation time 0.5 day 1–2 days
Impact on return rate +10% +30%

Push notifications are 3x more effective for re-engagement compared to email campaigns. Push notifications bring 1.5 times more returns, and our clients report engagement growth up to 40%.

How Push API Works: VAPID and Backend

To send push messages through a service worker, you need a pair of VAPID keys (Voluntary Application Server Identification). The server generates them once, and the browser passes the endpoint and public key upon subscription. Then the server sends a POST request to the endpoint with an encrypted payload. Implementation on Node.js with web-push takes about 10 lines of code. Typical third-party services charge $100/month; our self-hosted solution is 5x cheaper for 100k subscribers.

What's Included in Integration

Deliverables
  • Implementation of permission request utilities and notification display.
  • React hook.
  • Handling all permission states (default, granted, denied).
  • Optional integration with Service Worker for Push API and VAPID keys on the backend.
  • Full documentation of the implemented code.
  • Access to the repository for your team.
  • Training session (1 hour) on maintaining and extending the system.
  • 30 days of post-launch support and bug fixes.
Typical Timeline and Cost
  • Without Push API: 0.5 day, $500.
  • With Push API: 2 days, $1,200.
  • Savings vs third-party services: up to $200/month.
Common Mistakes During Integration
  • Requesting permission before user click — browser immediately blocks.
  • Ignoring the tag field — each notification is created separately, cluttering the system tray.
  • Missing data.url in Service Worker — user cannot navigate from the notification.
  • Not accounting for iOS limitations (no actions, no requireInteraction).

Comparison of Push Notification Providers

Provider Free Limit VAPID Support Documentation
Firebase Cloud Messaging 1 million/month Yes Excellent
WebPush (self-hosted) Unlimited Yes Average
OneSignal 10,000 subscribers Yes Good

We guarantee that your implementation will pass Core Web Vitals checks and be compatible with Chrome, Firefox, Safari, and Edge. Our team has specialized in web notifications since 2019, with 15+ completed projects. The Notifications API is an open specification; we work strictly according to standards.