ข้ามไปยังเนื้อหา

Install Prompt

เมื่อ browser ตัดสินใจว่า PWA ของคุณสามารถติดตั้งได้ (manifest ที่ถูกต้อง + service worker ที่ลงทะเบียน + HTTPS) จะยิง event beforeinstallprompt บน window โดยค่าเริ่มต้น browser จะแสดง install badge หรือ prompt ของตัวเองทันที — แต่คุณสามารถดักจับ event นั้น ซ่อน UI เริ่มต้น และแสดงปุ่มติดตั้งของคุณเองในเวลาที่เหมาะสม

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;
});

คุณต้องเรียก deferredPrompt.prompt() จากภายใน handler ที่เริ่มต้นโดยผู้ใช้ (การคลิก) การเรียกนอก user gesture จะทำให้เกิด error

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;
});

ขั้นตอนที่ 3 — ตอบสนองต่อการติดตั้งที่สำเร็จ

หัวข้อที่มีชื่อว่า “ขั้นตอนที่ 3 — ตอบสนองต่อการติดตั้งที่สำเร็จ”

event appinstalled ยิงหลังจากผู้ใช้ยืนยันการติดตั้ง:

window.addEventListener('appinstalled', () => {
console.log('PWA installed successfully');
deferredPrompt = null;
});

Safari บน iOS ไม่ ยิง beforeinstallprompt ไม่มีวิธีการเรียก install dialog แบบ programmatic ทางเลือกเดียวคือแสดง banner แนะนำที่แนะนำผู้ใช้ให้ทำด้วยตนเอง:

  1. แตะปุ่ม Share ใน Safari
  2. เลื่อนลงแล้วแตะ Add to Home Screen

ตรวจสอบ iOS เพื่อแสดงคำแนะนำที่ถูกต้อง:

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;
}

playground ด้านล่างเชื่อมต่อ install-button flow แบบครบถ้วน เนื่องจาก StackBlitz ทำงานภายใน iframe event beforeinstallprompt จะไม่ยิง — แต่คุณสามารถตรวจสอบโค้ดทั้งหมดและรันบน domain จริงเพื่อทดสอบ

Runs a real service worker + manifest in your browser.
ตัวเลือกBenefitCost
ดักจับ beforeinstallprompt แล้วแสดงปุ่มติดตั้งเองควบคุม timing และ UI ได้เต็มที่ ไม่รบกวนผู้ใช้ตอนที่ไม่พร้อมต้อง handle state และ event lifecycle เอง เพิ่ม complexity ของโค้ด
ปล่อยให้ browser แสดง install UI ของตัวเอง (default)ไม่ต้องเขียนโค้ดเพิ่ม ได้ UI มาตรฐานทันทีควบคุม timing ไม่ได้ อาจโผล่มาตอนที่ผู้ใช้ยังไม่พร้อมตัดสินใจ
  • เรียก prompt() นอก user gesture handler (เช่นใน useEffect ตอน mount) ทำให้ browser โยน error และปฏิเสธคำขอ
  • ไม่เก็บ deferredPrompt ไว้ตั้งแต่ event แรก ทำให้พลาดโอกาสแสดงปุ่มติดตั้งไปเลยหากไม่ได้ดักจับทัน
  • ลืมว่า iOS Safari ไม่ยิง beforeinstallprompt เลย แล้วออกแบบ UI ติดตั้งที่ใช้ไม่ได้กับผู้ใช้ iOS

ทั้ง beforeinstallprompt และ deferredPrompt.prompt() เป็น API เฉพาะ Chromium เท่านั้น (Chrome, Edge, Samsung Internet) — Firefox และ Safari ไม่ implement ทั้งคู่ (MDN: making PWAs installable) การรอแสดงปุ่มติดตั้งแบบกำหนดเองจนกว่าผู้ใช้จะมี engagement กับแอปบ้างแล้ว — แทนที่จะโชว์ตั้งแต่โหลดหน้าแรก — เป็น best practice ที่มีการบันทึกไว้จริงสำหรับเพิ่มอัตราที่ผู้ใช้กดยอมรับ install prompt ไม่ว่าจะเป็นแอปไหนก็ตาม

ต้องเรียกอะไรบน event beforeinstallprompt เพื่อระงับ install UI เริ่มต้นของ browser?
ต้องเรียก deferredPrompt.prompt() จากที่ไหน?
event ใดที่ยิงหลังผู้ใช้ติดตั้ง PWA สำเร็จ?
ผู้ใช้ iOS ต้องติดตั้ง PWA อย่างไรเมื่อ beforeinstallprompt ไม่พร้อมใช้งาน?