 Push notifications aren't something that are new. They've been around on native platforms for pretty much ever. But they're new on the web. And it's a powerful feature that we think is going to be really useful, but we need to be responsible about how we're going to use it. So I'm going to talk about some of the ways that I'm going to ask you to be responsible with using it and some of the ways that we're going to be responsible in using it. Jumia is a big company in Africa. They're kind of like the leading e-commerce company there. And they were seeing a lot of people come to their site, go shop on mobile, and then they would abandon their cart. And so their way to try and get people to complete their purchase was to send them an email. Well, one, getting them to actually give them their email address didn't work so well. And two, if they did, nobody was opening the emails. So they decided that they were going to try using web push notifications. So they added web push notifications recently. They're seeing a 38% open rate on their web push notifications. So think about that compared to email. It's right there. People are seeing it. Oh, hey, you abandoned your cart. There's something in here. Do you want it? Well, OK, so that's good. But they're seeing a nine times higher conversion from people who are getting web push notifications. So it's working phenomenally well for them. There are lots of other companies who are doing it, but that's just one. So let's take a look at what makes a notification engaging. What's useful? Users want to have notifications, and there is a point to the seal. I'll get to it in a sec. Users want to have notifications that are timely, that are relevant. They want things where they can say, hey, look. OK, I'm going to look at this and not necessarily have to open the app, but make a decision and do something without having to open it, and that are day-altering. So for these penguins getting a notification that their mortal enemy who's going to try and eat them is nearby, kind of helpful. This is a day-altering thing. So as you start to build notifications, ask yourself one big question. Is it important enough to warrant an interruption? Is this something that you want to get at your desk when you're at the office, maybe you're at home with family, having dinner, or out with friends? Is it important enough to warrant an interruption? And if it's not, think about ways that you can give users options to be able to say, well, I want these ones, but not these ones. So I think there are three key things that make a good notification. So let's take a look at those. The first one is it's timely. I feel like I need it right now. I want to look at it. I want to go, OK, yes, this is a notification that I'm going to do something with. Think like calendar notification. Hey, I should probably be on stage. That'd be a great calendar notification. Thankfully, I got that one. Synchronous communication. So I've got a chat going on, hello, hello. That is a perfect use for somebody sitting there waiting for that notification or that response for you. Don't send them things that they're not going to reply to, or that will fix themselves. So, oh, hey, I'm backing up your files. Who cares? Users don't care about that kind of thing. So keep it timely. The next one is be precise. Notifications aren't emails. You can only fit so much text and one image in a notification. Give them information that they can look at, figure out how they want to use it, and act on it, all right? The next one is it's relevant. Tell them who it's from, what it is specifically that they should care about in this particular thing. If it's a chat notification, tell them, hey, you got a chat notice from this person and here's what it says. And the other little bit on this one is if it's already on screen, don't show a notification for it. Like imagine a chat app again. We seem to have a lot of those. It's easy to keep going back to those examples. If the user's already in the chat app, they don't need to see, oh, they just got a message because they probably already saw the message. And there's one special one for web. And this one doesn't really apply for native applications because you're probably already working offline, but for web apps, make sure that whatever you're sending to the user is going to work whether they're online or offline. I live in New York City. So sometimes I have a cell signal in the subway or in the station and sometimes I don't, but I definitely don't have it in the tunnels. So if I look and I get a notification and I click on it just as I go into a tunnel and lose it, that's a useless notification to me. I'm going to throw it away. I'm going to get cranky at you and I'm not going to be a happy user. So let's try a few notifications and see how they work. Flight UA 875 is delayed. New departure time, 735. This one's good. It's timely because I'm probably sitting there waiting for a flight. And I want to know that my flight is there. It's precise because it's telling me what I need to know. It tells me the new flight time. It tells me who it's from. And it tells me where I'm going in terms of the flight number and all that kind of stuff. So this is a good one. I like this one. Credit card. Your credit card has been compromised. Yet not so good, right? Like, I get a new credit card probably every couple of months because somehow my credit card's been compromised. So this one, yeah, it's timely, but it's not precise. I don't know what credit card number or what credit card it is. I don't know if maybe just a whole bunch of credit card numbers were stolen or somebody's cloned it. I don't know what's going on. Well, and it's relevant because it is telling me it's my credit card. But with a few small changes, we can make this one useful. So did you make a $1 million purchase at Dr. Evil Inc with Visa 1234? It's relevant. I know which card it is. It's timely. And it tells me what's going on. And I've also added these action buttons to be able to say, yes, this was me, or nope, this wasn't me. I'm nice. I'm sweet. I'm innocent. I didn't do that. So Google+, Jane just posted a new message. Yeah. I'm not a big Google+, user, so I probably don't care about this all that much. But it's not timely because it's just a message. It's not like it's just something going up. There's no action that I'm going to take on this. Yeah, OK, it tells me who it's from. But what am I going to do with this? There are ways, and Google+, does have some really good, relevant, timely, precise notifications, but this isn't one of them. Awesome chat app. You have a new message. Yeah, no. So it's timely because, yes, it's synchronous communication. It's something somebody's sitting there waiting for it. But it's not precise. I don't know what the message is. And I don't know who it's from. It could be some spam bot. It could be my mom. Could be anybody else. I don't know. If it's my mom, I'm probably going to look at it, depending on my mood. Maybe it's a co-worker, and I need to reply to this. So with a little change, Jake says, I heart service workers. Probably something he'd actually say. So yes, now, tells me who it's from. It tells me what he's saying. I can then choose to reply to this or not. Ignore it however I want. All right, Goober, your self-driving car has arrived at 1, 2, 3, any street. I like this one. It's timely because my car has arrived. I'm going to be going somewhere, so it's good on time. It's precise. It tells me what it is that's arrived, and where it's arrived, and it's relevant. Yep, I asked for a car, so good. So this is a good one. Super cool, thanks for installing me. How many people have seen apps like this or notifications like this? Yeah, love these, don't you? You're going to have lots of ways, and already have lots of ways, hopefully, to monetize your users. Don't use notifications as a way to monetize your users, or just be like, hey, I'm still here. Please come visit me. Not going to make your users happy. They're going to say, go away, and they're probably not going to do it as politely as I just did. So question, new imaginary social network? Mary has just answered your question. This one's pretty good. It could be a little bit better. It's timely because I've got the information that I know somebody's answered my question. It's precise. It tells me who and what's happened with it. Now it could be a little bit more precise if I got the answer, if I knew what the answer was. But it's a notification. Maybe I asked a long question, and Mary gave me a long answer. So I want to balance those kinds of things. So clicking that would take me directly to the question. All right, so now that we know what makes a good notification, let's take a look at how it works. I'm going to give you the high level overview to start, and then we'll dive into the actual code and get really fun and technical. Notifications are built on service workers. So all the stuff that you're used to with service workers today, if you've started playing with them, you're going to need to use that technology. So that means your site needs to work on HTTPS, and you need to set up that service worker on the page and register handlers for it. And then what happens is your page says, hey, or your application, so your server, which is that example.com, sends a notification to an endpoint, and we'll dive a little bit deeper into endpoints later, sends that to the browser, the browser gets it, gives it to the service worker, and the service worker shows the notification. So let's walk through the flow of how a user gets subscribed. So the first thing we want to do is check to see if the user already has a subscription, if they're already subscribed to notifications so that we can update any UI on our page, because we want to be able to give users a way to say, yes, I want these, or no, I don't want these. So we want to check to see if they're subscribed. If they aren't subscribed, we're going to ask them to subscribe. They'll subscribe. Yay, awesome. And we're going to get a subscription ID. And this is sort of like the address that we're going to use to send the notification to the user, and then we send that up to our server, and we save that in our server. So that way we can get to that user later. We know how to address them. For sending a message on our server, we say, all right, great. I want to send a message to this user. And so you go and generate the message, and you send it up to the endpoint, and the endpoint goes, OK, great. I just got this message for this user. There it is. I'll send it over there. But I want to talk about endpoints for one sec. Endpoints are pretty cool in that right now there are essentially only two of them. We'll start to see more as other browsers support notifications. But right now there's one for Firefox, and there's one for Chrome. And what they do is they act sort of as a clearinghouse for all of the message that goes through. So that way your web app doesn't have to sit there and listen to your app, and your app, and your app, and your app. By keeping it through all one central channel, it means that we can keep the user's browser from killing their battery. You don't have to have service workers resident in memory the whole time. The browser just handles all of that stuff. And most of the platforms have good notification delivery services already. The one for Chrome on Android is built on FCM, or GCM. FCM, I guess it is. So it means that you can get those things very easily done with low power consumption. So then in the browser, when the notification comes in, the message comes in. We go, oh, great. OK, browser's got it. And the browser spins up the service worker. It says, ah, OK, this message goes to that service worker. And it spins up that service worker. The service worker handles the message and shows the notification. So that's the flow. Let's do it. There's a little bit of setup that we need to do for the endpoints. For Chrome, unfortunately, right now, Chrome doesn't support the web push protocol. It's coming. So there's a little bit of extra work that we have to do for Chrome today. This will go away probably in the next three to six months. I'm going for three months probably, but I'll give myself a little buffer space. And this will continue to work after that. But the web push protocol just means you have one thing to do. So you need to go in to the Cloud Console, create yourself a new project, and enable Firebase Cloud Messaging. It may still be labeled as Google Cloud Messaging. And then you need to get the project ID. And you need to get an API key. And just write those down, put them around for later. Then we need to go into the manifest and add the project ID to the GCM sender ID at the bottom. Again, this is only for Chrome, only for the next little while. But this tells Chrome, when it gets a message, who that message should go to. Which service worker should get that message? So you just need to add that one little bit. Set up Firefox. Yep, awesome, done. So Firefox uses the web push protocol already. So there's nothing special that you need to do. And one of the cool things about the web push protocol is that you can talk to any other endpoint without ever having used it before. So when Opera spins up theirs, you won't have to go and set any project up or anything like that. You can just go communicate to it right away. If Microsoft sets it up, if Safari sets it up, if they're using the web push protocol, you don't have to do anything. You just have to do a little bit of create a signature that says, hey, this is who I am. So if there's any problem, you know how to get a hold of me later. All right. I hope if I hit the right button. OK, so let's talk about how we subscribe users and unsubscribe users. So checking for subscriptions. This is something that we want to always do. We're doing progressive web apps. So we want to do this progressively. Check to see if service workers are actually supported. If they are supported, we go and get the registration. And in the registration, we call the push manager API. And push manager API, we say get the subscription to see if the user had subscribed or not. If the user subscribed, we'll get something back in that subscription. If the user hasn't, that'll be no. And we can use that information to set some browser UI so that we can say, oh, yeah, you're already subscribed. Thanks, yay. Or you're not subscribed, then please subscribe. Then to actually do the subscription, we're going to say, OK, service worker registration, get subscription, and get that registration. And again, we grab the push manager and subscribe. And we need to say user visible only. True. What that does is that says, all right, hey, if we're going to send a notification, we must show something. That is to prevent people from sending tons and tons of notifications that is going to wake up that service worker and keep the service worker alive the whole time, draining people's batteries, and make sure that you're doing something useful with each notification. So when the user then hits yes, I want to subscribe, we get back the subscription object. This subscription object is a object that we can do unsubscribe on. It's got some information about how to contact the user. We need to take that and send that up to our server. Because again, that's the address to go talk to the user. But if the user does deny the permission or the user's like, no, I don't want notifications from you, we just want to make sure we handle that gracefully. The subscription object is when you jsonify it, this is what it looks like. And there's a couple of things that I'll point out specifically in here. The first little bit is the first bit of the URL. So that tells you when you send a notification to the endpoint where that goes. So in this particular case, I did this in Chrome, so this is going to send to android.google.apis.gcmsend. The second bit is my unique ID. If you think about it as sort of like an email address, the first bit is the domain, the second bit is my name, or whatever the case is. And then the second bit here is keys. These are the user's public keys. If you're going to send any kind of data in your message, it has to be encrypted. And the reason for that is we want to make sure that from your server to the end user, no matter who the endpoint is, they can't see it. So if you send something up to a Chrome user, Google has no idea what that message is. There's no way we can see it. Firefox can't see it. Whoever else is running those endpoints, there's no way for them to be able to see it. So messages must be encrypted when you're sending them back and forth, or when you're sending them out to the user. So when do we prompt users? Generally, we don't want to do it on page load, right? Like the page loads, and all of a sudden you get a, hey, do you want to subscribe? This site wants to send you notifications. That feels spammy. That feels annoying. I don't know what kind of notifications you're going to send me. I'm going to tell you to insert not appropriate stage words here, right? So we want to make sure that users understand what's going on. If, for whatever reason, you decide that doing it on page load is the right approach for you, JalanTikus has done it, and they've done it well. What they do is on the page load, they dim down the page, they put a dialogue, and they tell the user what kind of notifications they're going to send, and they give them the choice there. So they're pre-prompting the user. They've done this well. If you're going to do it on page load, this is the way to do it. Don't actually just straight up prompt and be like, hey, subscribe, because they're going to hit no. The Weather Channel has done probably, I think, the best job of all the places that I've seen. So the Weather Channel has a specific page for signing up for notifications, and they do it in a specific contextual and user-initiated way. They've tied the subscription or signing up for notifications to what users want. So they have a place where it says, hey, activate browser notifications. They tell the user what kinds of notifications they're going to get. And so when the user goes and says, hey, yes, I want these notifications, and they ask for the subscription object, and that permission dialogue pops up, you already know that the user's going to say yes to that. If the user sees that without any contextual information, they don't know what kind of notifications you're going to send or why you're even sending notifications, they're going to hit block. Now, if they hit block, the only way to be unblocked is for them to go into their browser settings and change their browser settings and unblock you. How many people think they could get their family and friends to go into their browser settings and unblock something? Not going to happen. So we want to be really careful that we don't accidentally get our users to go block our sites. So we don't want to surprise them. Ask them first, then do the dialogue, the permission prompt. And the other thing about weather.com, they give users lots of options. I can say, hey, I want breaking news or government-issued alerts. They've got all sorts of other things. And I can choose the ones that I want. So I'm not getting every single thing that they send out, which is probably going to get a little bit annoying. So how do we unsubscribe a user? If the user says, nope, I don't want this anymore, rather than them going and finding a way to hit block. Because with every notification that pops up, there is an opportunity for them to hit the dialogue and be like, block, I don't want this anymore. We need to make it easy for them to unblock. So again, we've seen some of this code before. Service worker registration, get registration, get subscriptions, get the subscription again. And then we just call subscription.udzm. I'll try that one again. We call subscription.unsubscribe. And that unsubscribes the user. So that does it on the browser side. But the thing that we have to now do is go update our server. Because we have to tell our server, don't bother sending to this user anymore. Because if we try and send it to an endpoint and the user's unsubscribed, we're going to get essentially, nope, don't know that address. Sorry, go away, and it's just going to fail. So we just want to make sure that we're not sending annoying messages to the endpoint. We've got some sample code up on our GitHub repository that walk you through a lot of this process of how to sign the user up, some good practices there. It's a good place to start. It's not something that you necessarily want to use in production code, but it's a great place to start. So when we want to send a message, we want to get a message out. All right, remember that JSONified endpoint subscription thing? Keep this in mind, because we're going to need this. There's the endpoint and the keys. There are two different types of messages that we can send. One's called a tickle that has no data and the other one is payload with data. Tickles aren't really all that useful, but you might want them if you don't have a lot of stuff that you're ever going to send. Most likely, you'll be sending with data. So we need to encrypt those messages. So we take the keys that we got in the subscription. Those are the user's public keys. We take our payload. We do some AES-128 encryption on it, sign it with our keys, and we suddenly get an encrypted message. Now, I could probably spend the next 20 minutes plus the next talk walking you through how to do the encryption. And it's not fun, and I wouldn't recommend that you do that yourself. So we have another block of some sample code that you can use. Firefox has one as well. I'd actually recommend you use Firefox one, because the Firefox one supports both GCM or FCM right now, and it supports the web push protocol. And they've said that they're going to keep maintaining it as a library as opposed to ours just being some sample code. So check those guys out. Use that. It's probably a little bit easier to go. So to send a message via Firebase Cloud Messenger messaging, they change the name late in the game as after I started rehearsing, makes it all that much more fun to make sure you're saying the right thing. We do a post message. Both the Firebase Cloud Messaging and web push protocol use a REST API. So for that, we're just going to do a post to the URL that we got earlier. We're not going to use that extra sort of string bit. That's one of the key differences here. We use an authorization key. That's the API key that we got from the Cloud Console. We then have to include our public encryption keys and the salt that we use to encrypt the message. So we're doing public private key encryption. And then the message that we want to send. So you don't have to include the time to live, but the time to live is useful. That says I want this message to be delivered within the next 120 seconds. If it's not delivered in 120 seconds, abandon it. So imagine my phone is in the back turned off right now. So I wouldn't get that message because it would exceed the 120. So that's just how long the endpoint should try to deliver the message to your device, then the registration ID, and the raw data. The web push protocol is pretty much the same. Instead of doing a post request, we do a put request. And we use the whole endpoint. So we put the whole endpoint up in there. And instead of putting the time to live inside the data, we put the time to live as a header. We then have to say, hey, our content type is an octet stream because our content is actually binary data encoded. And we give it the encoding type so that we know, hey, this is all good. And then we need to include our public keys, just like we did before. Here's the message. Great. All right. And finally, we need to include the authorization bearer. We're using a protocol called Vapid. And Vapid, I really wanted to have some fun photo, but I couldn't find anything that worked and would be somewhat appropriate. But Vapid essentially says, hey, I am a server that is sending to you endpoint. And I am a real person. If I'm sending bad messages, here's how you can get a hold of me later. And so it just is a way of signing these messages to be like, yes, I'm not trying to cause a denial of service attack or give you bad stuff. And then finally, the last little bit is the encrypted payload. So we stick that on the end. All right, so when we handle the message coming in, we need to add an event listener to our service worker. So in the service worker, we want an event handler that listens for a push. And we're going to wrap everything in a wait until. The wait until, some people get a little bit, and even I got a little confused with it several times on why I'm using it and what's going on, and especially all the wonderful brackets. Wait until tells the service worker that you want it to keep working, stay alive, until the promise that's inside it returns. And you must have shown a notification at that point. Now, the reason that you want to do that is, say, for example, in your notification, you get some data that's come in. And you need to save that in an index DB database. Or you need to save that somewhere. Maybe you need to go and do a fetch request. Well, you don't want the service worker to shut you down because the service worker is like, well, I think you're done. You don't need to work anymore before you've shown the notification or before you've saved what you need to do. Wait until tells the service worker you need to stay alive, stay alive until I'm done with you. So then, self.registration show notification. And that says to the notification, all right, hey, I want to show a title and a body and a message and a tag. Well, that's not exactly the most exciting notification in the world, right? And it kind of goes against everything we talked about earlier in terms of notifications because it's pretty boring. Like, it doesn't tell me anything I need to know. So what about that payload stuff? Like, how do we get that? Well, what we do is say event.data. And if there's data in the payload, that gives us the data. And we can say .json or whatever to turn it into some kind of format that we want to handle. If there's no data, there are still some things we can do. And we only got data in Chrome 50, I think it was. So you might need to do some other things. In that case, you could use a fetch and go get something back from the server, right? In fact, in terms of data size, you can only have about 4k. Just, I think it's just a couple of bytes over 4k. So if you're actually trying to send something more meaningful down, right, and you want to make sure that the page works offline or you've got a new email and that kind of thing, it might be more than 4k. So in that case, you might use fetch here to go get that stuff. And then once you've done that, you can then call the notification and say notification.title, body, icon, and tag. The tag is there. What the tag does is that allows you to group similar messages so that if you've got three messages that come in with the same tag, only one message with that particular tag will show. So that way, you can group messages together. You don't have multiple things. Or you could have three messages if they have different tags. One of the other things that you can do is make it easy for the user to complete a task without actually having to open your app by adding action buttons. So action buttons you can think of is like, hey, I want to like this or retweet this or I want to confirm or cancel reservations. Maybe for, I wrote their name down because I keep forgetting it, Jalen Tickus, who has the shopping cart thing. Hey, do you want to just finish your shopping cart? Yes. Take it straight there. No, I want to abandon it and just throw it out. Or maybe it's, yeah, save it for later. I don't have time to check out now. So giving users an ability to be able to do additional things in their notifications. So to add a notification or add an action, we just need to add this actions attribute to our notification. And we need to supply a couple of things, the action. And this is just for us internally. So we know what the user clicked, a title so that you get something that's going on, and then an icon. So what image that you want. For any time both on here or on the icons that you're using within your notifications, I strongly recommend that you cache those with your service worker. That way they're always going to show up, right? Like if the user goes and clicks on, gets a notification just as they're going into that subway tunnel or whatever place where they have no network connection, you want to make sure that they're not seeing a notification that they don't know what it is. So having that title there is really important. All right, so the user just clicked on like, or they clicked on yes, or they clicked on something. How do we know what they clicked on? Well, we need an event listener in our service worker that listens for notification click. And the notification click says, all right, hey, you clicked on this, great. And in the event, we can look at the dot action. And that's going to tell us whether they clicked on an action or it'll be blank if they didn't click on anything. So if they clicked or if they clicked on the main part of the notification, if they clicked on that, it'll get that. So, you know, they clicked on like. In that case, event dot wait until, again, because we want to keep the service worker alive while we go do our thing. And I just did this one as a fetch. And I was like, all right, hey, go like this notification. Maybe they clicked on the main thing and you just want to open a web page. So then you can say, client dot open window and open the web page that they're using. So you get nice way of getting them into your app. All right, it would be nice if we can get notifications to dismiss across all devices. How much fun do you have when you come home and you look at your tablet or a phone or something else and there's dozens of other notifications showing? You can do that with the notification close event. So by listening for the notification close event, you can say, OK, great. All right, when that happens, I'm going to go get the data out of my notification and do a fetch and close that. In this particular case, one way you can do it is by when you send your notification down, you add an ID attribute to each notification so that you know what the user clicked. And when they closed it, you're good to go. All right, I blew through that. I talked a little fast. I hope not too bad. So you can build really great engagement with users by using push notifications. It's not terribly hard to do if you start building things with a service worker. If you've used a service worker before, you don't have to go all crazy and make everything work offline and do the whole progressive web app piece. You can add push notifications to any website today. As long as you're using HTTPS, you can get notifications added. As you build out your notifications, make sure that your notifications are precise, that they're timely, and they're relevant. Do that. Do I want to be disturbed by that? Don't tell your bosses about notifications that you think you're going to not want so that they get great ideas. We want to make sure that we keep good control over them. Keep them really solid and helpful to users. Ask permission and context. So don't do it on page load. Don't go and just do it completely randomly. Make sure the user understands what they're doing so that you ask them first and then do the permission dialogue so that they know why that notification dialogue that says, this site wants to send you notifications is showing up. We don't want to lose them if they block things. And finally, the last one, I always like to close this. Be awesome. Build stuff that's fantastic. Build stuff that's really great that you're going to like, that your users are going to like, and we're all going to like. So with that, there's a few things here that you can use. There's the web push notification getting started guide. This getting started guide. And there's a code lab that does this same thing, I believe, in the code labs area. So if you want to go try writing some web push notifications in a code lab, you can do that today. If you're really kind of curious about how the encryption stuff works, we do have a post up about that. If you just go, some of these links are kind of long. But if you go to developersgoogle.com slash web slash updates and just look for the data, it explains all the stuff you need to do. It's not terribly complex, but I'm just always afraid that if I screw one thing up, I'm going to like leak everything and security scares me because I just don't want to be that guy. And then finally, the last one is the vapid spec. That explains how to go set up the authorization key so that when you send your message to a web push protocol server, that message gets through. The browser is all good. So with that, I will say, thank you very much. I hope you've all had a wonderful I.O. Thank you.