9 amazing PWA secrets
Discover vital tips and tricks to get the most out of Progressive Web Apps.
About 8 min reading time
Progressive Web Apps (PWAs) are a new frontier in responsive web design, and they're growing in popularity. PWA support started with Chrome on Android, and is now available on most other Android browsers, such as Opera, Firefox, Samsung Internet and UCWeb, as well as iPhones and iPads from iOS 11.3 and Edge for Windows and Chrome on desktop operating systems.
To help you create a good user experience for this growing audience, we're going to share some vital tricks and ideas.
01. WebAPK vs Android shortcut #
In 2017, Chrome rolled out a new feature for Android users: WebAPK. Now, when your users install your PWA (if it meets the requirements), a Google Play server will create an APK (Android Package, a native app container) on the fly and install it in the device as if it's coming from the Play Store. Your user doesn't need to enable insecure sources or touch any other settings.
When the PWA is installed, it will appear in the home screen, in the app launcher, in Settings and as any other first-class citizen app in the OS, including information on battery and space used in the system.
If your PWA doesn't meet all the requirements, the Play service is down, there is a connection issue, or another Android browser such as Firefox or Samsung Internet is being used, a standard shortcut to the home screen will be created. That icon will be browser-branded from Android 8+.
WebAPK also enables a nice but dangerous feature you need to be aware of: the PWA will own the domain and path within the boundaries of the Android OS. Based on the scope attribute of your Web App Manifest, every link the user receives to that scope will be forwarded to your full-screen app and not the browser, which means you must pay attention to the URLs you use.
Let's say you have a PWA serving mobile users and it's on the root folder of your domain. When the app is installed through WebAPK, the whole domain will now be owned by the PWA. If you have a survey at /survey that you share through Facebook, or a PDF with terms and conditions that you email to your users at /terms.pdf, the OS will open PWA and not the browser when clicking those links. It's essential to check if your PWA routing system knows about those URLs and how to serve them and, if not, to open them in a browser on a different scope.
02. Create a custom web app installation banner #
We can't customise a browser's web app installation banner, but we can defer them after we show more information to the user
Several browsers invite the user to install your PWA if certain conditions are met, including recurrent visits from that user for your PWA. At the moment, the banner doesn't include enough information for why a user should accept. However, we can use events to avoid the banner and, more importantly, to defer it for something more likely to generate acceptance, such as an install icon.
The first step is to cancel the appearance of the banner and save the event object for later usage:
// global variable for the event object
var installPromptEvent;
window.addEventListener('beforeinstallprompt', function(event) {
event.preventDefault();
installPromptEvent = event;
});
The next step is to provide a user interface to explain the advantages of installing, or an Install button. That user interface will call our next function:
function callInstallPrompt() {
// We can't fire the dialog before preventing default browser dialog
if (installPromptEvent !== undefined) {
installPromptEvent.prompt();
}
}
03. Share content from your PWA #
On compatible browsers, the Web Share API will trigger the well-known share dialog from the operating system
When your PWA is in full-screen mode, there is no URL bar or Share action from the browser for the user to share content with social networks. We can take advantage of the Web Share API and have a fallback to open native social apps.
function share() {
var text = 'Add text to share with the URL';
if ('share' in navigator) {
navigator.share({
title: document.title,
text: text,
url: location.href,
})
} else {
// Here we use the WhatsApp API as fallback; remember to encode yourtext for URI
location.href = 'https://api.whatsapp.com/send?text=' +encodeURIComponent(text + ' - ') + location.href
}
}
04. Analytics tracking #
When you have a PWA, you will want to track as many events as possible, so let's take a look at everything we can currently measure. You can use Google Analytics APIs or any other analytic tools to track these events later.
window.addEventListener('appinstalled', function(event) {
// Track event: The app was installed (banner or manual installation)
});
window.addEventListener('beforeinstallprompt', function(event) {
// Track event: The web app banner has appeared
event.userChoice.then(function(result) {
if (result.outcome === 'accepted') {
// Track event: The web app banner was accepted
} else {
// Track event: The web app banner was dismissed
}
});
});
The next important tracking event is when the user opens the app from the home screen. That means the user has clicked the app's icon or, on Android with WebAPK support, also clicked on a link pointing to the PWA scope.
The simplest way to do this is through the manifest's start_url
attribute, adding a tracking event in the URL that can be automatically used as an origin from an Analytics script, such as:
start_url: '/?utm_source=standalone&utm_medium=pwa'
Also, the following script leaves us a boolean stating if the user is currently in a browser (true) or a standalone app mode (false):
var isPWAinBrowser = true;
// replace standalone with fullscreen or minimal-ui according to your manifest
if (matchMedia('(display-mode: standalone)').matches) {
// Android and iOS 11.3+
isPWAinBrowser = false;
} else if ('standalone' in navigator) {
// useful for iOS < 11.3
isPWAinBrowser = !navigator.standalone;
}
Then, if you use push notifications, you can track several events in the service worker, such as:
self.addEventListener('push', function(e) {
// Track event: Push Message Received
});
self.addEventListener('notificationclick', function(e) {
// Track event: Push Message Clicked, you can read e.action.id to track actions
});
self.addEventListener('notificationclose', function(e) {
// Track event: Push Message Dismissed
});
05. Create a compatible iOS PWA #
When doing PWAs on iOS, always make sure you check your status bar definition, which will create different status bar experiences
While many think PWA support is about to land for the first time on iOS 11.3, the truth is that the concept – albeit with a different name – was presented by Steve Jobs more than ten years ago at WWDC 07. That's why iOS supported home screen and offline apps for a while, using legacy techniques. But from iOS 11.3, it will start to support the same specs as Android.
If you still want to offer an installation experience before iOS 11.3, you need to add meta tags or use a polyfill this author created at https://github.com/firtman/iWAM
Now your PWA will be offline-capable and installable on iOS even if you don't opt-in for iOS. It's important to understand some differences that might affect your PWA user experience on iOS:
- Icons on iOS must be square and non-transparent to avoid UI problems. Don't use the same icon you have on Android. Use 120x120 and 180x180 for iPhones.
- If you have an SPA or you link to other pages on your scope, be careful with navigation, as iOS users don't have a way to go back or forward if you don't provide navigation links within your UI. Swipe gestures don't work on full-screen PWAs.
- As of the first versions of iOS 11.3, the OS reloads PWAs on every access to the app, so if the user needs to get out of the app to come back later (for example, for a two-way authentication process), remember your app will start from scratch by default.
06. Syncing data in the background #
Service workers have a separate life cycle from the PWA window or browser's tab. That's why you can make network operations in the background, even after the user closes the PWA. If there is a pending operation and there is no available network access at that point, the engine will let us process while in the background if a connection is detected later.
The Background Sync API is currently only available on some browsers, so you must provide a fallback. The idea is that your PWA will set a flag with a string tag, stating that it needs to do background sync operation.
navigator.serviceWorker.ready.then(function(reg) {
reg.sync.register('myTag')
});
Then, on the ServiceWorker we listen to the event, and if it's the label, we are expecting we return a promise. If the promise is fulfilled, then the operation is flagged as finished. If not it will keep trying later in the background.
self.addEventListener('sync', function(event) {
if (event.tag === 'myTag') {
event.waitUntil(doAsyncOperationForMyTag());
}
});
07. Social networks and pseudo-browsers #
If your users share your PWA content on social networks, or if they use pseudo-browsers (browsers without their own engine but using web views), you need to be aware of some issues.
For example, Facebook uses a WebView inside the Android and iOS apps to offer an in-app browsing experience when the users click on a link. On Android, most of the WebViews don't support service workers and can't install your PWA, so when the user opens your content from Facebook, your PWA will act as if it's a non-compatible browser without any cached files or session details.
From iOS 11.3 the WebView will support service workers, but it will be a clone of the same PWA that the user has used in Safari or even in other pseudo-browsers, such as Chrome or Firefox on iOS.
Therefore, if you are rendering an installation banner or installation hint dialog explaining the value of installing your app, check if you are within a WebView because the user won't be able to follow your steps. Hide that information or invite the user to open the URL in the default browser. This applies to Facebook on Android, Facebook on iOS, Chrome on iOS and Firefox on iOS, among other apps. Doing a live check if you are on a WebView or not is tricky, but there is a helper tool available.
08. Test on Android devices and emulators #
Testing service workers and Web App Manifest requires https, with the exception of localhost. While local desktop testing is fine initially, at one point we want to see our PWAs in action on Android devices. How can we do that? Accessing a dev server from our phone or Android emulator won't work because it's not https and it's not localhost from an Android OS point of view.
The solution appears with Chrome Developer Tools. If we go to chrome://inspect and open an emulator or a real device with USB debugging connected, we will be able to enable port forwarding. Then http://localhost on our Android device will be forwarded to our host computer's localhost or any other host. With this trick, Android will render the PWA properly over a non-secure connection. Have in mind, though, that while WebAPK will create the package and install it, it might not work in standalone mode.
09. Publishing to stores #
PWA Builder is a Microsoft online tool to create store-compatible PWA packages for Windows 10 and other operating systems
While the PWA approach didn't start with the stores in mind, some offerings, including Twitter Lite and Google Maps Go in the Play Store, started to serve PWAs on the stores. If this is something you are interested in, to distribute your PWA without packaging it with Cordova, your available options are:
- Microsoft Store: You can create a PWA for Windows 10 using the official tool from pwabuilder.com
- Google Play Store: At the time of writing, the Trusted Web Activities available on Canary Channel enable you to create an Android app that just opens a PWA you own and distributes it in the Store, creating a similar solution to WebAPK. You can learn more here.
- Apple App Store: Currently there are no official solutions to distributing PWAs, but WKWebView will support service workers from iOS 11.3, so it won't be difficult to create a simple wrapper for a PWA. The question is, will Apple approve it in the Store? Apple doesn't want solutions that are just websites with a wrapper on it.
This article was originally published in issue 304 of Net Magazine