Web Push (browser notifications)
Send notifications to your visitors' browsers — even when your site isn't open. JourneyLayer Web Push uses the standard Web Push Protocol (VAPID), so one setup covers Chrome, Edge, Firefox, and macOS Safari 16+.
The SDK never prompts for notification permission on page load. The native
browser prompt only appears when you call JourneyLayer.webPush.subscribe()
(or requestPermission()) from a real user action — a button click or a soft
prompt's "Allow". This is both a browser requirement and good UX.
Customer setup (6 steps)
1. Add the JourneyLayer hosted script
If you haven't already, install the Website SDK — see Install:
<script src="https://cdn.journeylayer.com/p/<PROJECT_PUBLIC_ID>/jl-script.js" async></script>
2. Add your site to Allowed domains
Web Push subscribe/unsubscribe calls are origin-checked just like events. Add
every origin you serve from under Settings → SDK / Install → Allowed
domains (apex + www + staging). See
Allowed domains.
3. Configure VAPID keys
In the dashboard, open Settings → Channels → Web push → Browser & OS:
- Click Generate keypair (the private key is stored encrypted server-side and never shown), then
- Enable the browsers you support (Chrome/Edge, Firefox, Safari) and Save
each. Set a VAPID subject (a
mailto:orhttps:contact for the push service).
4. Upload jl-sw.js to your website root
A push service worker must be same-origin with your pages — browsers won't
register one from track.yourdomain.com or our CDN. So host our default worker
on your own domain:
- Download
jl-sw.jsand upload it to your site root, reachable athttps://yoursite.com/jl-sw.js. - If you host it at a different path, set that path in the browser card's
Service worker path field (default
/jl-sw.js).
The worker handles displaying the notification, opening the click‑through URL, and best‑effort delivery/click tracking.
The JourneyLayer SDK is loaded cross-origin (from our CDN or your
track. subdomain), so it cannot register the push service worker for you —
browsers only allow a service worker to be registered from the same origin
as the page. This is why jl-sw.js must be hosted on your website root.
The <script> SDK and the same-origin jl-sw.js worker are two separate files
and the script can't replace the worker.
5. Ask for permission from a button or soft prompt
Call subscribe() from a click — never on load:
<button id="enable-notifications">Enable notifications</button>
<script>
document.getElementById('enable-notifications').addEventListener('click', async () => {
const res = await JourneyLayer.webPush.subscribe();
if (res.ok) {
console.log('Subscribed to web push');
} else {
console.log('Not subscribed:', res.reason); // e.g. permission_denied, not_configured
}
});
</script>
6. Verify the subscription
In JourneyLayer → Profiles / Find People, the visitor's profile shows a Web Push Subscribed event in their activity. You can also send a test from Settings → Channels → Web push → Send test.
SDK reference
All methods are on JourneyLayer.webPush and are safe to call — they return a
result object and never throw. If Web Push isn't configured for your project,
subscribe() resolves with { ok: false, reason: 'not_configured' }.
| Method | Returns | Notes |
|---|---|---|
getPermissionStatus() | 'default' | 'granted' | 'denied' | 'unsupported' | Synchronous. |
requestPermission() | Promise<NotificationPermission> | Shows the native prompt. Call from a user gesture. |
subscribe() | Promise<{ ok, reason? }> | Requests permission (if needed), registers the SW, subscribes, and registers with JourneyLayer. |
unsubscribe() | Promise<{ ok }> | Unsubscribes locally and revokes server-side. |
isSupported() | boolean | false on browsers without Push/Notification APIs. |
Soft prompt
A soft prompt is an optional pre-permission message ("Get notified about…")
shown before the native dialog, so a "no" doesn't permanently block you. Design
it under Settings → Channels → Web push → Soft Prompt (title, message,
allow/later text, delay). Show it yourself, then call subscribe() when the
visitor clicks Allow.
Browser support (V1)
| Browser | Status |
|---|---|
| Chrome / Edge / Brave / Opera | ✅ Supported |
| Firefox | ✅ Supported |
| Safari (macOS 16+) | ✅ Supported. iOS requires the site be installed as a PWA (Add to Home Screen). |
| KaiOS | ⛔ Not supported in V1 |
Troubleshooting
subscribe()returnsnot_configured— generate VAPID keys and enable at least one browser in Settings → Channels → Web push.permission_denied— the visitor blocked notifications; they must re-allow in browser site settings. You can't re-prompt programmatically.sw_register_failed—jl-sw.jsisn't reachable at the configured path on your origin (must be same-origin, served over HTTPS). Openhttps://yoursite.com/jl-sw.jsto confirm it loads.- Nothing arrives after a test send — confirm the subscription exists (profile shows Web Push Subscribed), the browser tab can be closed but the OS must allow notifications, and check the browser isn't in a focus/Do-Not-Disturb mode.
- 403 on subscribe — your page origin isn't in Allowed domains.