DEV Community

Shanu
Shanu

Posted on

Push Notification Frontend Setup: Connecting to Your Node.js Backend

In our previous article, we explored the backend implementation of a push notification system using Node.js. We covered how to set up a server to handle push notifications, manage user subscriptions, and ensure a production-grade environment. If you missed that, you can catch up on the details of backend setup and best practices in our first article.

In this second part, we shift our focus to the frontend implementation. Here, you'll learn how to integrate the push notification system with your web application's frontend. This involves requesting user permissions, registering a service worker, subscribing users to push notifications, and sending subscription data to your backend. By connecting the frontend and backend components, you'll create a complete push notification system that enhances user engagement even when your web application is not actively open.

Frontend Integration for Push Notifications

Integrating push notifications into the frontend involves several steps to ensure that users can subscribe to notifications and receive them even when the web application is not actively open. Here’s a step-by-step guide:

1. Request User Permission

Code:

// public/main.js

// Check if the browser supports service workers and notifications
if ('serviceWorker' in navigator && 'PushManager' in window) {
    // Register the service worker
    navigator.serviceWorker.register('/service-worker.js')
        .then(registration => {
            // Request permission for notifications
            return Notification.requestPermission()
                .then(permission => {
                    if (permission === 'granted') {
                        console.log('Notification permission granted.');
                    } else {
                        console.error('Notification permission denied.');
                    }
                });
        })
        .catch(error => {
            console.error('Service Worker registration failed:', error);
        });
}
Enter fullscreen mode Exit fullscreen mode

Explanation:

  • Service Worker and PushManager Support Check: We first check if the browser supports Service Workers and the PushManager API. Service Workers are a core technology for push notifications, allowing background scripts to handle push events.
  • Service Worker Registration: The navigator.serviceWorker.register('/service-worker.js') line registers a service worker from the service-worker.js file. This is crucial because the service worker is responsible for receiving push messages and displaying notifications.
  • Notification Permission Request: Notification.requestPermission() prompts the user to allow or deny notifications. This is a required step before you can send notifications to the user. Handling the user's response ensures that notifications are only sent if the user has granted permission.

2. Register a Service Worker

Code:

// public/service-worker.js

self.addEventListener('push', event => {
    const data = event.data.json();
    self.registration.showNotification(data.title, {
        body: data.body,
        icon: '/images/icon.png'
    });
});
Enter fullscreen mode Exit fullscreen mode

Explanation:

  • Service Worker Setup: The service-worker.js file contains the script that runs in the background of the user's browser.
  • Push Event Listener: self.addEventListener('push', event => {...}) listens for push events sent by the server. When a push message is received, this event triggers.
  • Displaying Notifications: self.registration.showNotification(data.title, {...}) shows a notification with the specified title and body. This is how the notification appears to the user. The icon can be customized to show a relevant image.

3. Subscribe to Push Notifications

Code:

// public/main.js

navigator.serviceWorker.ready
    .then(registration => {
        return registration.pushManager.subscribe({
            userVisibleOnly: true,
            applicationServerKey: urlBase64ToUint8Array('<YOUR_PUBLIC_VAPID_KEY>')
        });
    })
    .then(subscription => {
        // Send the subscription object to your backend
        return fetch('/api/subscribe', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify(subscription)
        });
    })
    .catch(error => {
        console.error('Failed to subscribe:', error);
    });

// Helper function to convert base64 VAPID key to Uint8Array
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;
}
Enter fullscreen mode Exit fullscreen mode

Explanation:

  • Service Worker Ready: navigator.serviceWorker.ready ensures that the service worker is fully installed and ready to handle push events.
  • Subscription: registration.pushManager.subscribe({...}) creates a subscription to the push service using the applicationServerKey, which is your public VAPID key. This key is required for sending notifications to this subscription.
  • Send Subscription to Backend: The subscription object is sent to your server, where it can be stored for future use. This allows your server to send notifications to the client.
  • Convert VAPID Key: urlBase64ToUint8Array converts the base64-encoded VAPID key to a Uint8Array. This conversion is necessary because the pushManager.subscribe method requires the key in this format.

4. Handle Subscription on the Backend

Code:

// /controllers/notificationController.js

const User = require('../models/user');

exports.saveSubscription = async (req, res, next) => {
    try {
        const { userId, subscription } = req.body;
        const user = await User.findById(userId);
        if (!user) {
            return res.status(404).json({ error: 'User not found' });
        }
        user.subscriptions.push(subscription);
        await user.save();
        res.status(200).json({ message: 'Subscription saved' });
    } catch (error) {
        next(error);
    }
};
Enter fullscreen mode Exit fullscreen mode

Explanation:

  • Save Subscription: The saveSubscription function takes the subscription object from the frontend and saves it to the database associated with a user. This allows your backend to keep track of which users want to receive notifications and where to send them.

5. Update Routes

Code:

// /routes/notificationRoutes.js

router.post('/subscribe', notificationController.saveSubscription);
Enter fullscreen mode Exit fullscreen mode

Explanation:

  • Subscription Route: Adds a new endpoint to handle subscription requests. When the frontend sends subscription data, this route calls the saveSubscription controller function to process and store the subscription.

Summary

Integrating push notifications into the frontend involves:

  1. Requesting Permission: Asking users to allow notifications.
  2. Registering a Service Worker: Setting up the background script to handle push messages and display notifications.
  3. Subscribing to Push Notifications: Creating a subscription and sending it to the backend.
  4. Handling Subscription Data on Backend: Storing subscription information in the database.
  5. Updating Routes: Adding endpoints to manage subscription data.

These steps ensure that your users can receive timely push notifications and that your application is set up to handle them correctly. Each step is crucial for creating a seamless experience for users while maintaining a robust backend system.

With the frontend integration now complete, you’ve successfully connected your web application to a fully functional push notification system. By following the steps outlined, you've learned how to request user permissions, register service workers, handle push events, and manage user subscriptions. This integration ensures that users receive timely updates and notifications, even when they're not actively interacting with your site.

If you haven’t yet explored the backend setup, be sure to review our first article for a comprehensive guide on the server-side implementation. Together, these articles provide a complete picture of how to build and deploy a robust push notification system in a production environment.

Feel free to revisit both parts of this series as you implement push notifications in your projects, and don’t hesitate to reach out if you have any questions or need further assistance.

Top comments (0)