How to Add an "Install App" Button to Your PWA for All Platforms

A simple example of how to add an Install App button to your PWA ready website or web app.
January 22, 2025 by
Administrator
| No comments yet

Progressive Web Apps (PWAs) have become an excellent way to provide a native app experience directly from the web. To encourage users to install your PWA, you can add a simple "Install App" button that triggers the installation process on supported platforms. This post will guide you step-by-step on how to implement this feature and provide a fallback for iOS devices.

Why Add an "Install App" Button?

By default, browsers may prompt users to install a PWA when certain conditions are met. However, this can be inconsistent and easily missed. Adding a visible "Install App" button:

  • Improves discoverability.
  • Encourages users to install your app.
  • Gives you control over when to show the installation option.

Step 1: Capturing the beforeinstallprompt Event

The beforeinstallprompt event is fired when the browser detects that your PWA meets the installation criteria (e.g., it has a valid manifest.json and service worker). This event can be stored and triggered when the user clicks the "Install App" button.

Here’s how to capture the event:

let deferredPrompt;

window.addEventListener('beforeinstallprompt', (e) => {
    // Prevent the default prompt from showing automatically
    e.preventDefault();
    // Save the event for later use
    deferredPrompt = e;

    // Show the install button
    document.getElementById('install-button').style.display = 'block';
});

Step 2: Triggering the Installation Prompt

When users click the button, you can trigger the saved beforeinstallprompt event using its prompt() method. You can also handle the user’s response (e.g., whether they accepted or dismissed the installation).

document.getElementById('install-button').addEventListener('click', async () => {
    if (deferredPrompt) {
        // Show the installation prompt
        deferredPrompt.prompt();

        // Wait for the user's choice
        const { outcome } = await deferredPrompt.userChoice;
        console.log(`User response: ${outcome}`);

        // Clear the saved prompt
        deferredPrompt = null;
    }
});

Step 3: Detecting Successful Installation

You can use the appinstalled event to detect when the PWA is installed. Once installed, you can hide the "Install App" button to avoid unnecessary prompts.

window.addEventListener('appinstalled', () => {
    console.log('PWA installed');
    document.getElementById('install-button').style.display = 'none';
});

Step 4: Adding the Install Button to Your HTML

Here’s a simple example of an "Install App" button styled for better visibility:

<button id="install-button" style="display: none; position: fixed; bottom: 20px; right: 20px; padding: 10px 20px; background-color: #007bff; color: white; border: none; border-radius: 5px; cursor: pointer;">
    Install App
</button>

Initially, the button is hidden. It becomes visible only when the beforeinstallprompt event is fired.

Step 5: Fallback for iOS Devices

Unfortunately, iOS (Safari) does not support the beforeinstallprompt event or the prompt() method. To provide a smooth user experience, you can display a message explaining how to manually install the PWA.

Detecting iOS Devices

You can use the following function to check if the user is on iOS:

function isIOS() {
    return /iPhone|iPad|iPod/i.test(navigator.userAgent);
}

Displaying Instructions for iOS

If the user is on iOS, show a message with instructions to manually add the PWA to their home screen. Here’s an example:

<div id="ios-instructions" style="display: none; position: fixed; bottom: 20px; left: 20px; padding: 10px; background-color: #f7f7f7; border: 1px solid #ddd; border-radius: 5px; max-width: 300px;">
    <p>To install this app on your iPhone or iPad:</p>
    <ol>
        <li>Tap the <strong>Share</strong> button in Safari.</li>
        <li>Scroll down and select <strong>Add to Home Screen</strong>.</li>
        <li>Follow the on-screen instructions.</li>
    </ol>
    <button id="ios-close-btn" style="margin-top: 10px; padding: 5px 10px; background-color: #007bff; color: white; border: none; border-radius: 5px; cursor: pointer;">
        Got it
    </button>
</div>

JavaScript to Handle iOS Fallback

Display the instructions if the user is on iOS and allow them to dismiss the message:

if (isIOS()) {
    const iosInstructions = document.getElementById('ios-instructions');
    iosInstructions.style.display = 'block';

    document.getElementById('ios-close-btn').addEventListener('click', () => {
        iosInstructions.style.display = 'none';
    });
}

Complete Example Code

Here’s the complete code for adding the "Install App" button with an iOS fallback:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="manifest" href="manifest.json">
    <link rel="apple-touch-icon" href="icon-192x192.png"> <!-- Placeholder for apple-touch-icon -->
    <title>PWA Sample App</title>
    <script>
        if ('serviceWorker' in navigator) {
            window.addEventListener('load', () => {
                navigator.serviceWorker.register('service-worker.js')
                    .then(registration => {
                        console.log('Service Worker registered with scope:', registration.scope);
                    })
                    .catch(error => {
                        console.error('Service Worker registration failed:', error);
                    });
            });
        }
    </script>
    <style>
        /* Moved styles for Install Button */
        #install-button {
            display: none;
            position: fixed;
            bottom: 20px;
            right: 20px;
            padding: 10px 20px;
            background-color: #007bff;
            color: white;
            border: none;
            border-radius: 5px;
            cursor: pointer;
        }

        /* Moved styles for iOS Instructions */
        #ios-instructions {
            display: none;
            position: fixed;
            bottom: 20px;
            left: 20px;
            padding: 10px;
            background-color: #f7f7f7;
            border: 1px solid #ddd;
            border-radius: 5px;
            max-width: 300px;
        }

        /* Moved styles for iOS Close Button */
        #ios-close-btn {
            padding: 5px 10px;
            background-color: #007bff;
            color: white;
            border: none;
            border-radius: 5px;
            cursor: pointer;
        }

        body {
            font-family: Arial, sans-serif;
            margin: 0;
            padding: 0;
            background-color: #f4f4f4;
        }

        header {
            background: #333;
            color: #fff;
            padding: 10px 0;
            text-align: center;
        }

        main {
            padding: 20px;
        }

        footer {
            text-align: center;
            padding: 10px 0;
            background: #333;
            color: #fff;
            position: fixed;
            width: 100%;
            bottom: 0;
        }
    </style>
</head>

<body>
    <header>
        <h1>Welcome to the PWA Sample App</h1>
    </header>
    <main>
        <h2>Home Page</h2>
        <p>This is a sample Progressive Web App demonstrating the install button and offline capabilities.</p>
    </main>
    <footer>
        <p>&copy; 2023 PWA Sample App</p>
    </footer>

    <!-- Install Button -->
    <button id="install-button">
        Install App
    </button>

    <!-- iOS Instructions -->
    <div id="ios-instructions">
        <p>To install this app on your iPhone or iPad:</p>
        <ol>
            <li>Tap the <strong>Share</strong> button in Safari.</li>
            <li>Scroll down and select <strong>Add to Home Screen</strong>.</li>
            <li>Follow the on-screen instructions.</li>
        </ol>
        <button id="ios-close-btn">
            Got it
        </button>
    </div>
    <script>
        let deferredPrompt;

        function isIOS() {
            return /iPhone|iPad|iPod/i.test(navigator.userAgent);
        }

        if (isIOS()) {
            const iosInstructions = document.getElementById('ios-instructions');
            iosInstructions.style.display = 'block';

            document.getElementById('ios-close-btn').addEventListener('click', () => {
                iosInstructions.style.display = 'none';
            });
        }

        window.addEventListener('beforeinstallprompt', (e) => {
            e.preventDefault();
            deferredPrompt = e;
            document.getElementById('install-button').style.display = 'block';
        });

        document.getElementById('install-button').addEventListener('click', async () => {
            if (deferredPrompt) {
                deferredPrompt.prompt();
                const { outcome } = await deferredPrompt.userChoice;
                console.log(`User response: ${outcome}`);
                deferredPrompt = null;
            }
        });

        window.addEventListener('appinstalled', () => {
            console.log('PWA installed');
            document.getElementById('install-button').style.display = 'none';
        });
    </script>
</body>

</html>


Add service-worker.js and manifest.jason

To complete our PWA website we should write a manifest.json and optionally a service-worker.js.

manifest.json

{
  "name": "PWA Sample App",
  "short_name": "PWA App",
  "start_url": "index.html",
  "display": "standalone",
  "background_color": "#ffffff",
  "theme_color": "#000000",
  "icons": [
    {
      "src": "icon-192x192.png",
      "sizes": "192x192",
      "type": "image/png"
    },
    {
      "src": "icon-512x512.png",
      "sizes": "512x512",
      "type": "image/png"
    }
  ]
}
service-worker.js:

const CACHE_NAME = 'pwa-cache-v1';
const urlsToCache = [
  'index.html',
  'manifest.json',
  'icon-192x192.png',
  'icon-512x512.png'
];

// Install the service worker
self.addEventListener('install', (event) => {
  event.waitUntil(
    caches.open(CACHE_NAME)
      .then((cache) => {
        return cache.addAll(urlsToCache);
      })
  );
});

// Fetch resources from the cache
self.addEventListener('fetch', (event) => {
  event.respondWith(
    caches.match(event.request)
      .then((response) => {
        return response || fetch(event.request);
      })
  );
});
Run using simple http server in Python:

$ python3 -m http.server 8000


And your website or your web app is PWA and users can easily install it as native app on any platform:


Conclusion

By making your website or web app PWA ready your users can easily install it as a native app. Adding an "Install App" button makes your PWA more user-friendly and increases the chances of installation. By handling the beforeinstallprompt event and providing fallback instructions for iOS users, you ensure your app is accessible to everyone.


in Web
Administrator January 22, 2025
Share this post
Tags
Archive

Please visit our blog at:

https://zehabsd.com/blog

A platform for Flash Stories:

https://readflashy.com

A platform for Persian Literature Lovers:

https://sarayesokhan.com

Sign in to leave a comment