Install Prompt Issues | Blue Frog Docs

Install Prompt Issues

Fix Add to Home Screen and PWA installation prompt problems

Install Prompt Issues

What This Means

The install prompt (Add to Home Screen) allows users to install your PWA. Issues include:

  • Prompt never appearing
  • Prompt dismissed and not returning
  • Installation failing silently
  • Different behavior across browsers

Install Prompt Requirements

Chrome requires ALL of these:

  1. HTTPS (or localhost)
  2. Valid web app manifest with required fields
  3. Registered service worker with fetch handler
  4. Not already installed
  5. Meets engagement heuristic (user interaction)

How to Diagnose

1. DevTools Checklist

  1. DevTools > Application > Manifest

    • Check "Installability" section for errors
  2. DevTools > Application > Service Workers

    • Verify SW is registered and active

2. Console Debugging

// Check if install prompt is available
window.addEventListener('beforeinstallprompt', (e) => {
  console.log('Install prompt available!');
  console.log('Platforms:', e.platforms);
});

// Check if already installed
window.addEventListener('appinstalled', () => {
  console.log('PWA was installed');
});

// Check display mode
if (window.matchMedia('(display-mode: standalone)').matches) {
  console.log('Already running as installed PWA');
}

3. Common Blockers

Issue Check
No HTTPS Site must be secure
Manifest missing <link rel="manifest"> present
Manifest invalid Check DevTools for errors
No service worker SW registered with fetch handler
Already installed Check if already in standalone mode
iOS Safari Uses different install mechanism

General Fixes

Custom Install Button

// main.js - Custom install experience
let deferredPrompt;

window.addEventListener('beforeinstallprompt', (e) => {
  // Prevent default mini-infobar
  e.preventDefault();

  // Save event for later
  deferredPrompt = e;

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

document.getElementById('install-button').addEventListener('click', async () => {
  if (!deferredPrompt) return;

  // Show the prompt
  deferredPrompt.prompt();

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

  // Clear the deferred prompt
  deferredPrompt = null;

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

// Track successful installs
window.addEventListener('appinstalled', () => {
  console.log('PWA installed successfully');
  // Track in analytics
  gtag('event', 'pwa_install', { method: 'browser_prompt' });
});

Install Prompt UI

<!-- Custom install banner -->
<div id="install-banner" style="display: none;">
  <div class="install-content">
    <img src="/icons/icon-72.png" alt="App icon">
    <div>
      <strong>Install BlueFrog</strong>
      <p>Add to your home screen for quick access</p>
    </div>
    <button id="install-button">Install</button>
    <button id="dismiss-button">&times;</button>
  </div>
</div>

<style>
#install-banner {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  background: white;
  padding: 16px;
  box-shadow: 0 -2px 10px rgba(0,0,0,0.1);
  z-index: 1000;
}
.install-content {
  display: flex;
  align-items: center;
  gap: 16px;
  max-width: 600px;
  margin: 0 auto;
}
</style>

iOS Safari Installation

iOS doesn't support beforeinstallprompt. Provide manual instructions:

// Detect iOS Safari
const isIOS = /iphone|ipad|ipod/.test(navigator.userAgent.toLowerCase());
const isInStandaloneMode = window.matchMedia('(display-mode: standalone)').matches;
const isSafari = /safari/.test(navigator.userAgent.toLowerCase()) &&
                 !/chrome/.test(navigator.userAgent.toLowerCase());

if (isIOS && isSafari && !isInStandaloneMode) {
  showIOSInstallInstructions();
}

function showIOSInstallInstructions() {
  const banner = document.getElementById('ios-install-banner');
  banner.innerHTML = `
    <p>Install this app on your iPhone:</p>
    <ol>
      <li>Tap the Share button <span class="share-icon">⎙</span></li>
      <li>Scroll and tap "Add to Home Screen"</li>
    </ol>
  `;
  banner.style.display = 'block';
}

Delayed Prompt Strategy

// Don't show install prompt immediately
let deferredPrompt;
let promptShownThisSession = false;

window.addEventListener('beforeinstallprompt', (e) => {
  e.preventDefault();
  deferredPrompt = e;
});

// Show after user engages (e.g., scrolls, reads content)
let scrollDepth = 0;
window.addEventListener('scroll', () => {
  const currentDepth = (window.scrollY / document.body.scrollHeight) * 100;
  if (currentDepth > 50 && !promptShownThisSession && deferredPrompt) {
    showInstallBanner();
    promptShownThisSession = true;
  }
});

// Or show after time on page
setTimeout(() => {
  if (deferredPrompt && !promptShownThisSession) {
    showInstallBanner();
    promptShownThisSession = true;
  }
}, 60000); // 1 minute

Persist Dismiss Preference

const DISMISS_KEY = 'pwa-install-dismissed';
const DISMISS_DURATION = 7 * 24 * 60 * 60 * 1000; // 7 days

function shouldShowInstallBanner() {
  const dismissedAt = localStorage.getItem(DISMISS_KEY);
  if (dismissedAt) {
    const elapsed = Date.now() - parseInt(dismissedAt, 10);
    if (elapsed < DISMISS_DURATION) {
      return false;
    }
  }
  return true;
}

function dismissInstallBanner() {
  localStorage.setItem(DISMISS_KEY, Date.now().toString());
  document.getElementById('install-banner').style.display = 'none';
}

Platform-Specific Guides

Platform Guide
Next.js Next.js PWA Install
WordPress WordPress PWA Install

Verification

  1. Meet all install criteria
  2. beforeinstallprompt fires (check console)
  3. Custom install button triggers prompt
  4. Installation completes successfully
  5. App appears in app drawer/home screen

Common Mistakes

Mistake Fix
Calling prompt() without user gesture Must be triggered by click
Not preventing default Call e.preventDefault()
Expecting iOS support Provide manual instructions
Prompt reuse Can only use deferredPrompt once

Further Reading

// SYS.FOOTER