A push notification is a short message that a website or app sends to your device, which appears even when the site is closed. On the web it needs three browser features: a service worker running in the background, the Push API to receive the message, and the Notifications API to display it, once the visitor agrees.
| Piece | What it does |
|---|---|
| Service worker | A script the browser keeps for your site that can wake up when a message arrives |
| Push API | Subscribes the browser and receives messages pushed from your server |
| Notifications API | Asks permission and draws the notification on screen |
| Your server | Stores each subscription and sends messages through the browser's push service |
Updated
Push is how a shop tells a customer their order shipped, or a booking site reminds someone of tomorrow's appointment, without email. Done well it is welcome; asked for too early it gets blocked for good. The demo below shows the permission states with a local notification only.
This checks what your browser supports and lets you show yourself one local notification. Nothing is subscribed and no server is involved.
What this browser supports: Notifications API, Service workers, Push API (PushManager), Secure page (HTTPS)
Notification permission right now:
Runs only when the visitor taps your button. The public key comes from your server's VAPID key pair.
document.querySelector("#notify").addEventListener("click", async () => {
if (!("serviceWorker" in navigator) || !("PushManager" in window)) return;
const permission = await Notification.requestPermission();
if (permission !== "granted") return;
const registration = await navigator.serviceWorker.register("/sw.js");
await navigator.serviceWorker.ready;
const subscription = await registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: VAPID_PUBLIC_KEY, // from your server
});
await fetch("/api/push-subscriptions", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(subscription),
});
});The service worker wakes on a push event and must show a notification for it.
self.addEventListener("push", (event) => {
const data = event.data ? event.data.json() : { title: "Update" };
event.waitUntil(
self.registration.showNotification(data.title, {
body: data.body,
icon: "/icon-192.png",
tag: data.tag || "general",
data: { url: data.url || "/" },
})
);
});
self.addEventListener("notificationclick", (event) => {
event.notification.close();
event.waitUntil(clients.openWindow(event.notification.data.url));
});
Push reaches the device's notification area, which makes it right for things that are time sensitive and personal: a delivery today, a table ready, a payment problem.
Anything long, or anything a person needs to find again later, belongs in email. A sale every day belongs nowhere near push.
After a visitor blocks notifications, the permission reads denied and MDN's own example simply stops asking; turning it back on is up to the visitor, in the browser's site settings. That is why a soft ask, your own banner before the real prompt, is common.
MDN also notes that Chrome and Firefox no longer allow the permission request from a cross-origin iframe, so ask from your own top-level page.
Yes, since iOS and iPadOS 16.4, for web apps added to the Home Screen. WebKit says such an app can ask for permission, and the request must come from a direct user action such as tapping a button.
No. MDN describes the Push API as letting a web app receive messages whether or not it is in the foreground, or even loaded. The service worker handles the message.
granted (the visitor allowed it), denied (they blocked it) and default (not decided). In the default state the browser acts as if it were denied.
Yes. MDN marks the Notifications permission request as available only in secure contexts, and says service workers are only available in secure contexts too (http://localhost counts while you develop).
An option to pushManager.subscribe() promising every push will produce something the user can see. MDN notes Chrome and Edge reject the subscription unless it is set to true.
Related: Progressive web apps, Double opt-in, Welcome email templates, Sentry breadcrumbs.
Start for free or see all free tools. We.Inc is free to start, with no card needed. AI building is on paid plans from $20 a month.
We.Inc is an AI-powered website builder you can resell under your own brand. Launch a branded client dashboard, bill on Stripe Connect, and deliver AI-generated websites in minutes. White-label plans start at $99 a month for 25 client sites, with a 7-day free trial and no per-site fees.