Webpushmeldingen: hoe ze werken en hoe je ze goed gebruikt
Hoe webpushmeldingen werken, van service workers en VAPID tot echte browserondersteuning inclusief iOS, plus de toestemmings-UX en cijfers die het resultaat bepalen.
Webpushmeldingen zijn het enige marketingkanaal waarin één slechte ontwerpbeslissing je permanent buiten de deur van een klant kan zetten. Vraag op het verkeerde moment om toestemming, de bezoeker klikt op Blokkeren, en die browser is voorgoed gesloten voor je. Geen tweede verzoek, geen tweede campagne, geen winback-e-mail. Door die asymmetrie loont het om het mechanisme te begrijpen voordat je één bericht schrijft.
Wat webpushmeldingen zijn
Een webpushmelding is een bericht dat je server naar de browser van een abonnee stuurt, wordt getoond door het meldingencentrum van het besturingssysteem, en ook wordt afgeleverd als je site gesloten is. Dat laatste is de hele reden van bestaan: anders dan een pop-up op de pagina bereikt web push iemand die op dit moment niet naar je website kijkt.
Het is gebouwd uit drie webplatform-API’s die samenwerken, en de verdeling daartussen verklaart het meeste gedrag van het kanaal: de Service Worker API, de Push API en de Notifications API.
Hoe web push onder de motorkap werkt
De service worker
Een service worker is een JavaScript-worker die als proxy fungeert tussen je webapp, de browser en het netwerk. Hij draait op zijn eigen thread, heeft geen toegang tot de DOM en blijft bestaan nadat de pagina die hem registreerde is gesloten. Die duurzaamheid maakt het mogelijk om een pushbericht te ontvangen en een melding te tonen terwijl niemand je tabblad open heeft. Service workers draaien alleen in beveiligde contexten, dus via HTTPS, waarbij http://localhost voor ontwikkeling als beveiligd geldt.
Het abonnement: een endpoint plus twee sleutels
Zodra een service worker actief is, roept de pagina registration.pushManager.subscribe() aan. De browser praat met de pushservice van zijn leverancier en geeft een PushSubscription terug met daarin:
endpoint, een unieke capability-URL waarop de pushservice berichten aanneemtkeys.p256dh, een publieke Elliptic Curve Diffie-Hellman-sleutel op de P-256-curvekeys.auth, een authenticatiegeheim
Je server slaat alle drie op en behandelt het endpoint als een geheim, want iedereen die het heeft kan naar die abonnee versturen. De sleutels bestaan omdat payloads end-to-end versleuteld zijn. RFC 8291 legt vast hoe: een ECDH-uitwisseling op P-256 vestigt een gedeeld geheim, HKDF leidt daar sleutels uit af, en de payload wordt verzegeld met AES-128-GCM onder de content-encoding aes128gcm. De pushservice geeft cijfertekst door die hij zelf niet kan lezen.
De pushservice
Je stuurt pushberichten niet rechtstreeks naar een apparaat. Je stuurt ze naar een pushservice die door de browserleverancier wordt gedraaid: de FCM-endpoints van Google voor Chrome, autopush van Mozilla voor Firefox, de pushservice van Apple voor Safari. RFC 8030, “Generic Event Delivery Using HTTP Push”, definieert het protocol. Je server doet een POST naar het abonnementsendpoint, en de pushservice regelt de lastige kanten van mobiele bezorging: één batterijvriendelijke verbinding met het apparaat, wachtrijen tijdens offline zijn, en de browser wekken zodra er een bericht binnenkomt. Dit is ook de reden dat bezorging niet gegarandeerd kan worden. Staat het apparaat lang genoeg uit, dan verlopen berichten volgens hun TTL en worden ze weggegooid.
VAPID: aantonen wie er verstuurt
Dat het endpoint geheim is, is dunne beveiliging. RFC 8292 voegt Voluntary Application Server Identification toe, oftewel VAPID, zodat een pushservice kan zien van welke applicatieserver een bericht afkomstig is.
Je genereert eenmalig een ECDSA-sleutelpaar op de NIST P-256-curve. De publieke sleutel gaat in applicationServerKey wanneer de browser zich abonneert, waarmee het abonnement aan jouw server wordt gebonden. Bij elke push stuurt je server een JWT die met de bijbehorende privésleutel is ondertekend via ES256, met een aud-claim voor het domein van de pushservice, een exp-claim van maximaal 24 uur vooruit en optioneel een sub-claim met contactgegevens. De pushservice controleert de handtekening, waardoor een gestolen endpoint alleen niet langer genoeg is om je abonnees te spammen.
Het bezorgpad, van begin tot eind
- De pagina registreert een service worker en roept, nadat toestemming is verleend,
subscribe()aan met je publieke VAPID-sleutel. - Je server slaat het teruggegeven endpoint en de sleutels op bij het abonneerecord.
- Om te versturen versleutelt je server de payload met
p256dhenauth, ondertekent een VAPID-JWT en doet een POST naar het endpoint. - De pushservice authenticeert het verzoek en levert het versleutelde bericht af.
- De browser wekt de service worker met een
push-event, dat de payload ontsleutelt enServiceWorkerRegistration.showNotification()aanroept. - Een klik vuurt
notificationclickaf in de service worker, waar je de bestemmings-URL opent.
Waarom het toestemmingsmodel zo streng is
Kijk naar wat een abonnement toekent: een achtergrondproces dat draait zonder dat je site open staat, plus het recht om te tekenen op het meldingsoppervlak van het besturingssysteem. Browsers zetten daar dan ook een expliciete toestemming per domein voor, verleend door de gebruiker, en de meeste eisen dat het verzoek volgt op een echte handeling van die gebruiker.
Een tweede beperking verrast mensen. Chrome en Edge vereisen userVisibleOnly: true bij het abonneren, een belofte dat elke push een voor de gebruiker zichtbare melding oplevert, dus stille pushberichten op de achtergrond zijn geen ondersteund gebruik van de API. Firefox hanteert daarnaast een quotum voor pushberichten die geen melding opleveren.
Browser- en platformondersteuning
Volgens MDN is de Push API sinds maart 2023 breed beschikbaar als Baseline, wat betekent dat het werkt in actuele versies van Chrome, Edge, Firefox en Safari op desktop, en in Chrome en Firefox voor Android. Twee kanttekeningen wegen zwaarder dan die kop.
Ten eerste is de Notifications API niet overal beschikbaar. MDN markeert hem als beperkt beschikbaar, omdat de constructor Notification() op de meeste mobiele browsers een TypeError opwerpt. Gebruik voor alles wat op telefoons moet werken persistente meldingen via ServiceWorkerRegistration.showNotification(), en dat is toch al het service worker-pad waar je op zit.
Ten tweede zijn meldingsopties ongelijk geïmplementeerd. Actieknoppen, badges, afbeeldingen en requireInteraction verschillen per browser en besturingssysteem, dus ontwerp meldingen die ook met alleen een titel, een tekst en een pictogram nog goed leesbaar zijn.
De eis voor iOS en iPadOS
Deze kanttekening bepaalt of web push haalbaar is voor een doelgroep die vooral mobiel is, en bijna overal wordt hij verkeerd weergegeven.
Apple voegde Web Push toe in iOS en iPadOS 16.4, en het werkt alleen voor webapps die aan het beginscherm zijn toegevoegd. In de woorden van WebKit: “we voegen ondersteuning voor Web Push toe aan webapps op het beginscherm”, en “een webapp die aan het beginscherm is toegevoegd, kan toestemming vragen om pushmeldingen te ontvangen”. De gebruiker voegt hem toe via het deelmenu en “Zet op beginscherm”, en toestemming moet daarna worden gevraagd als reactie op een directe handeling, zoals het tikken op een aanmeldknop.
Een site die in een gewoon Safari-tabblad op de iPhone openstaat, kan geen pushabonnement aanmaken. Dat is een echte drempel: je vraagt om een installatiestap voordat je überhaupt om toestemming kunt vragen. Op macOS gaat het makkelijker, want Safari 16.1 op macOS Ventura bracht op standaarden gebaseerde Web Push voor gewone websites zonder installatiestap.
Een minimaal abonnementsvoorbeeld
Dit is de volledige flow aan clientzijde. Hij hoort in een klikhandler thuis, niet bij het laden van de pagina.
async function subscribeToPush(vapidPublicKey) { // Push en service workers vereisen een beveiligde context (HTTPS). if (!("serviceWorker" in navigator) || !("PushManager" in window)) return null;
const registration = await navigator.serviceWorker.register("/sw.js");
// Moet vanuit een gebruikershandeling worden aangeroepen, en maar één keer per gebruiker. const permission = await Notification.requestPermission(); if (permission !== "granted") return null;
const subscription = await registration.pushManager.subscribe({ userVisibleOnly: true, applicationServerKey: vapidPublicKey, // base64url-gecodeerde P-256 publieke sleutel });
// Bewaar endpoint + sleutels op de server; behandel het endpoint als een geheim. await fetch("/api/push/subscribe", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(subscription), });
return subscription;}Binnen sw.js handel je het push-event af, roep je self.registration.showNotification(title, options) aan, en handel je notificationclick af om de bestemmings-URL te openen.
Toestemmings-UX: waar de meeste programma’s stranden
Vraag het nooit bij het laden van de pagina
Lighthouse heeft daar een eigen audit voor: “als je pagina bij het laden om toestemming vraagt om meldingen te sturen, zijn die meldingen mogelijk niet relevant voor je gebruikers of hun behoeften”. De aanbeveling is om een specifiek type melding aan te bieden en pas om toestemming te vragen nadat de gebruiker zich voor dat type heeft aangemeld. Safari 12.1 en andere browsers gingen verder en eisen interactie met de pagina voordat er überhaupt een verzoek gedaan mag worden.
Gebruik een zachte voorvraag
Toon eerst je eigen uitnodiging op de pagina. Die benoemt de waarde, kan zonder blijvende schade worden weggeklikt, en alleen een klik erop activeert het echte browservenster. Iemand die je zachte voorvraag vandaag negeert, kun je volgende maand opnieuw vragen. Iemand die op Blokkeren klikt niet. Twee regels maken het werkbaar: beschrijf wat je echt gaat sturen in plaats van “ontvang updates”, en lok nooit een klik per ongeluk uit, want een per ongeluk gegeven toestemming leidt meteen tot afmelden.
Vraag het in context
De aanbeveling van Chrome zelf is om “je gebruikers het initiatief te laten nemen en meldingen in hun eigen tempo aan te laten zetten” door schakelaars discreet in bestaande interfaceonderdelen te plaatsen, en om te vermijden dat je “vensters en/of overlays toont zonder context of meteen nadat een gebruiker op de site landt”.
De momenten die in commerce werken zijn heel specifiek: een knop “waarschuw mij zodra dit weer op voorraad is” bij een uitverkocht product, een bestelbevestigingspagina die bezorgupdates aanbiedt, een prijsalertschakelaar bij een veelbekeken product. De toestemming wordt geruild tegen een benoemd voordeel in plaats van geoogst.
Een weigering is in de praktijk permanent
Wanneer iemand meldingen blokkeert, bewaart de browser die beslissing voor jouw domein. Latere aanroepen van Notification.requestPermission() vallen terug op de opgeslagen waarde denied zonder iets te tonen, en daarom controleert het voorbeeld van MDN zelf Notification.permission voordat het ooit requestPermission() aanroept. Een blokkade terugdraaien betekent graven in de site-instellingen, en dat doet vrijwel niemand.
Wat browsers doen als je het fout doet
De gevolgen zijn allang niet meer alleen een laag opt-inpercentage.
- Chrome plaatst domeinen met een zeer laag acceptatiepercentage automatisch in een stillere toestemmings-UI, apart per apparaattype, waardoor het venster voor iedereen wordt onderdrukt.
- Chrome legt limieten op aan sites die veel pushvolume combineren met weinig betrokkenheid, en geeft dan HTTP 429 terug. De escalatie loopt van één dag naar zeven en daarna veertien, en wordt pas gereset na 42 opeenvolgende dagen zonder verstoring.
- Chrome trekt de meldingstoestemming nu automatisch in voor sites waarmee een gebruiker recent geen interactie heeft gehad, waar sprake is van “zeer lage gebruikersbetrokkenheid en een hoog volume verzonden meldingen”. De onderbouwing van Google is niet mis te verstaan: “Minder dan 1% van alle meldingen krijgt enige interactie van gebruikers.”
Je kunt abonnees die je al had verdiend kwijtraken door simpelweg slecht te versturen.
Web push vergeleken met e-mail en sms
| Factor | Web push | Sms | |
|---|---|---|---|
| Bereik | Alleen browsers die zich hebben aangemeld | Iedereen met het adres | Iedereen met het nummer |
| Marginale kosten | Praktisch nul | Zeer laag | Per bericht, het hoogst |
| Snelheid | Seconden, getoond door het besturingssysteem | Minuten tot dagen, begraven in een inbox | Seconden |
| Berichtlengte | Een titel en een korte tekst | Onbeperkt, rijke opmaak | Circa 160 tekens per segment |
| Toestemming | Browservenster, één klik | Adresverzameling, idealiter dubbele opt-in | Expliciet en zwaar gereguleerd |
| Identiteit | Een browser op één apparaat | Een persoon | Een persoon |
| Overdraagbaarheid | Geen | Volledige export | Volledige export |
Het verschil in eigendom dat de strategie verandert
Een pushabonnement is een capability-URL die aan één browserprofiel op één apparaat is gebonden. Het is geen persoon. Dezelfde klant die Chrome op een laptop en Firefox op een telefoon gebruikt, is twee losstaande abonnementen, en je kunt niet weten dat het om dezelfde mens gaat tenzij die zich bekendmaakt.
Het is ook niet overdraagbaar. Je kunt een e-maillijst exporteren en die morgen in een ander platform laden. Pushabonnementen kun je niet tussen leveranciers verplaatsen, omdat de sleutels en de VAPID-binding zijn aangemaakt tegen een specifieke applicatieserversleutel.
Behandel web push dus als versneller op een kanaal dat je zelf bezit, nooit als vervanging. Gebruik het pushmoment om een e-mailadres of een telefoonnummer te verdienen, niet andersom. De complete gids voor marketingautomatisering behandelt hoe je meerdere kanalen in één journey bedraadt.
Toepassingen die echt werken
Het kanaal beloont berichten die tijdgevoelig en persoonlijk relevant zijn en met één tik af te handelen.
- Verlaten winkelwagen. Een push binnen een uur, later versterkt door een e-mail. De gids voor e-mails bij een verlaten winkelwagen behandelt de volgorde.
- Weer-op-voorraadmeldingen. Het sterkste geval, omdat de gebruiker er expliciet om heeft gevraagd.
- Prijsdalingen op gevolgde artikelen. Dezelfde logica, zelfgekozen relevantie.
- Bezorg- en bestelstatus. Hoge openingsintentie, weinig kans op klachten.
- Belangrijk nieuws binnen een gevolgd onderwerp. Nieuws, uitslagen, beschikbaarheidsvensters.
Wat mislukt is net zo duidelijk: generieke uitzendingen in de trant van “we hebben een nieuw artikel gepubliceerd”, ongedifferentieerde dagaanbiedingen, alles wat meer nodig heeft dan een titel en één regel, heractivatiesalvo’s naar abonnees die de laatste twintig meldingen hebben genegeerd, en transactionele inhoud waarvan een duurzaam bewijs moet blijven bestaan.
Frequentie, timing en segmentatie
Begin voorzichtig: één tot drie meldingen per abonnee per week, en breid alleen uit als je afmeld- en klikpercentages standhouden. Vermoeidheid komt sneller opzetten dan bij e-mail, want dempen kost één tik op een melding die het besturingssysteem al had getoond.
Timing is tegelijk een voordeel en een risico. Push komt onmiddellijk aan, dus een bericht dat om 02:00 wordt verstuurd, komt om 02:00 binnen. Sla de tijdzone van een abonnee op of leid hem af bij het aanmelden, en houd verzendingen binnen een vastgelegd venster.
Segmentatie wordt begrensd door wat je weet over een abonnement in plaats van over een persoon, dus de werkbare dimensies zijn gedragsmatig: bekeken pagina’s, gevolgde producten, status van de winkelwagen, recentheid van aankopen, platform. De gids voor klantsegmentatie gaat er dieper op in.
Web push meten
Vier cijfers doen ertoe, en ze zijn niet allemaal op dezelfde manier meetbaar.
- Aflevering. Of de pushservice het verzoek heeft geaccepteerd. Een 201 betekent geaccepteerd, niet afgeleverd. Een 404 of 410 betekent dat het abonnement dood is.
- Weergave. Of de melding daadwerkelijk is getoond. Dat weet je alleen als de service worker terugmeldt zodra
showNotification()is afgerond. - Doorklikpercentage. Kliks gedeeld door weergaven. Dit is het getal dat het waard is om te optimaliseren.
- Afmeldpercentage. Afmeldingen en ingetrokken toestemmingen per verzending. Volg dit nauwlettender dan de CTR, want het is de voorlopende indicator voor de dood van het kanaal.
Valkuilen bij attributie
Pushattributie vleit zichzelf. De melding komt binnen op een apparaat dat de abonnee toch al vasthad, dus hij eist vaak de eer op voor een sessie die er sowieso was gekomen. Werk met holdoutgroepen in plaats van incrementaliteit aan te nemen. Weergaven worden ondergeteld terwijl elke klik wordt geregistreerd, dus een CTR die tegen verzendingen wordt berekend, overdrijft de prestatie. En omdat een abonnement een browser is en geen persoon, ziet een push die op een telefoon wordt aangeklikt en in een aankoop op de desktop eindigt eruit als twee losstaande gebeurtenissen. De gids voor e-mailmarketingcijfers behandelt meethygiëne over kanalen heen.
Toestemming, GDPR en afmelden
Het toestemmingsvenster van de browser is een technische drempel. Het is niet automatisch een volledige juridische grondslag voor marketing.
Richt je je op mensen in de EU of het Verenigd Koninkrijk, behandel push dan zoals je e-mail behandelt. Leg uit wat je gaat sturen voordat het venster verschijnt, zodat de toestemming geïnformeerd en specifiek is. Leg vast wanneer en waar het abonnement is aangemaakt, en koppel pushtoestemming nooit aan een handeling die er niets mee te maken heeft. Koppel je abonnementen aan geïdentificeerde klanten, dan vallen die gegevens onder je verplichtingen rond persoonsgegevens, inclusief verwijderverzoeken.
Hygiëne rond afmelden telt net zo zwaar. Bied een voorkeurenscherm op je site aan zodat mensen de frequentie kunnen verlagen in plaats van te blokkeren, roep PushSubscription.unsubscribe() aan en verwijder het record aan serverzijde zodra ze dat doen, en ruim abonnementen op bij een 404 of 410. De richtlijn van MDN is kort en juist: gebruikers moet “een eenvoudige manier worden geboden om zich af te melden voor meer in de toekomst”.
Waar web push past in een kanalenstack
Web push is een goed derde kanaal en een slecht eerste: snel, marginaal gratis en ongeëvenaard voor tijdkritische waarschuwingen, maar apparaatgebonden, niet exporteerbaar en één klik verwijderd van permanent verlies.
Daarmee wordt orkestratie het echte probleem. Welk bericht gaat naar welk kanaal, hoe onderdruk je de e-mail als de push al heeft geconverteerd, en hoe houd je één beeld van de klant over oppervlakken die mensen verschillend identificeren. Brevo biedt web- en mobiele push naast e-mail en sms, en Tajo zit boven op Brevo om die kanaaloverstijgende logica voor Shopify-winkels te coördineren. Voor de sms-kant, zie de gids voor sms-automatisering.
Belangrijkste punten
- Web push is een samenspel van drie API’s: een service worker voor uitvoering op de achtergrond, de Push API voor abonnement en transport, en de Notifications API voor weergave. Een abonnement is een endpoint plus een
p256dh-sleutel en eenauth-geheim, payloads zijn end-to-end versleuteld, en VAPID bewijst wie de verzender is. - Push is sinds maart 2023 breed beschikbaar als Baseline, maar op iOS en iPadOS werkt het alleen voor webapps die aan het beginscherm zijn toegevoegd.
- Vraag nooit om toestemming bij het laden van de pagina. Gebruik een zachte voorvraag, vraag het in context, en onthoud dat een blokkade permanent is voor dat domein.
- Chrome dwingt inmiddels stillere vensters, limieten en automatisch intrekken van toestemming af, dus slecht versturen kost je abonnees die je al had.
- Een abonnement is een browser, geen persoon, en is niet te exporteren. Bouw eerst de e-maillijst en gebruik push om die te versnellen.