Guide
Web Push Notifications Guide for Websites and Web Apps
Web Push lets a website reach users after they leave the page, when the browser and operating system allow it. A production system needs more than a permission prompt: it needs a service worker, VAPID keys, subscriber storage, backend-only sending, and logs.
What Web Push actually requires
A browser notification begins with permission, but permission alone does not send anything. The browser creates a push subscription tied to a service worker. Your backend stores that subscription with a stable `recipientId`. Later, the backend sends a message through the push service using VAPID credentials.
DNZ Notifications exposes this through subscriber registration and send endpoints. The browser or client-safe integration registers the device, while trusted backend code sends notifications with a private API key.
Implementation steps
First, serve a service worker from your domain. Second, request notification permission at a user-friendly moment, not immediately on page load. Third, call `pushManager.subscribe` with the public VAPID key. Fourth, register the subscription with `/v1/subscribers/register`. Fifth, send messages from your server using `/v1/send`.
Use a stable `recipientId` that matches your user or account model. If you use random IDs per browser session, you will not be able to target the same user across devices or recover cleanly when a subscription changes.
const registration = await navigator.serviceWorker.register("/sw.js");
const subscription = await registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: urlBase64ToUint8Array(VAPID_PUBLIC_KEY),
});
await fetch("https://api.example.com/v1/subscribers/register", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-Key": CLIENT_API_KEY,
},
body: JSON.stringify({
recipientId: "user_123",
platform: "web",
deviceTransport: "web_push",
webPush: subscription.toJSON(),
}),
});Sending notifications
Sending should happen from the backend. The payload should include a clear title, body, and optional data such as a URL or order ID. Do not put secrets in push payload data; browsers and operating systems may expose notification content in previews.
The DNZ send endpoint queues the notification and returns a notification ID. Delivery is asynchronous, so your UI should not treat the API response as proof that the user saw the message.
await fetch("https://api.example.com/v1/send", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-Key": process.env.DNZ_NOTIFICATIONS_API_KEY,
},
body: JSON.stringify({
recipientId: "user_123",
channel: "push",
title: "Order shipped",
body: "Your order DNZ-1042 is on the way.",
data: { orderId: "DNZ-1042", url: "/orders/DNZ-1042" },
}),
});Common mistakes
The most common mistake is asking for permission too early. Users reject prompts they do not understand. Ask after a clear action, such as enabling order updates or account alerts. Another mistake is losing subscriptions because the app does not refresh them after browser changes.
Also watch for over-sending. Push notifications are powerful because they interrupt the user. Use templates, segments, and logs to keep messages useful. Transactional notifications usually perform better than broad generic alerts.
FAQ
Does Web Push work after the tab is closed?
Yes, when the browser, OS, and user permission allow it through the service worker.
Do I need VAPID keys?
Yes. VAPID identifies the sender and is required for standards-based Web Push.
Can I send from frontend JavaScript?
Registration can happen in the frontend, but sending should happen from your backend.
Related content
Add Web Push to your product
Open DNZ Notifications and connect VAPID, subscribers, templates, and delivery logs.
Open notifications hub