Push Notifications

Part 3 - Crafting Dynamic and Feature-Rich Push Notifications

March 4, 2024
Learn to craft eye-catching, dynamic push notifications using Notification API, Firebase Cloud Messaging, and best practices for separation of duties. Improve user engagement and app usage.
TABLE OF CONTENTS

In this portion of the series, we will focus on crafting dynamic and feature-rich notifications using the Notification API, incorporating push notification services, and leveraging push notification workers. Furthermore, we will examine best practices for separation of duties between main and worker threads and illustrate the process of frontend and backend integration for generating push notifications.

Read all parts of this push notification service workers series here:

  1. Part 1 - Getting Started with Web Push Notifications Service Workers
  2. Part 2 - Obtaining User Permissions and Managing Subscriptions for Web Push Notifications
  3. Part 3: Crafting Dynamic and Feature-Rich Push Notifications

Understanding Push Notification Services and Workers:

Push notification services refer to cloud-based infrastructure responsible for relaying push notifications from the backend server to client devices. They act as intermediaries facilitating communication between the backend and the client application. Common push notification services include Apple Push Notification service (APNs), Firebase Cloud Messaging (FCM), and Amazon Simple Notification Service (SNS).

Push notification workers, often implemented as service workers, operate independently from the main application thread. These specialized scripts manage push notification lifecycle events and facilitate the display of notifications. Separation of duties is achieved by delegating resource-heavy tasks and operations to the worker thread, preserving the main thread's performance and efficiency.

Designing Eye-catching Notifications with the Notification API

  1. Use the showNotification() method to create a local notification instance, passing in the title and an optional options object.
        
            self.registration.showNotification('Your Order Has Shipped', {
              body: 'Order #12345 shipped today! Track it now.',
              icon: './assets/images/shipped.png',
              actions: [{
                  action: 'track',
                  title: 'Track Shipment',
                  icon: './assets/images/track.png'
                },
                {
                  action: 'cancel',
                  title: 'Cancel Shipment',
                  icon: './assets/images/cancel.png'
                },
              ],
              vibrate: [200, 100, 200],
              lang: 'en-US',
              tag: 'order-shipped',
              timestamp: Date.now(),
              data: {
                orderId: '12345'
              }
            });
        
    

Available Properties for Personalizing Appearance and Behavior:

  • title: Required string representing the notification title.
  • body: Optional string describing the notification content.
  • icon: Optional URL pointing to a small image representing the notification.
  • actions: Optional array of objects, each containing an action, title, and potentially an icon.
  • vibrate: Optional array of numbers indicating vibration patterns.
  • lang: Optional string denoting the language of the notification.
  • tag: Optional string serving as a unique identifier for the notification.
  • timestamp: Optional number representing the UNIX timestamp for the notification.
  • data: Optional object holding arbitrary data associated with the notification.

Separating Responsibilities Between Main and Service Worker Threads:

  1. Limit interaction with the DOM to the main thread, avoiding manipulation from the service worker context.
  2. Handle UI-related activities, such as updating layout or querying user inputs, in the main thread.
  3. Perform expensive computations or operations involving large amounts of data in the service worker.

Personalizing Notifications Based on Context and Preferences:

  1. Adapt notifications dynamically by retrieving user preferences and device context. This can include language, theme, or geolocation.
        
            const userPreferences = /* Retrieve user preferences */;
            const deviceContext = /* Retrieve device context */;

            const notificationOptions = {
              ...userPreferences,
              ...deviceContext,
            };

            self.registration.showNotification('Updated Privacy Policy', notificationOptions);
        
    


Implementing Best Practices for Separation of Responsibilities:

  1. Offloading heavy computation and data processing tasks to the worker thread improves the main thread's performance and reduces lag.
        
            self.addEventListener('fetch', (event) => {
              if (/* Event matches complex criteria */) {
                event.waitUntil(() => {
                  /* Perform intensive task */
                });
              }
            });
        
    


Listening to Push Events and Executing Relevant Callbacks:

  • Attach a push event listener to the service worker and execute the appropriate callback functions based on the event data.
        
            self.addEventListener('push', (event) => {
              if (event.data) {
                const payload = event.data.json();
                const notificationOptions = payload.notification || {};
                self.registration.showNotification(payload.title, notificationOptions);
              }
            });
        
    
  • Within the handler, extract the necessary information from the event.data object, typically employing structured clone algorithms.
  • Construct and present the notification using showNotification().

Establishing Frontend and Backend Integration for Push Notifications:

  • Develop RESTful APIs at the backend to accept incoming push notification requests.
        
            func handlePushNotificationRequest(w http.ResponseWriter, r *http.Request) {
              var payload Payload
              json.NewDecoder(r.Body).Decode(&payload)
              // Process the payload and trigger push notification
            }
        
    
  • Generate and send push notifications via the POST method, transmitting the encoded subscription object and any accompanying metadata.
  • Format push notification payloads correctly, accounting for encryption, authentication, and compression.
 
      {
        "title": "Breaking News",
        "notification": {
          "body": "Lorem ipsum dolor sit amet.",
          "icon": "/path/to/icon.png",
          "actions": [...]
        },
        "data": {
          "url": "/news/breaking"
        }

    
  • Ensure compliance with the standards defined by the Internet Engineering Task Force (IETF) and W3C.
  • Validate and parse the received data at the frontend, executing the appropriate callback functions as needed.

Conclusion

In this series, we explored enabling and verifying push notifications using Firebase Cloud Messaging, obtained user permissions, managed subscriptions, constructed rich and interactive notifications, and established frontend and backend integration for generating push notifications. Following these guidelines empowers developers to effectively engage users, increase retention, and promote app usage.

Read all parts of this push notification service workers series here:

  1. Part 1 - Getting Started with Web Push Notifications Service Workers
  2. Part 2 - Obtaining User Permissions and Managing Subscriptions for Web Push Notifications
  3. Part 3: Crafting Dynamic and Feature-Rich Push Notifications
Written by:
ABOUT THE AUTHOR

What’s a Rich Text element?

The rich text element allows you to create and format headings, paragraphs, blockquotes, images, and video all in one place instead of having to add and format them individually. Just double-click and easily create content.

Static and dynamic content editing

A rich text element can be used with static or dynamic content. For static content, just drop it into any page and begin editing. For dynamic content, add a rich text field to any collection and then connect a rich text element to that field in the settings panel. Voila!

How to customize formatting for each rich text

Headings, paragraphs, blockquotes, figures, images, and figure captions can all be styled after a class is added to the rich text element using the "When inside of" nested selector system.

Implement a powerful stack for your notifications
By clicking “Accept All Cookies”, you agree to the storing of cookies on your device to enhance site navigation, analyze site usage, and assist in our marketing efforts. View our Privacy Policy for more information.