Tutorial
January 15, 2026 · 6 min read
Web Push implementation checklist
Web Push looks simple in a demo and gets complicated in production. This checklist covers the parts teams usually miss between "it works on my Chrome" and "it works for real users across browsers".
1. Service worker
- Serve a single
service-worker.jsfrom your origin root (scope matters — a worker under/js/can't control the whole site). - Handle the
pushevent and callshowNotification()within the event'swaitUntil()— browsers terminate the worker otherwise. - Handle
notificationclickto focus an existing tab or open the target URL.
2. VAPID keys
- Generate one VAPID key pair per application, not one shared pair. Keep the private key server-side only.
- Send the public key to the browser at subscription time; sign outgoing pushes with the private key.
3. Permission UX
- Never call
Notification.requestPermission()on page load. A cold prompt is denied ~90% of the time, and a denial is sticky. - Use a soft pre-prompt ("Want deploy alerts?") and only trigger the native prompt after the user opts in.
4. Subscription storage
- Store the full subscription (endpoint +
p256dh+auth) keyed to your user. - On HTTP
410 Gone/404from the push service, delete the subscription — it's permanently dead.
5. Safari & cross-browser
- Safari 16+ (macOS Ventura) supports the standard Web Push Protocol; older Safari does not. Feature-detect, don't assume.
- iOS Safari requires the site to be added to the Home Screen before it can request push permission.
OpenPushAPI handles the VAPID signing, dead-subscription cleanup (auto-removal on 410), and cross-browser delivery for you — you embed the SDK and call OpenPush.init(). See the documentation to get started.
Ready to ship push notifications?
Create free account →