Web Push Notifications – Part 3 – ServiceWorker Extras

In the recent posts about showcase coffeepush, we explored the main idea and then the technical implementation to enable the push feature.  After a while, we realized that ServiceWorkers can be used for many other cool features, too, and these features are often not hard to implement. So while we only needed a ServiceWorker initially to get access to the PushManager, we ended up also exploring offline web apps and web install banners.

Offline (or partially cached) Web Apps

As our web app is about submitting live orders to a barista, technically completely “offline” does not make sense. But what we’re interested in, is caching which will improve the experience for the customer. We decided to start caching all web app resources with the installation of the serviceworker and to only exclude the API calls to submit the order. These calls can luckily easily be identified by having a path that begins with “/api/”.

To begin caching the resources of the web page, you first have to react to the ServiceWorkers install event:

The call to evt.waitUntil() will not return before the precache() Promise has fulfilled. It opens a storage and begins caching the individual resources. This task could obviously be automated later on, for example by creating the list automatically.

When a page with such a ServiceWorker will be loaded the next time, the ServiceWorker will be able to react to “fetch” events whenever a resource is loaded. It’s here where we have to decide what we cache and what will still be forwarded to a live request.

If you simply “return” from the fetch event listener function, it means that request will try to be fulfilled in the normal way, by making a request to the URL. We always want to use live requests for all socket.io communication, certain images and all ‘/api/’ calls as our service requires this.

All other requests can be fulfilled from the cache:

There are many other ways to respond via a ServiceWorker’s cache – e.g. you can decide to go with a cached version in case the network takes too long. Or invalidate the cache and precache again after a certain amount of time. We’ve found this page over at Mozilla quite helpful.

Web Install Banners

Now that we have an active ServiceWorker on our page and we do partial caching, we figured that

we’re very close to another neat feature: Web Installl Banners. It means that the browser decides based on certain criteria if you may “install the web page” by adding a direct link on the homescreen. All that is required is a manifest file to get the basics going. We then also decid

ed to defer the display of this prompt as we found it to annoying right at the beginning of the order process.

The Manifest

The manifest file is a simple text-based file, linked from the HTML of your page. It informs the browser about the available icons, the orientation it’s intended for and the exact way to start your app later on if the icon is clicked by the user. As in our case we load the respective event information based on a path variable (event/<event>, e.g. event/someevent) will load the data for ‘someevent’ from a backend API) we had to serve the manifest in a dynamic way. So we added a route to our epxress based node.js backend:

The start_url attribute in the served JSON deserves special attention. The launcher query parameter that gets added allows us to detect in the page’s javascript if that page was already started by the launcher. Thus, we don’t want to show any new notifications to install the web page to the home screen any more.

Delayed Web Install Banners

Another goal of ours was to defer the asking for installation to a later point. We found it to obtrusive to ask right when the page loads. The user should first finish his order, which is of key importance, and then secondly be asked if he wants to install this web app. Therefore, we needed to prevent the default browser behavior.

Before a notification for installation is shown to the browser’s user, the beforeinstallprompt event will be sent out. Here, we prevent the default (to show a notification) and instead save the received event in the global scope via the variable installEvent. Next, we check if we got launched via the the homescreen menu by checking the query variables. If got loaded by normal means (by scanning a QR code, tapping an NFC tag or by direct entry of the URL), we show an install button and register a click listener to that button. This button is shown at the end of the ordering process only, thereby not nagging the user before.

Check out these recent posts about our web push and service workers showcase coffeepush: we explored the main idea and then the technical implementation to enable the push feature so far.

Leave a Reply

Your email address will not be published. Required fields are marked *