The Install Prompt
The install flow
Section titled “The install flow”When a browser decides your PWA is installable (valid manifest + registered service worker + HTTPS), it fires the beforeinstallprompt event on window. By default the browser would show its own install badge or prompt immediately — but you can intercept that event, hide the default UI, and show your own install button at the right moment.
Step 1 — stash the event
Section titled “Step 1 — stash the event”let deferredPrompt = null;
window.addEventListener('beforeinstallprompt', (event) => { // Prevent the browser from showing its mini-infobar event.preventDefault(); // Save the event so we can trigger it later deferredPrompt = event; // Show your own install button document.getElementById('install-btn').hidden = false;});Step 2 — trigger the prompt from a user gesture
Section titled “Step 2 — trigger the prompt from a user gesture”You must call deferredPrompt.prompt() from inside a user-initiated handler (a click). Calling it outside a user gesture will throw.
document.getElementById('install-btn').addEventListener('click', async () => { if (!deferredPrompt) return; // Show the browser's install dialog deferredPrompt.prompt(); // Wait for the user's choice const { outcome } = await deferredPrompt.userChoice; console.log('User choice:', outcome); // 'accepted' or 'dismissed' deferredPrompt = null; document.getElementById('install-btn').hidden = true;});Step 3 — react to a completed install
Section titled “Step 3 — react to a completed install”The appinstalled event fires after the user confirms the install:
window.addEventListener('appinstalled', () => { console.log('PWA installed successfully'); deferredPrompt = null;});iOS differences
Section titled “iOS differences”Safari on iOS does not fire beforeinstallprompt. There is no programmatic way to trigger the install dialog. Your only option is to show an instructional banner that guides the user manually:
- Tap the Share button in Safari.
- Scroll down and tap Add to Home Screen.
Detect iOS to show the right guidance:
const isIos = /iphone|ipad|ipod/i.test(navigator.userAgent);const isInStandaloneMode = window.matchMedia('(display-mode: standalone)').matches;
if (isIos && !isInStandaloneMode) { document.getElementById('ios-hint').hidden = false;}Try it live
Section titled “Try it live”The playground below wires up a complete install-button flow. Because StackBlitz runs inside an iframe, the beforeinstallprompt event will not fire — but you can inspect the full code and run it on a real domain to test.