Chrome Notifications for your Website

Today I had the opportunity to work on a small web based push notification event using GCM (Google Cloud Messaging) and wanted to share the experience and show how the service could benefit you.

Because this was new, the first thing that I did was look into how I could implement the push logic. I came across this which straight from Google Developers looked promising, so I got started.

The idea was, I had a CRON task set which pulled in information on a regular schedule. When this data was stored, I would call a sub routine which was a simple count of the data and rather than send an Email notification I would send a desktop notification. Pretty simple right?

So, first order of business was to create and register a service worker. This involved some quick Javascript in 2 files, firstly my main.js file:

if ('serviceWorker' in navigator) {
 console.log('Service Worker is supported');
 navigator.serviceWorker.register('sw.js').then(function(reg) {
   console.log(':^)', reg);
   // TODO
 }).catch(function(err) {
   console.log(':^(', err);
 });
}

To check that this is registered properly, a good place to look is the following url chrome://serviceworker-internals.

and secondly the sw.js file:

console.log('Started', self);
self.addEventListener('install', function(event) {
  self.skipWaiting();
  console.log('Installed', event);
});
self.addEventListener('activate', function(event) {
  console.log('Activated', event);
});
self.addEventListener('push', function(event) {
  console.log('Push message received', event);
  // TODO
});

Then I was directed to create an API Console project, I already had one ready but for those of you that don’t you want to head over to the API Console and make a new project. You will then want to enable Mobile APIs - Google Cloud Messaging and create a server key.

For the next step you would need to have the following:

Project ID: (From the Project Dashboard)
Server Key: (You've just made it)

Onto the next one, let’s make a manifest.json file in your public root and lay it out like so:

{
  "name": "The Name of your Project",
  "gcm_sender_id": "Project ID"
}

and make sure you link to your manifest.json file from your head:

<link rel="manifest" href="/manifest.json">

Awesome, hope you haven’t had any issues so far. Let’s get subscribed for push notifications by editing our main.js file. You can replace the code block that we added before with something like this:

if ('serviceWorker' in navigator) {
    console.log('Service Worker is supported');
    navigator.serviceWorker.register('sw.js').then(function(reg) {
        console.log(':^)', reg);
        reg.pushManager.subscribe({
            userVisibleOnly: true
        }).then(function(sub) {
            console.log('endpoint:', sub.endpoint);
        });
    }).catch(function(error) {
        console.log(':^(', error);
    });
}

and now if you refresh your page, you’ll notice a popup asking for you to allow or block notifications. Awesome!

But more importantly, if you have your console open (of course you do!) you should notice an output that looks like:

endpoint: 'https://android.googleapis.com/gcm/send/APA91bGdUldXgd4Eu9MD0qNmGd0K6fu0UvhhNGL9FipYzisrRWbc-qsXpKbxocgSXm7lQuaEOwsJcEWWadNYTyqN8OTMrvNA94shns_BfgFH14wmYw67KZGHsAg74sm1_H7MF2qoyRCwr6AsbTf5n7Cgp7ZqsBZwl8IXGovAuknubr5gaJWBnDc'

What you want to do is parse out everything from the last / as this is your customers subscription id.

For this, I used a quick bit of javascript that looked like this (not clean but quick and effective):

if ('serviceWorker' in navigator) {
    console.log('Service Worker is supported');
    navigator.serviceWorker.register('sw.js').then(function(reg) {
        console.log(':^)', reg);
        reg.pushManager.subscribe({
            userVisibleOnly: true
        }).then(function(sub) {
            var str = sub.endpoint;
            var n = str.lastIndexOf('/');
            var subscriptionId = str.substring(n + 1);
        });
    }).catch(function(error) {
        console.log(':^(', error);
    });
}

I could then make an AJAX call and store this subscription ID in my database and send the user push notifications.

I am sure you are thinking, but how do I make a push notification. Well it’s a really simple cURL request laid out like so:

curl --header "Authorization: key=XXXXXXXXXXXX" --header "Content-Type: application/json" https://android.googleapis.com/gcm/send -d "{\"registration_ids\":[\"fs...Tw:APA...SzXha\"]}"

Key should equal your Server Key which was created earlier. And registration_ids is an array of the subscription_ids gathered from your users in our previous step.

And that is it. Make the above cURL request and you should see a push notification popup pretty instantly!

Don’t forget to checkout the Google Developers guide here and most importantly.. Happy Coding!