patternjavascriptModerate
PWA install prompt — BeforeInstallPromptEvent and deferring the browser prompt
Viewed 0 times
Chrome 44+, Edge 76+
install promptbeforeinstallpromptPWA install buttonadd to home screendeferredPrompt
browser
Problem
Developers show the native browser install banner immediately on page load, which is disruptive and has low conversion. Alternatively, they miss the event entirely because it fires before they are ready to respond to it.
Solution
Capture the BeforeInstallPromptEvent and trigger it only from a user-initiated UI element.
let deferredPrompt;
window.addEventListener('beforeinstallprompt', (e) => {
// Prevent the default browser mini-infobar
e.preventDefault();
deferredPrompt = e;
// Show your custom install button
document.getElementById('install-btn').hidden = false;
});
document.getElementById('install-btn').addEventListener('click', async () => {
if (!deferredPrompt) return;
deferredPrompt.prompt();
const { outcome } = await deferredPrompt.userChoice;
console.log('Install outcome:', outcome); // 'accepted' | 'dismissed'
deferredPrompt = null;
document.getElementById('install-btn').hidden = true;
});
// Detect if app is already installed
window.addEventListener('appinstalled', () => {
console.log('PWA installed');
deferredPrompt = null;
});
let deferredPrompt;
window.addEventListener('beforeinstallprompt', (e) => {
// Prevent the default browser mini-infobar
e.preventDefault();
deferredPrompt = e;
// Show your custom install button
document.getElementById('install-btn').hidden = false;
});
document.getElementById('install-btn').addEventListener('click', async () => {
if (!deferredPrompt) return;
deferredPrompt.prompt();
const { outcome } = await deferredPrompt.userChoice;
console.log('Install outcome:', outcome); // 'accepted' | 'dismissed'
deferredPrompt = null;
document.getElementById('install-btn').hidden = true;
});
// Detect if app is already installed
window.addEventListener('appinstalled', () => {
console.log('PWA installed');
deferredPrompt = null;
});
Why
The install prompt is a one-shot event per session. If you call e.preventDefault() and then discard the event, the user cannot install until the next page load. Deferring gives you control over when and how to surface the install CTA.
Gotchas
- beforeinstallprompt only fires on Chrome and Edge — Safari uses Add to Home Screen from the share sheet (no JS API)
- prompt() can only be called once per captured event — create a new install button flow after dismissal by waiting for the next beforeinstallprompt
- The event does not fire if the app is already installed (check via window.matchMedia('(display-mode: standalone)'))
- iOS Safari does not support BeforeInstallPromptEvent — display manual instructions for iOS users separately
Context
Building a custom install flow for a Progressive Web App
Revisions (0)
No revisions yet.