Customize PWA Installs with BeforeInstallPromptEvent
Progressive Web Apps (PWAs) provide native-like experiences on the
web, but default browser installation banners can feel intrusive or
appear before a user understands the app’s value. The
BeforeInstallPromptEvent interface gives developers
programmatic control over when and how the installation prompt is
displayed. By intercepting this event, JavaScript can suppress the
default browser banner, save the event reference, and trigger a tailored
installation flow through custom user interface elements at the most
effective moment.
How BeforeInstallPromptEvent Works
When a browser detects that a web application meets all PWA
criteria—such as having a valid Web App Manifest, a registered Service
Worker, and being served over HTTPS—it fires the
beforeinstallprompt event on the global window
object before showing its standard installation UI.
Developers can leverage this event in four distinct steps:
1. Intercepting the Default Prompt
By adding an event listener for beforeinstallprompt and
calling event.preventDefault(), you prevent the browser
from displaying its default mini-infobar or automated prompt to the
user.
let deferredPrompt;
window.addEventListener('beforeinstallprompt', (e) => {
// Prevent the default browser install banner
e.preventDefault();
// Stash the event so it can be triggered later
deferredPrompt = e;
// Update UI to notify the user they can install the PWA
showInstallPromotion();
});2. Displaying Custom In-App Promotion
Once the event is captured and stored, your application can reveal custom UI elements that fit natively into your design. Common patterns include an “Install App” button in the navigation bar, a banner within the settings menu, or a prompt after a user completes a meaningful action (such as placing an order or bookmarking an item).
3. Triggering the Browser Install Dialog
The saved BeforeInstallPromptEvent object contains a
.prompt() method. When the user interacts with your custom
install button, JavaScript invokes this method to finally show the
native confirmation dialog.
installButton.addEventListener('click', async () => {
if (!deferredPrompt) {
return;
}
// Show the native install prompt
deferredPrompt.prompt();
// Wait for the user to respond to the prompt
const { outcome } = await deferredPrompt.userChoice;
console.log(`User response to the install prompt: ${outcome}`);
// We've used the prompt, and can't use it again; throw it away
deferredPrompt = null;
hideInstallPromotion();
});4. Handling the User’s Choice
The userChoice property on the
BeforeInstallPromptEvent returns a Promise that resolves to
an object containing the user’s decision (accepted or
dismissed). This allows the application to track conversion
metrics, hide promotional components, or provide contextual onboarding
immediately following acceptance.
Key Considerations and Limitations
- Single Use: A
BeforeInstallPromptEventinstance can only be called once via.prompt(). Once executed, the variable must be cleared, and the app must wait for another event if the user rejects it. - User Engagement Requirement: Calling
prompt()must occur inside a user-gesture handler, such as aclickevent listener, to prevent unauthorized pop-ups. - Browser Compatibility: The
BeforeInstallPromptEventis supported primarily on Chromium-based browsers, including Google Chrome, Microsoft Edge, and Samsung Internet on Android and desktop. Browsers like Apple Safari and Mozilla Firefox do not currently support this event, meaning alternative fallback instructions (such as “Add to Home Screen” guides) are required for those platforms.