Progressive Web Apps (PWA)

Push Notifications

16 min Lesson 8 of 30

Push Notifications in PWAs

Push notifications allow your PWA to send messages to users even when the app is not open. This powerful feature can significantly improve user engagement by delivering timely updates, alerts, and personalized content.

Push API Overview

The Push API enables web applications to receive messages pushed from a server, regardless of whether the app is active. It works in conjunction with Service Workers to display notifications.

Key Components:
  • Push Service: Browser-managed service that handles message delivery
  • Push Subscription: Unique endpoint for each user device
  • Notifications API: Displays visual notifications to users
  • Service Worker: Receives push events in the background
  • Application Server: Your backend that sends push messages

Requesting Notification Permission

Before sending notifications, you must request permission from the user:

// Check if notifications are supported if ('Notification' in window) { console.log('Notifications are supported'); } else { console.log('Notifications are not supported'); } // Request permission async function requestNotificationPermission() { const permission = await Notification.requestPermission(); if (permission === 'granted') { console.log('Notification permission granted'); return true; } else if (permission === 'denied') { console.log('Notification permission denied'); return false; } else { console.log('Notification permission dismissed'); return false; } } // Usage with user interaction document.getElementById('enable-notifications').addEventListener('click', async () => { const granted = await requestNotificationPermission(); if (granted) { await subscribeToPushNotifications(); } });
Important: Notification permission requests must be triggered by a user interaction (like clicking a button). Requesting permission on page load is considered bad UX and may be blocked by browsers.

Creating a Push Subscription

Subscribe the user to push notifications using the PushManager API:

// Generate VAPID keys first (server-side): // npm install web-push // npx web-push generate-vapid-keys const publicVapidKey = 'YOUR_PUBLIC_VAPID_KEY'; async function subscribeToPushNotifications() { try { const registration = await navigator.serviceWorker.register('/sw.js'); await navigator.serviceWorker.ready; const subscription = await registration.pushManager.subscribe({ userVisibleOnly: true, applicationServerKey: urlBase64ToUint8Array(publicVapidKey) }); console.log('Push subscription:', JSON.stringify(subscription)); // Send subscription to your server await fetch('/api/push-subscribe', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(subscription) }); console.log('Subscription saved to server'); return subscription; } catch (error) { console.error('Failed to subscribe:', error); } } function urlBase64ToUint8Array(base64String) { const padding = '='.repeat((4 - base64String.length % 4) % 4); const base64 = (base64String + padding).replace(/\-/g, '+').replace(/_/g, '/'); const rawData = window.atob(base64); const outputArray = new Uint8Array(rawData.length); for (let i = 0; i < rawData.length; ++i) { outputArray[i] = rawData.charCodeAt(i); } return outputArray; }

Handling Push Events in Service Worker

Listen for push events in your service worker and display notifications:

// In sw.js self.addEventListener('push', (event) => { let notificationData = { title: 'New Notification', body: 'You have a new message', icon: '/images/icon-192x192.png', badge: '/images/badge-72x72.png', tag: 'notification-1', data: { url: '/messages' } }; if (event.data) { const payload = event.data.json(); notificationData = { ...notificationData, ...payload }; } event.waitUntil( self.registration.showNotification(notificationData.title, { body: notificationData.body, icon: notificationData.icon, badge: notificationData.badge, tag: notificationData.tag, data: notificationData.data, vibrate: [200, 100, 200], actions: [ { action: 'open', title: 'Open' }, { action: 'close', title: 'Close' } ] }) ); });
Exercise:
  1. Implement a notification permission request UI with clear explanation
  2. Create a push subscription and send it to your server
  3. Set up a Node.js server with web-push to send test notifications
  4. Handle notification clicks to navigate to specific pages
  5. Add notification action buttons and handle their clicks