Maxim Salnikov
@webmaxru
Push Notifications
My App
Maxim Salnikov

-
PWA Slack organizer
-
PWA Oslo / PWA London meetups organizer
-
PWA speaker and trainer
-
Google Dev Expert in Web Technologies

Azure Developer Technical Lead at Microsoft

Why is this important?
For user:
timely updates from websites you use
For publisher:
effectively re-engage users with customized, relevant content
Current support

Involved parties & flow

Feature detection
if (!('serviceWorker' in navigator)) {
// Service Worker isn't supported on this browser
// Disable or hide UI.
return;
}
if (!('PushManager' in window)) {
// Push isn't supported on this browser
// Disable or hide UI.
return;
}
Requesting permission
Notification.requestPermission().then(function(result) {
if (result === 'denied') {
console.log('Permission wasn\'t granted');
return;
}
if (result === 'default') {
console.log('The permission request was dismissed');
return;
}
// Do something with the granted permission
// result === 'granted' in this case
});

UX patterns
-
Ask to subscribe at a time when the benefit is obvious
-
Antipattern: to show the permission dialog to users as soon as they land on your site
-
Consider how a user should unsubscribe or opt out of push messaging.



Allow users to unsubscribe.
Otherwise they'll block!
Subscribing
navigator.serviceWorker.register('/service-worker.js')
.then(function(registration) {
const subscribeOptions = {
userVisibleOnly: true,
applicationServerKey: 'key...'
};
return registration.pushManager.subscribe(subscribeOptions);
})
.then(function(pushSubscription) {
console.log(JSON.stringify(pushSubscription));
return pushSubscription;
});
{
"endpoint": "https://particular-push-service.com/long-unique-id/",
"keys": {
"p256dh": "BNcRdreALRFXTkOOUHK1EtK2wtaz5Ry4YfYCA=",
"auth": "tBHItJI5svbpez7KI4CCXg=="
}
}
Push event
self.addEventListener('push', function(event) {
notification = event.data.json()
event.waitUntil(
self.registration.showNotification(
notification.title, notification.options
)
)
})

Notification UX

const title = 'Something Has Happened'
const options = {
message: 'Something you might want to check out',
icon: '/assets/images/logo.png'
}
self.registration.showNotification(title, options)
MyAirline
Online check in is available
MyAirline
myairline.com


Flight
DY1043
Depart
21.09 13:45
OSL -> LAX
Click here to check in now
myairline.com
-
Do not Repeat Yourself
-
Provide actual information instead of notifying about it
-
Give a call to action
Notification actions
self.addEventListener('notificationclose', function(event) {
const dismissedNotification = event.notification
event.waitUntil( triggerAnalytics( dismissedNotification ) )
})
self.addEventListener('notificationclick', function(event) {
const clickedNotification = event.notification
clickedNotification.close()
event.waitUntil( performAction( clickedNotification ) );
});
-
Open a window
-
Focus an existing window
-
Message a page from a push event
Thank you!
Maxim Salnikov
@webmaxru
Questions?
Maxim Salnikov
@webmaxru
PWA: Push Notifications
By Maxim Salnikov
PWA: Push Notifications
- 4,595