Live stream set for 2025-04-20 at 14:00:00 Eastern
Ask questions in the live chat about any programming or lifestyle topic.
This livestream will be on YouTube or you can watch below.
Cross Platform PWA Install Button
Creating a custom install button for a Progressive Web App (PWA) involves several steps to ensure it works across different browsers and devices. The PWA must meet the minimum requirements such as being available of a secure HTTPS connection.
The event listener “beforeinstallprompt” is fired only once for the installation. The default behavior of the event can be prevented and hooked to a custom event such as a custom button click.
The PWA can not be installed directly via a custom button. Instead the prompt for installation can be triggered.
As of Spring 2025, only Chromium-based web browser support the beforeinstallprompt event on the desktop and Android.
In this tutorial, a polyfill will not be implemented for web browsers that lack support for the beforeinstallprompt event. Permission is required to install the app, so it must be secure connection unless it is on the same workstation where localhost is allowed in the URL.
Requirements For Locally Hosted PWA
Glossary:
IP
Internet Protocol address is a numerical label that is assigned to a device connected to a computer network.
Wi-Fi
Wireless network protocols based on the IEEE 802.11 standards for local area networks.
WLAN
Wireless LAN is a computer network that links 2 or more devices.
TCP/IP
Transmission Control Protocol/Internet Protocol is a framework for computer networking.
USB
Universal Serial Bus is a standard for digital data transmission and power delivery between electronics.
ADB
Android Debug Bridge.
PWA
Progressive Web App is built using web platforms to provide platform-specific experiences.
Polyfill
Implements a new standard feature that is not natively supported.
Web Prompt
Instructs the browser to display a dialog prompting the user for input.
Testing Devices
Name | Description | Results |
---|---|---|
Sony Xperia XA1 Ultra | Updated to Android 8.0 and latest web browser. | Successfully installed & uninstalled. |
Samsung Galaxy S21 FE 5G | Updated to Android 14.0 and default camera application. | Successfully installed & uninstalled. |
Custom Workstation | Fedora Linux Workstation 41, Gnome 47. | Successfully installed & uninstalled. |
Name | Description | Example |
Generate Transparent Graphic Images
# Create Installation Icon # magick -size 512x512 xc:none pwa-install-btn.webp # Create Narrow Screenshot # magick -size 1080x1920 xc:none pwa-install-btn-screenshot-narrow.avif # Create Wide Screenshot # magick -size 1920x1080 xc:none pwa-install-btn-screenshot-wide.avif # Create Favicon # cat > favicon.svg << 'EOF' <?xml version="1.0" encoding="UTF-8" ?> <svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="12" height="12"></svg> EOF
HTML Cross Platform Install Button
<!DOCTYPE html> <html> <head> <title>PWA Install Button</title> <meta name="viewport" content="width=device-width, initial-scale=1" /> <style> button { color: blue; background: red; display: none; } </style> <link rel="icon" href="/install-btn/favicon.svg" type="image/svg+xml" sizes="any"> <link rel="manifest" href="/install-btn/manifest.json" /> </head> <body> <h2>This App Uses A Custom Button For Installation</h2> <button>Install Prompt</button> <script src="/install-btn/index.js"></script> </body> </html>
JavaScript Toggle Install Prompt Button And Register PWA Service Worker
if ("serviceWorker" in navigator) { window.addEventListener("load", () => { window.addEventListener('beforeinstallprompt', (evt) => { let btn = document.querySelector('button'); btn.style.display = 'block'; btn.onclick = () => { evt.prompt(); btn.style.display = 'none'; }; }); // Register Server Worker navigator.serviceWorker .register("/install-btn/sw.js", {scope: "/install-btn/"}) .then(res => console.log("Service Worker Registered")) .catch(err => console.log("Service Worker Not Registered", err)); }); }
JavaScript Service Worker Install
self.addEventListener('install', (event) => { event.waitUntil( caches.open('pwa-install-button').then((cache) => { return cache.addAll([ '/install-btn/' ]); }) ); }); self.addEventListener("fetch", fetchEvent => { fetchEvent.respondWith( caches.match(fetchEvent.request).then(res => { return res || fetch(fetchEvent.request); }) ); });
JSON Manifest
{ "name": "PWA Install Button", "short_name": "Install Button", "start_url": "/install-btn/index.html", "display": "standalone", "icons": [ { "src": "/install-btn/pwa-install-btn.webp", "type": "image/webp", "sizes": "512x512" } ], "screenshots": [ { "src": "/install-btn/pwa-install-btn-screenshot-narrow.avif", "sizes": "1080x1920", "form_factor": "narrow", "label": "Protrait view showing PWA install button" }, { "src": "/install-btn/pwa-install-btn-screenshot-wide.avif", "sizes": "1920x1080", "form_factor": "wide", "label": "Landscape view showing PWA install button" } ] }
PHP HTTP Server
# Start PHP Web Server # php -S localhost:8000
ADB Wireless Connection
# Start Optional Android Wireless Connection # adb tcpip 5555 adb tcpip connect [Android Device IP Address] adb devices
Download
The ImageMagick tools can be downloaded from ImageMagick and installed on your workstation.
The PHP scripting language can be downloaded from PHP and installed on your workstation.
Explanation
- Generate a graphic images.
- Place all files in a subfolder.
- The button will only show if the PWA is not installed.
- Use the ADB tool to connect to your Android device.
- Open the Chrome web browser on your Android device.
- Open the Chrome web browser or chromium-based web browser on your desktop.
- On the desktop, navigate to chrome://inspect/#devices.
- Enable port forwarding.
- You should now be able to open the localhost port number in the mobile Android Chrome web browser.







Usage
- You may use the ImageMagick magick command line tool to generate images.
- You may use the PHP built-in web server and Stunnel for tunneling secure connections.
- The Barcode Detection API is limited to 13 formats and not all might be supported in different web browsers.
Open Source
ImageMagick is licensed under the ImageMagick License. The permissive license has conditions requiring preservation of copyright and license notices. Redistribution is permitted in source or binary form with or without modifications, consult the license for more specific details..
The PHP License is an open-source under which the PHP scripting language is released. The permissive license has conditions requiring preservation of copyright and license notices. Redistribution is permitted in source or binary form with or without modifications, consult the license for more specific details.
Conclusion:
The default prompt event behavior can be prevented on supoorting web browsers in order to create a custom prompt event button. The PWA app should listener for the beforeinstallprompt event. The event is fired once during the installation process.
If you enjoy this article, consider supporting me by purchasing one of my OjamboShop.com Online Programming Courses or publications at Edward Ojambo Programming Books or simply donate here Ojambo.com Donate
References:
- Customer Sets Price Plugin for WooCommerce on Ojambo.com
- Learning JavaScript Course on OjamboShop.com
- Learning Python Course on OjamboShop.com
- Learning PHP Course on OjamboShop.com
- Learning JavaScript Paperback on Amazon
- Learning JavaScript Ebook on Amazon
- Learning Python Ebook on Amazon
- Learning PHP Ebook on Amazon
- OjamboServices.com For Custom Websites, Applications & Tutorials