Adding a custom Install button in Progressive Web Apps

Amit Merchant · June 9, 2021 ·

The other day, I was looking for a way to add a custom “Install” button in my Notepad app which is essentially a Progressive Web App (PWA).

Introduction

To give you a primer, when you open a PWA, a beforeinstallprompt event would get fired in supported browsers. When this event is fired, the browser would show an installation popup to the user like so.

Native PWA Popup

The user can then choose to install the app by hitting the “Install” button or dismiss the popup. So, what if you want to remind your users to install your PWA once again after they dismiss the installation popup?

To get around this, what you can do is show a custom “Install” button somewhere in your app itself which would trigger the user to install your PWA.

This is exactly what I did in my Notepad PWA as well. How did I achieve this? Read on to know how.

Tap into the beforeinstallprompt event

Remember I talked about the beforeinstallprompt event which triggers the installation popup? We need to add an event listener for this event in our app and save the event to use it later to trigger the native installation popup. You can do it like so.

let deferredPrompt;

window.addEventListener('beforeinstallprompt', (e) => {
    deferredPrompt = e;
});

As you can tell, we need to define a global variable called deferredPrompt and when the beforeinstallprompt event occurs, we can save the event to the deferredPrompt variable for later use.

Add an Install button in the PWA

Next, we can now add an install button somewhere in our app. In my Notepad app, I have put it into the “About” modal next to the app’s title like so.

You can choose to put it anywhere within your app. But make sure that it should be non-intrusive and not in the face of the user.

Hook into the button’s click event

Once done, we can add a “click” event listener on this button and use the deferredPrompt global variable to trigger browser’s native installation popup like so.

const installApp = document.getElementById('installApp');

installApp.addEventListener('click', async () => {
    if (deferredPrompt !== null) {
        deferredPrompt.prompt();
        const { outcome } = await deferredPrompt.userChoice;
        if (outcome === 'accepted') {
            deferredPrompt = null;
        }
    }
});

As you can see, we can trigger the native installation popup by using the deferredPrompt.prompt() and then we can wait (“await”) for the user selection in the form of deferredPrompt.userChoice.

This will return the user choice as outcome. If the user chooses to install the application, the outcome would be “accepted” and then we can set deferredPrompt to null so that it won’t trigger the install popup the next time user clicks on the button.

If the user dismisses the popup, the outcome would be “dismiss” in that case.

Take a look at the entire process in action.

Custom Install button in action

And that is how you can add a custom install button in your PWAs!

But there are a few more things that you can do to make this process more seamless.

Showing “Install” button only in supported browsers

Not every browser (such as Firefox, Safari, etc.) supports installing PWAs. So, it would be a better idea to show the “Install” button in supported browsers only.

To achieve this, what I did is by default I made the “Install” button hidden and for that, I did the following in the CSS.

.install-app-btn-container {
  display: none;
}

Now to show it in the supported browser, all I did is made it visible when the beforeinstallprompt event is fired like so.

window.addEventListener('beforeinstallprompt', (e) => {
    $('.install-app-btn-container').show();
    deferredPrompt = e;
});

Notice, I have used jQuery to make it visible but you can use whatever you want.

Using this approach, you are also not showing the “Install” button in the case if the app is already installed because in such a case, the beforeinstallprompt would not get fired.

So, you’re aiming at two targets using only one arrow here!

You can check out the source code of my Notepad app further if you want.

👋 Hi there! I'm Amit. I write articles about all things web development. If you like what I write and want me to continue doing the same, I would like you buy me some coffees. I'd highly appreciate that. Cheers!

Comments?