JavaScript Notification API
Introduction
The Notification API is a powerful feature of modern browsers that allows web applications to display desktop notifications to users. These notifications appear outside the browser window, making them perfect for alerting users about important events even when they're not actively viewing your web page.
In this guide, we'll explore how to use the Notification API to enhance user engagement and provide timely updates in your web applications.
Browser Support and Compatibility
The Notification API is supported by most modern browsers including Chrome, Firefox, Safari, and Edge. However, it's always good practice to check for compatibility before using it.
if ('Notification' in window) {
console.log('Notifications are supported in this browser');
} else {
console.log('This browser does not support notifications');
}
Permission Model
For security reasons, websites need explicit permission from users before they can display notifications. The Notification API provides a permission system with three possible states:
default
- The user hasn't been asked about notifications yetgranted
- The user has given permission to show notificationsdenied
- The user has declined permission to show notifications
Checking Permission Status
You can check the current permission status using:
console.log(Notification.permission);
// Output could be: "default", "granted", or "denied"
Requesting Permission
To request permission from the user:
async function requestNotificationPermission() {
try {
const permission = await Notification.requestPermission();
console.log('Permission status:', permission);
return permission;
} catch (error) {
console.error('Error requesting notification permission:', error);
}
}
// Using the function
requestNotificationPermission().then(permission => {
if (permission === 'granted') {
console.log('We can now show notifications!');
}
});
Important: Most browsers now require that the permission request is triggered by a user action like a button click, rather than automatically on page load.
Creating a Basic Notification
Once you have permission, creating a notification is straightforward:
function showSimpleNotification() {
// Check if we have permission first
if (Notification.permission === 'granted') {
const notification = new Notification('Hello there!', {
body: 'This is my first notification',
icon: '/path/to/icon.png'
});
} else if (Notification.permission !== 'denied') {
// We need to ask for permission first
Notification.requestPermission().then(permission => {
if (permission === 'granted') {
const notification = new Notification('Hello there!', {
body: 'This is my first notification',
icon: '/path/to/icon.png'
});
}
});
}
}
Notification Options
The Notification constructor accepts various options to customize how your notification appears:
const options = {
body: 'This is the notification message body',
icon: '/images/notification-icon.png',
badge: '/images/badge-icon.png', // A small icon for devices with limited space
image: '/images/large-image.jpg', // A large image to be shown in the notification
tag: 'message-notification', // An ID to group similar notifications
dir: 'ltr', // Text direction: 'ltr' (left to right) or 'rtl' (right to left)
lang: 'en-US', // Language of the notification content
vibrate: [200, 100, 200], // Vibration pattern for mobile devices
renotify: false, // Whether to alert the user again if a new notification replaces an old one
requireInteraction: false, // Whether the notification should remain active until the user clicks or dismisses it
silent: false, // Whether to suppress the default notification sound
timestamp: Date.now() // Timestamp for when the notification was created
};
const notification = new Notification('Notification Title', options);
Handling Notification Events
Notifications can trigger events that you can listen for:
function showNotificationWithEvents() {
if (Notification.permission === 'granted') {
const notification = new Notification('New Message', {
body: 'You received a new message',
icon: '/images/message-icon.png'
});
notification.onclick = function(event) {
console.log('Notification clicked');
window.focus(); // Focus the browser window that created the notification
// You could also navigate to a specific URL:
// window.location.href = 'https://example.com/messages';
notification.close(); // Close the notification
};
notification.onshow = function(event) {
console.log('Notification was shown to the user');
};
notification.onclose = function(event) {
console.log('User closed the notification');
};
notification.onerror = function(event) {
console.error('Error displaying notification');
};
}
}
Real-World Examples
Chat Application Notification
Here's how you might implement notifications in a chat application:
function notifyNewMessage(senderId, senderName, messageText) {
// Ensure we have notification permission
if (Notification.permission !== 'granted') {
return;
}
// Don't show notifications if the user is currently viewing the chat
if (document.hasFocus() && activeChatId === senderId) {
return;
}
// Create a notification with the sender's avatar and message preview
const notification = new Notification(senderName, {
body: messageText.substring(0, 100) + (messageText.length > 100 ? '...' : ''),
icon: `/images/user-avatars/${senderId}.jpg`,
tag: `chat-${senderId}`, // Group messages from the same sender
badge: '/images/chat-badge.png',
renotify: true
});
// When clicked, focus the window and open that specific chat
notification.onclick = function() {
window.focus();
openChatWithUser(senderId);
notification.close();
};
}
Task Reminder Application
For a task management application, you might implement deadline reminders:
function scheduleTaskReminder(taskId, taskTitle, dueDate) {
// Calculate time until the task is due
const now = new Date();
const timeTillDue = dueDate - now;
// Don't schedule if it's already past due
if (timeTillDue <= 0) return;
// Schedule a notification for 1 hour before the deadline
setTimeout(() => {
if (Notification.permission === 'granted') {
const notification = new Notification('Task Reminder', {
body: `"${taskTitle}" is due in 1 hour`,
icon: '/images/task-icon.png',
requireInteraction: true // Keep the notification visible until user interaction
});
notification.onclick = function() {
window.focus();
openTaskDetails(taskId);
notification.close();
};
}
}, timeTillDue - (60 * 60 * 1000)); // 60 * 60 * 1000 = 1 hour in milliseconds
}
Service Worker Integration
For more advanced notification scenarios, especially when you want to show notifications when your web app is not open, you should use Service Workers:
// First, register a service worker
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/service-worker.js')
.then(registration => {
console.log('Service Worker registered with scope:', registration.scope);
})
.catch(error => {
console.error('Service Worker registration failed:', error);
});
}
// Then, to send a notification via the service worker
function sendNotificationViaServiceWorker(title, options) {
if ('serviceWorker' in navigator && 'PushManager' in window) {
navigator.serviceWorker.ready.then(registration => {
registration.showNotification(title, options);
});
} else {
// Fall back to regular Notification
new Notification(title, options);
}
}
Your service worker file (service-worker.js
) would handle notification events:
self.addEventListener('notificationclick', event => {
const notification = event.notification;
const action = event.action;
notification.close();
// Handle notification click based on the action or default behavior
if (action === 'open') {
clients.openWindow('/inbox');
} else if (action === 'dismiss') {
// Just close the notification
} else {
// Default click action
clients.openWindow('/dashboard');
}
});
self.addEventListener('notificationclose', event => {
// You could log analytics when users dismiss notifications
console.log('User closed notification without taking action');
});
Best Practices
-
Don't abuse notifications - Only send notifications that are valuable to users
-
Respect user choices - If a user denies permission, don't continually ask them to enable notifications
-
Be mindful of timing - Avoid sending notifications during typical sleeping hours unless critical
-
Use notifications for time-sensitive information - Focus on real-time updates that users will find valuable
-
Make notification text clear and concise - Keep titles under 40 characters and body text under 100 if possible
-
Provide a meaningful icon - Use a recognizable icon that helps users identify the source of the notification
-
Group related notifications - Use the
tag
property to avoid notification overload -
Consider mobile users - Ensure notifications are valuable and non-intrusive on mobile devices
Common Pitfalls and Troubleshooting
Permission Request Being Ignored
Many modern browsers have added restrictions on requesting notification permissions:
// This may be ignored in some browsers:
window.addEventListener('load', function() {
Notification.requestPermission(); // ❌ Not triggered by user interaction
});
// Better approach:
document.getElementById('notification-button').addEventListener('click', function() {
Notification.requestPermission(); // ✅ Triggered by user interaction
});
HTTP vs HTTPS
The Notification API typically requires a secure context (HTTPS) in production environments. It may work on HTTP in localhost development environments, but will fail on deployed HTTP sites.
Permission Permanently Denied
If a user selects "Block" or "Never Allow" for notifications, websites cannot re-request permission programmatically. You'll need to guide users to change this setting in their browser preferences.
function checkAndInformAboutPermissions() {
if (Notification.permission === 'denied') {
// Show instructions to the user about how to enable notifications
document.getElementById('notification-instructions').style.display = 'block';
}
}
Summary
The JavaScript Notification API provides a powerful way to engage users with timely information outside of your web application's window. Key points to remember:
- Always check for browser support and user permission
- Request notification permission based on user action
- Keep notifications relevant, timely and non-intrusive
- Use service workers for notifications when your web app is not open
- Be respectful of user preferences and follow best practices
By implementing notifications thoughtfully, you can enhance user engagement and provide a more responsive user experience in your web applications.
Exercises
-
Create a simple web page with a button that requests notification permission and displays a basic notification when clicked.
-
Build a countdown timer that shows a notification when time runs out, with an option to restart the timer by clicking on the notification.
-
Implement a notification system that groups related notifications using the
tag
property. -
Create a service worker that handles notifications and responds to different action buttons included in the notification.
-
Build a notification scheduling system that allows users to receive reminders at specific times, even when your web page is not open.
Additional Resources
- MDN Web Docs: Notification API
- Web.dev: Notifications API
- Can I Use: Web Notifications
- Push API for server-initiated notifications
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)