An Introduction to the Web Notifications API

The time of the 56kb connections has faded out of memory for a lot of people (mobile users not withstanding). It was a time when browsers that could open a single page where enough, and no one could even predict a future with multi-tabbed browsing. Today, we’re overwhelmed by social networks, posts, replies, comments, photos, videos, and much more. Several systems have been created to overcome the need to look at every single tab to check for new activities. One of these methods are notifications, which are very widespread on different websites.

Until not too long ago, every developer had to implement notifications on their own, resulting in a whole set of different solutions. The W3C has defined an API to solve this problem in a standard way called the Web Notifications API.

On mobile devices we’re very familiar with the concept of notifications. Try to be offline for a couple of hours and, as soon as you connect to the Internet, you’ll be overwhelmed by notifications from the different apps installed on your device. It’d be great to have the same mechanism for our web pages that work seamlessly on desktop and mobile devices. As stated in the introduction, such system has been developed and standardized, so today we have the Web Notifications API.

Notification Hell
Image shamelessly stolen from the presentation of Brad Frost, Death to Bullshit

What is the Web Notifications API

The Web Notifications API is defined as an API for end-user notifications. A notification allows alerting the user outside the context of a web page of an occurrence, such as the delivery of email. The specifications don’t describe how and where a UA should display these notifications. Therefore, we’ll see different styles on different browsers and, based on the device we’re using, we’ll see the notifications in different places (for example on mobile we may see them in the notifications bar). It’s worth noting that before you can show a notification, the browser shows an alert to the the user, who must explicitly give his/her consensus.

An example of a notification using the Web Notifications API on Firefox
An example of a notification using the Web Notifications API on Firefox

This API has been around for a while, to the point that the specifications have changed several times. The specification has known two major versions. The first version was implemented in older versions of Chrome and Firefox. Now, the specification seem stable, although as of April, 19th 2014 it’s still a W3C Working Draft.

Thinking of some use cases for such an API isn’t very hard. For example, you may want to receive a notification as soon as you receive an email. You may also want to be notified if someone mentions you in a Tweet, or posts a photo of you on Facebook or Google+.

Now that we know what this API is, and what it’s good for, let’s delve into the description of its methods, properties, and events.

Methods, Properties, and Events

The Web Notifications API is exposed through the Notification property of the window object. This is a constructor that allows us to create a notification instance. It accepts two parameters – a string containing the title of the notification, and an optional object of settings. Before we see how we can create an instance, let’s look at the settings we can specify:

  • body: A string used to further specify the purpose of the notification.
  • lang: Specifies the language of the notification. Its value must be compliant with the BCP 47 standard. Examples of valid strings are en-US and it-IT.
  • dir: Defines the direction of the message’s text. Its value can be auto meaning that the direction is based on the browser’s settings, ltr to specify a left-to-right direction (for European languages), or rtl to specify a right-to-left direction (for some Asian languages).
  • tag: A string that is used as an ID that can be employed to retrieve, replace, or remove the notification.
  • icon: Specifies the URL of an image that will be used as the notification’s icon.

To create an instance of a Notification object, we should write a statement like the following:

var notification = new Notification('Email received', {
  body: 'You have a total of 3 unread emails'
});

Pretty easy, isn’t it?

It turns out that the settings we’ve just learned are also available as read-only properties of a notification instance. In addition, the Notification object exposes a property called permission. permission contains a string representing the current permission to display notifications. Its value can be one of the followings: denied, which means that the user has denied notifications, granted, which means the user has given permission, or default, which means the user choice is unknown.

This API exposes two methods: requestPermission() and close(). As the names suggest, the former is used to request the permission to show notifications to the user, while the latter programmatically closes a notification. requestPermission() is a method of the Notification object and accepts an optional callback that is executed when the user accepts or denies permission. The choice is passed to the callback as a parameter, and the value can be granted, denied, or default.
close() is an instance method and doesn’t accept any parameters.

Sometimes we may need to perform an action as soon as the status of the notification changes. For example, we may want to know if the user has clicked the notification, or when it is closed. To do that, we can attach a handler to one of the four events exposed:

  • onclick: Fired when the user clicks on the notification.
  • onclose: Fired as soon as the user or the brower closes the notification.
  • onerror: Fired if an error occurs with the notification.
  • onshow: Fired when the notification is shown.

A basic example of using these events is shown below.

var notification = new Notification('Email received', {
  body: 'You have a total of 3 unread emails'
});

notification.onshow = function() {
  console.log('Notification shown');
};

Browser Compatibility

Support for the Web Notifications API isn’t very good on both desktop and mobile. On desktop, Chrome and Firefox implemented the first version of this API a while ago. However, considering only the new version of the API, implementation starts from Chrome 22 and Firefox 22 (both without a vendor prefix). Safari 6+ also supports the Web Notifications API. On the mobile side of things, only Firefox and Blackberry have full support. Testing if a browser supports this API is a matter of writing a check like the one shown below.

if ('Notification' in window) {
  // API supported
} else {
  // API not supported
}

Demo

In this section I’ll show you a simple demo that allows you to so see this API in action. The demo is made of two parts. In the first part, there is a form that lets you write some text which will be used in the displayed notification. In the second part, a button allows you to quickly see what this API does using predefined parameters that I’ve included in the demo. Both these requests will trigger the request for permission to the user. Once permission is given, the notification will appear on the screen in case of a desktop, and in the notification bar in the case of a mobile device.

In the scripting part of the demo, the first thing we do is test the browser to see if it supports the Web Notifications API. If the API isn’t supported, we display the message “API not supported”, and disable the two buttons that trigger the notifications. If the browser implements this API, we attach a listener to the click event of the buttons. As you can see from the code, the handler is the same and the different title and message shown is changed according to the element that has triggered the event:

if (event.target.id === 'button-wn-show-preset') {
  // Uses the preset parameters
} else {
  // Uses the custom parameters
}

In addition to displaying the notification, we attach a handler to each of the four events exposed by the notification instance. This handler will do nothing but log, in a specific textform element, the event fired and the button that fired it.

A live demo of the code below is available here.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    <title>Web Notifications API Demo</title>
    <style>
      *
      {
        -webkit-box-sizing: border-box;
        -moz-box-sizing: border-box;
        box-sizing: border-box;
      }

      body
      {
        max-width: 500px;
        margin: 2em auto;
        padding: 0 0.5em;
        font-size: 20px;
      }

      h1
      {
        text-align: center;
      }

      .hidden
      {
        display: none;
      }

      #custom-notification
      {
        margin-top: 1em;
      }

      label
      {
        display: block;
      }

      input[name="title"],
      textarea
      {
        width: 100%;
      }

      input[name="title"]
      {
        height: 2em;
      }

      textarea
      {
        height: 5em;
      }

      .buttons-wrapper
      {
        text-align: center;
      }

      .button-demo
      {
        padding: 0.5em;
        margin: 1em;
      }

      #log
      {
        height: 200px;
        width: 100%;
        overflow-y: scroll;
        border: 1px solid #333333;
        line-height: 1.3em;
      }

      .author
      {
        display: block;
        margin-top: 1em;
      }
    </style>
  </head>
  <body>
    <h1>Web Notifications API</h1>
    <span id="wn-unsupported" class="hidden">API not supported</span>

    <form id="custom-notification" action="">
      <label for="title">Title:</label>
      <input type="text" id="title" name="title" />

      <label for="body">Body:</label>
      <textarea id="body" name="body"></textarea>

      <div class="buttons-wrapper">
        <button id="button-wn-show-preset" class="button-demo">Show Preset Notification</button>
        <input type="submit" id="button-wn-show-custom" class="button-demo" value="Show Custom Notification" />
      </div>
    </form>

    <h3>Log</h3>
    <div id="log"></div>
    <button id="clear-log" class="button-demo">Clear log</button>

    <script>
      if (!('Notification' in window)) {
        document.getElementById('wn-unsupported').classList.remove('hidden');
        document.getElementById('button-wn-show-preset').setAttribute('disabled', 'disabled');
        document.getElementById('button-wn-show-custom').setAttribute('disabled', 'disabled');
      } else {
        var log = document.getElementById('log');
        var notificationEvents = ['onclick', 'onshow', 'onerror', 'onclose'];

        function notifyUser(event) {
          var title;
          var options;

          event.preventDefault();

          if (event.target.id === 'button-wn-show-preset') {
            title = 'Email received';
            options = {
              body: 'You have a total of 3 unread emails',
              tag: 'preset',
              icon: 'http://www.audero.it/favicon.ico'
            };
          } else {
            title = document.getElementById('title').value;
            options = {
              body: document.getElementById('body').value,
              tag: 'custom'
            };
          }

          Notification.requestPermission(function() {
            var notification = new Notification(title, options);

            notificationEvents.forEach(function(eventName) {
              notification[eventName] = function(event) {
                log.innerHTML = 'Event "' + event.type + '" triggered for notification "' + notification.tag + '"<br />' + log.innerHTML;
              };
            });
          });
        }

        document.getElementById('button-wn-show-preset').addEventListener('click', notifyUser);
        document.getElementById('button-wn-show-custom').addEventListener('click', notifyUser);
        document.getElementById('clear-log').addEventListener('click', function() {
          log.innerHTML = '';
        });
      }
    </script>
  </body>
</html>

Conclusion

In this article we’ve discussed the Web Notifications API and the use cases for it. We’ve also described the methods, properties, and the events exposed by the API. As we’ve seen, using this API is pretty easy, so it should not be hard for you to employ it in your next project.

Unfortunately, its support among browsers is not so good, but because Chrome, Firefox, and Safari implemented it, on average we should be able to cover a good portion of our users. To reinforce the concepts don’t forget to play with the provided demo and, possibly to try to change the code.

Win an Annual Membership to Learnable,

SitePoint's Learning Platform

  • http://www.7eyetechnologies.com Kristina Roy

    Hi Aurelio De Rosa,
    You really shared good post about API notifications. You shared some critical points about design that were difficult to discuss. It helped me to increase knowledge about API. Your all tips are really nice and helpful to everyone. Thanks to share such useful post.

    • Aurelio De Rosa

      Hi Kristina.

      Thank you for the compliments. I’m glad you liked the article and find it useful to understand this API. Keep reading to discover even more APIs. Oh, just in case you missed some articles of mine, you can take a look at http://www.sitepoint.com/10-html5-apis-worth-looking/

  • Alex Hall

    Nice introduction to Notifications Aurelio. One thing with your demo… is it the expected behaviour that clicking the notification and triggering the click event stops subsequent notifications from showing? This is the behaviour I’m experiencing in Chrome 34. In fact, now when I return to the demo they don’t show at all!

    • Aurelio De Rosa

      Hi Alex.
      Your question is really interesting. The specifications don’t define a behavior for that, but the reason is that the `tag` property is the same and *not empty*. In fact, if you set an empty tag, the notification will be shown again as if it was a new notification each time.

      Said that, this behavior is relative to Chrome only as Firefox acts in the same way either with a set tag or an empty tag.

    • Aurelio De Rosa

      Hi Alex.

      I delve a bit more and found that this is a Chrome-specific issue ( http://lists.w3.org/Archives/Public/public-web-notification/2014Apr/0001.html ).

      • Alex

        After playing around with a JS-Bin demo, I found you can avoid the issue in Chrome 34 by issuing a close() on the notification when it has been clicked. The notification is closed by the user’s click anyway, and calling close() on the notification makes future notifications show as normal.

        In other words,

        notification.addEventListener(‘click’, function() {
        // do other stuff
        this.close();
        });

        should fix it.

  • Djalma Ribeiro

    Massa d+!

  • Aurelio De Rosa

    Hi Ulli. If you’re developing a Hybrid app with PhoneGap, you still need to use its APIs or a plugin. You won’t be able to use the Web Notifications API anyway. You can only use it for a web application for one or more specific browsers.

  • Noitidart

    The issue is you can’t control how long the notification stays. I would
    like for it to stay till dismissed. And multiple notifications seem to
    overlap…. Which is horrible, using FF29

    • Aurelio De Rosa

      Hello.

      You can actually control the time using the `close()` method to close them programmatically. Besides, they don’t overlap, they are just overwritten showing only the last one (assuming they use the same tag).

      • Noitidart

        Ah cool I didn’t know that. So you can keep it open indefinitely? Can you please show me example of that. The overwriting of last one is no good still, I would hope it would show all, unless a param like “overwriteLast” is specified to true.

  • Roman

    This may be a good technology… for a website that can force people to use a range of specific browsers and versions.

    • Aurelio De Rosa

      Hi.
      While currently only few browsers support this API, in the next few months all major browsers will do. So, this is really something that you can start using in production right now.

      • Roman

        Only their then recent versions, but lots of people still use old versions and will for a long time.

        • Aurelio De Rosa

          How people can use older versions of Firefox or Chrome if they (the browsers) autoupdate?

          • Roman

            “How” isn’t as important as the fact that they do. Also, there’s IE, Safari, and Opera, in addition Firefox and Chrome. Why don’t you ask somebody to show you their traffic data so that you’d connect with reality :)

          • Aurelio De Rosa

            Well, the sentence “How isn’t as important as the fact that they do.” suggests me that you’ve no idea of how this may be possible. The only way you can be stuck with an older version with Firefox and Chrome (with IE it’d be so easy) is that you have unplugged your WIFI or the Ethernet cable. But if this is true, there is also no need to talk about this API.

            Said that, with this API supported by Firefox, Chrome, and Safari you have a good 67% of support (based on the last month data http://www.sitepoint.com/browser-trends-april-2014-signs-stability/ ). This means 2 out of 3 of your users *already* can take advantage of this API.

            Finally, implementing this API you’re making a step forward, not backward. What this means is that you’ve only to wait few months (weeks?) and the coverage of your users will grow (and for free). Today we’re still supporting users with IE8 that has a mere 8%, so there is really no point to avoid the use of such technologies (with a smart fallback).

          • Roman

            Dude, why don’t you get yourself a website and look at analytics data? You are using “don’t ruin my theory with your facts” approach.

          • acmeira

            No, he’s not.

          • Roman

            I manage several websites, and traffic stats show that plenty of people use old versions (of pretty much ALL browsers). So, yes, he is.

  • Giuseppe

    Fantastic…thanks

  • Aurelio De Rosa

    And I imagine you’ve statistics that prove that a lot of users disable updates, don’t you?

    • M S

      “The only way you can be stuck with an older version with Firefox and
      Chrome (with IE it’d be so easy) is that you have unplugged your WIFI or
      the Ethernet cable.”

      And when someone points out that this is CLEARLY factually wrong, you ask for “statistics”?

      • Aurelio De Rosa

        Sure. Talking about something without any data seems to me very useless. If someone wants to be a professional of the web should make decisions based on data, not on feelings or his own opinion. This discussion seems to be the old question “Do you plan for people who disable JavaScript?” This was so silly that Firefox has even disabled the possibility to turn off JavaScript. Data have proved that (almost) nobody have JavaScript in mind. (However you should still develop with progressive enhancement in mind)

        So, if you all are all concerned about the 0.0001 (or so) that voluntarily disable the Firefox autoupdate I assume you’re all still developing websites with IE6 or even IE5 in mind, aren’t you?

        • M S

          Are you seriously not grasping that people are calling you out on making a false claim?
          Auto update CAN be turned off, period.

          The percentage of people actually using the function has ZERO effect on its existens.

          If you want to be professional, you need to be capable of recognizing when you made a mistake, and own it.

        • Lasse Rafn

          Sadly, I sometimes have 1-3% users without Javascript and up to 5-6% using IE7 and lower (??). And 5~10% using outdated browsers (of Chrome, Firefox and Safari mainly) – its’ differs a lot monthly but it’s sad to see.

          I started building websites for people with and without javascript, for down to IE6 sometimes, and for very early versions of major browsers.. Damn I once tested in Netscape (only a few years back).. But at some point, you just have to realise that you should not allow people to use the web, if they limit the developers. If someone disables Javascript, well then you’re going to have a hard time using my service, that you obviously wanted since you’re browsing my site.. Ohh, no notification support? Well, you’ll have to return to the site for updates.

          You can’t limit the developer, AND expect full functionality. Stop developing and designing for the people that will only limit you, focus on the people who let you impress them. Spending HOURS trying to build for IE7-8 and non-javascript devices is NOT worth it. And especially not IE6 and such.. damn, even Facebook has a box above the site saying people should upgrade..

          Last note; if you feel the need to design for old IE browsers and non-javascript users.. who are you targeting then? I’ve never seen young people or adults use VERY outdated browsers and not use javascript.. But I’ve seen old people do so.. and trying to make a business online, with that target, is not a good idea in the first place.. if people use IE6 and has no javascript, how would you sell your service in the first place, the person is obviously afraid of anything on the scary internet.

  • KingIsulgard

    Hi there, this is a great tutorial and works fine when the user is on the site. This might be a stupid question but is it also possible to display notifications when the user is NOT browsing your site? Maybe let them subscribe to pull for new possible notifications every x minutes?

    • Aurelio De Rosa

      Hi.

      On mobile you have push notifications, on desktop you have emails I guess.

  • prashant jain

    Hi,
    This API is not working in chrome(mobile). It is working fine in firefox(desktop) and chrome (desktop).