This guide walks you through the process of creating a custom push notification system, from the moment a user visits your site to when they receive a push notification. We'll cover the flow of events, data handling, and the interactions between the client (browser) and server.
The Process: Step by Step
1. User Visits Your Website
When a user first visits your website, two main steps occur:
- Service Worker Registration: Your JavaScript checks if the browser supports service workers and registers one if supported. This is done using the following code:
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/service-worker.js')
.then(function(registration) {
console.log('Service Worker registered with scope:', registration.scope);
}).catch(function(error) {
console.error('Service Worker registration failed:', error);
});
}
-
User Permission Request: The site prompts the user to allow push notifications. This is done using the
Notification.requestPermission()
method:
Notification.requestPermission().then(function(permission) {
if (permission === 'granted') {
console.log('Notification permission granted.');
// Proceed to subscribe the user to push notifications
} else {
console.log('Notification permission denied.');
}
});
2. User Subscribes to Push Notifications
If the user grants permission, the following steps occur:
-
Create Push Subscription: The service worker's
PushManager
subscribes the user to push notifications. This is done using the following function:
function subscribeUser() {
navigator.serviceWorker.ready.then(function(registration) {
const publicKey = 'Your Public VAPID Key Here';
registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: urlBase64ToUint8Array(publicKey)
}).then(function(subscription) {
console.log('User is subscribed:', subscription);
// Send the subscription to your server
sendSubscriptionToServer(subscription);
}).catch(function(error) {
console.error('Failed to subscribe the user:', error);
});
});
}
- Send Subscription to Server: The subscription object is sent to your server via an AJAX request. You can use a function like this:
function sendSubscriptionToServer(subscription) {
return fetch('/save-subscription', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(subscription)
}).then(function(response) {
if (!response.ok) {
throw new Error('Failed to save subscription on server');
}
return response.json();
}).then(function(data) {
console.log('Subscription saved on server:', data);
}).catch(function(error) {
console.error('Error saving subscription on server:', error);
});
}
- Server Saves Subscription: Your server receives the subscription object and stores it in a database. A simple database schema might look like this:
CREATE TABLE push_subscriptions (
id SERIAL PRIMARY KEY,
endpoint TEXT NOT NULL,
auth_key TEXT NOT NULL,
p256dh_key TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
3. Sending a Push Notification
When you want to send a notification:
-
Prepare Notification Payload: Create a payload for the notification on your server. This could be a JSON object containing
title
,body
,icon
, and other relevant data:
const payload = JSON.stringify({
title: 'Hello!',
body: 'You have a new notification.',
icon: '/icon.png',
badge: '/badge.png'
});
-
Send Push Notification: Use a library like
web-push
to send the notification to subscribed users. Here's an example of how to do this:
const webpush = require('web-push');
const vapidKeys = {
publicKey: 'Your Public VAPID Key Here',
privateKey: 'Your Private VAPID Key Here'
};
webpush.setVapidDetails(
'mailto:your-email@example.com',
vapidKeys.publicKey,
vapidKeys.privateKey
);
// Retrieve subscriptions from the database
const subscriptions = getSubscriptionsFromDatabase();
subscriptions.forEach(subscription => {
webpush.sendNotification(subscription, payload)
.then(response => console.log('Notification sent:', response))
.catch(error => console.error('Error sending notification:', error));
});
- Handle Push Event in Service Worker: The service worker displays the notification when it reaches the user's browser. This is done by adding an event listener in your service worker file:
// service-worker.js
self.addEventListener('push', function(event) {
const data = event.data.json();
const options = {
body: data.body,
icon: data.icon,
badge: data.badge
};
event.waitUntil(
self.registration.showNotification(data.title, options)
);
});
4. Handling User Interaction with Notifications
When a user interacts with a notification, the service worker listens for the notificationclick
event. You can handle this event in your service worker like this:
// service-worker.js
self.addEventListener('notificationclick', function(event) {
event.notification.close();
event.waitUntil(
clients.openWindow('https://yourwebsite.com')
);
});
If you define custom actions within the notification, you can handle these too:
self.addEventListener('notificationclick', function(event) {
const action = event.action;
if (action === 'view') {
clients.openWindow('/specific-page');
} else {
clients.openWindow('/');
}
event.notification.close();
});
Error Handling and Maintenance
To handle failed notifications and clean up your database, you can use error handling in your notification sending code:
webpush.sendNotification(subscription, payload)
.catch(error => {
if (error.statusCode === 410 || error.statusCode === 404) {
console.log('Subscription has expired or is no longer valid:', subscription.endpoint);
// Remove subscription from database
deleteSubscriptionFromDatabase(subscription.endpoint);
} else {
console.error('Error sending notification:', error);
}
});
Regularly check and clean up your database by removing subscriptions that are no longer valid.
Tech Stack
To implement this system, you'll need:
- Client-Side: HTML/CSS/JavaScript, Service Worker, Push API, Notifications API
- Server-Side: Node.js, Express.js, Web-Push Library, Database (e.g., PostgreSQL, MySQL)
- General Tools: Web Server (e.g., Nginx), SSL Certificate, Git, NPM or Yarn
- Optional: Monitoring Tools, Automated Deployment Tools, Database Backup Solutions
Summary
This guide provides a robust, self-hosted push notification system, ensuring full control and customization. The process involves setting up a service worker, managing user permissions, handling subscriptions, sending notifications, and maintaining the system. With this setup, you have complete control over your notification system, allowing for customization and optimization according to your specific needs.
Top comments (0)