Skip to content

Notification Options — Rich Push Notifications with Actions and Media

DodaTech Updated 2026-06-28 6 min read

In this tutorial, you will learn about Notification Options. We cover key concepts, practical examples, and best practices to help you master this topic.

Rich notification options include action buttons, images, badges, vibration patterns, sounds, and grouping — making PWA notifications as capable as native notifications on mobile and desktop.

What You'll Learn

By the end of this tutorial, you will understand all available notification options, how to use actions for user interaction, how to group related notifications, and how to customize the notification appearance.

Why It Matters

Basic text-only notifications get ignored. Rich notifications with action buttons, images, and clear grouping increase engagement rates by 2-3x. Well-designed notifications let users take action (reply, approve, snooze) directly from the notification, reducing the friction of reopening your app.

Real-World Use

A project management PWA sends notifications for task assignments with action buttons: "Accept", "Delegate", and "View Details". Accepting directly from the notification updates the task status without opening the app. The notification also shows the task priority color and due date.

Available Notification Options

Notification Options Overview
    ┌──────────────────────────────────────────────────────────┐
    │                    Notification                          │
    ├──────────────────────────────────────────────────────────┤
    │  Icon: [●]  Title: "Task Assigned"                      │
    │  Body: "You have been assigned 'Update docs'"            │
    │  Image: [screenshot of task]                             │
    │  Badge: [3]                                              │
    │  ┌──────────┐  ┌──────────┐  ┌──────────┐              │
    │  │  Accept  │  │ Delegate │  │  Dismiss │              │
    │  └──────────┘  └──────────┘  └──────────┘              │
    │  ──────────────────────────────────────────             │
    │  Silent mode: on/off   Alert type: persistent            │
    └──────────────────────────────────────────────────────────┘

Think of notification options like the features of a smartphone notification. A basic notification is like a text message — just words. Rich notifications are like a message with photos, action buttons, and quick replies — far more useful and actionable.

Comprehensive Notification Example

self.addEventListener('push', event => {
    const data = event.data.json();

    const options = {
        // Core content
        body: data.body,
        icon: data.icon || '/icons/icon-192.png',
        image: data.image,
        badge: '/icons/badge.png',

        // Behavior
        tag: data.tag || 'default',
        renotify: false,
        silent: false,
        requireInteraction: true,
        data: {
            url: data.url,
            messageId: data.id,
            timestamp: Date.now()
        },

        // Actions (buttons)
        actions: [
            {
                action: 'accept',
                title: 'Accept',
                icon: '/icons/check.png'
            },
            {
                action: 'view',
                title: 'View Details',
                icon: '/icons/view.png'
            },
            {
                action: 'dismiss',
                title: 'Dismiss'
            }
        ],

        // Visuals
        vibrate: [200, 100, 200],
        sound: '/sounds/notification.mp3',
        timestamp: Date.now(),

        // Android-specific
        priority: 'high',
        appBadgeCount: 5
    };

    event.waitUntil(
        self.registration.showNotification(data.title, options)
    );
});

Action Buttons and Handling

self.addEventListener('notificationclick', event => {
    event.notification.close();

    const action = event.action;
    const data = event.notification.data;

    console.log('Action:', action, 'Data:', data);

    switch (action) {
        case 'accept':
            // Accept the task via API
            event.waitUntil(
                fetch(`/api/tasks/${data.messageId}/accept`, {
                    method: 'POST'
                }).then(() => {
                    console.log('Task accepted');
                })
            );
            break;

        case 'view':
            // Open the task page
            event.waitUntil(
                clients.openWindow(data.url)
            );
            break;

        case 'dismiss':
            // Just close, no further action
            console.log('Notification dismissed');
            break;

        default:
            // Click on the notification body (not an action)
            event.waitUntil(
                clients.openWindow(data.url || '/')
            );
            break;
    }
});

Notification Grouping with Tags

Use the tag property to replace or group related notifications:

// Tag-based notification grouping
self.addEventListener('push', event => {
    const data = event.data.json();

    // Use same tag for related notifications
    // New notification with same tag replaces the old one
    const options = {
        body: data.body,
        tag: data.type === 'chat' ? `chat-${data.chatId}` : `default-${data.type}`,
        renotify: true, // Vibrate even if replacing
        data: { ... }
    };

    event.waitUntil(
        self.registration.showNotification(data.title, options)
    );
});

Badge and App Badge Count

// Set app badge (number on icon)
self.addEventListener('push', event => {
    const data = event.data.json();

    // Update badge count
    if (navigator.setAppBadge) {
        navigator.setAppBadge(data.unreadCount || 0);
    }

    // Notification with badge icon (small monochrome icon)
    const options = {
        body: data.body,
        badge: '/icons/badge.png', // 96x96 monochrome PNG
        icon: '/icons/icon-192.png', // Full color icon
        appBadgeCount: data.unreadCount
    };

    event.waitUntil(
        self.registration.showNotification(data.title, options)
    );
});

// Clear badge when user opens the app
self.addEventListener('notificationclick', event => {
    if (navigator.clearAppBadge) {
        navigator.clearAppBadge();
    }
    // ...
});

Vibration Patterns

// Different vibration patterns for different notification types
const VIBRATION_PATTERNS = {
    message: [200, 100, 200],          // Two short buzzes
    urgent: [500, 200, 500, 200, 500], // Three long buzzes
    alert: [200],                       // Single short buzz
    silent: []                          // No vibration
};

self.addEventListener('push', event => {
    const data = event.data.json();
    const pattern = VIBRATION_PATTERNS[data.priority] || VIBRATION_PATTERNS.message;

    const options = {
        body: data.body,
        vibrate: pattern,
        silent: data.priority === 'silent'
    };

    event.waitUntil(
        self.registration.showNotification(data.title, options)
    );
});

Timestamp and Priority

self.addEventListener('push', event => {
    const data = event.data.json();

    const options = {
        body: data.body,
        timestamp: data.timestamp || Date.now(), // Controls display order
        urgent: data.urgent || false,
        priority: data.urgent ? 'high' : 'default',

        // On Android, high priority notifications
        // show as heads-up (pop over other apps)
        ...(data.urgent && { priority: 'high', vibrate: [500, 200, 500] })
    };

    event.waitUntil(
        self.registration.showNotification(data.title, options)
    );
});

Common Mistakes

  1. Using too many actions. More than 3 action buttons gets truncated on most devices. Limit actions to 2-3 critical options.
  2. Not setting a tag. Without a tag, every notification is separate. Unread counts become unmanageable. Always set a meaningful tag.
  3. Ignoring renotify behavior. When replacing a notification with the same tag, set renotify: true if you want the device to vibrate/alert again.
  4. Badge images that are not monochrome. The badge icon must be monochrome (single color). Color images are not supported for badges.
  5. Not handling the default click action. Users may click the notification body, not an action button. Always handle the default case (event.action === '') by opening the app.

Practice Questions

  1. What does the tag property do in notification options?
  2. How do action buttons work and how are they handled?
  3. What is the difference between icon, badge, and image in notifications?
  4. How do you set a vibration pattern for different notification types?
  5. What happens when you set renotify: true with an existing tag?

Challenge: Create a chat notification system with: grouped notifications per conversation (tag), reply action button, different vibration patterns for messages vs mentions, badge count updates, and a 5-second auto-dismiss for non-urgent notifications.

FAQ

Can notification actions include text input?

No, the Notification API does not support text input directly. For replies, open the app to a reply interface. Some platforms support 'inline reply' but this is not standard.

What image formats are supported for notification icons?

PNG is the most widely supported. For badge icons, use a monochrome PNG. For the main icon, use a color PNG with transparent background.

How long do notifications persist?

Notification persistence depends on the device and user settings. set requireInteraction: true to keep the notification until the user interacts with it.

Can I update a notification after it is shown?

No, you cannot update a displayed notification. Replace it by showing a new notification with the same tag. The old notification is replaced.

Do notification sounds work on mobile?

Sound support varies. Some mobile browsers ignore the sound option. If sound is critical, design your app to play sounds via the Web Audio API when the user is active.

Mini Project

Build a notification system for a task management PWA with: three action buttons (Accept, Delegate, Dismiss), priority-based vibration patterns, task count badge, grouped notifications per project (using tags), and a default click that opens the specific task page. Test on both desktop and mobile.

What's Next

You have mastered notification content. Now learn how to handle notification permissions — requesting permission gracefully, handling denial, and respecting user preferences.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro