An install button should appear only when the browser decides the Web App is eligible to be installed. That signal is the beforeinstallprompt event, which fires once the app satisfies the installability criteria. Capturing the event gives you control over timing: instead of letting the browser prompt at an arbitrary moment, you hold onto the event and trigger installation when it suits the user.
Capture the event first
Until the event arrives, there is nothing to prompt with and no reason to show an install button. So the first step is to attach a handler that stores the event and reveals the button that was previously hidden.
Roughly four edits are involved:
- Click Remix to Edit to make the project editable.
- Add a
beforeinstallpromptevent handler to thewindowobject. - Save the
eventas a global variable; we'll need it later to show the prompt. - Unhide the install button.
Code:
window.addEventListener('beforeinstallprompt', (event) => {
// Prevent the mini-infobar from appearing on mobile.
event.preventDefault();
console.log('๐', 'beforeinstallprompt', event);
// Stash the event so it can be triggered later.
window.deferredPrompt = event;
// Remove the 'hidden' class from the install button container.
divInstall.classList.toggle('hidden', false);
});
Trigger the prompt from a user gesture
Showing the prompt itself means calling prompt() on the saved beforeinstallprompt event. The call has to happen inside a user gesture, which is why it belongs in the install button's click handler rather than in the handler that captured the event.
- Add a click event handler for the install button.
- Call
prompt()on the savedbeforeinstallpromptevent. - Log the results of the prompt.
- Set the saved
beforeinstallpromptevent to null. - Hide the install button.
Code:
butInstall.addEventListener('click', async () => {
console.log('๐', 'butInstall-clicked');
const promptEvent = window.deferredPrompt;
if (!promptEvent) {
// The deferred prompt isn't available.
return;
}
// Show the install prompt.
promptEvent.prompt();
// Log the result
const result = await promptEvent.userChoice;
console.log('๐', 'userChoice', result);
// Reset the deferred prompt variable, since
// prompt() can only be called once.
window.deferredPrompt = null;
// Hide the install button.
divInstall.classList.toggle('hidden', true);
});
Account for every install path
Your button is not the only route to installation. Users can also install through Chrome's menu, the mini-infobar, or an icon in the omnibox. The appinstalled event on the window object covers all of them, so it's the right place to record an install regardless of how it started.
- Add an
appinstalledevent handler to thewindowobject. - Log the install event to analytics or other mechanism.
Code:
window.addEventListener('appinstalled', (event) => {
console.log('๐', 'appinstalled', event);
// Clear the deferredPrompt so it can be garbage collected
window.deferredPrompt = null;
});
Where to go next
Your app is now installable. Two related behaviors are worth adding afterwards:



