Install Prompt
ขั้นตอนการติดตั้ง
หัวข้อที่มีชื่อว่า “ขั้นตอนการติดตั้ง”เมื่อ browser ตัดสินใจว่า PWA ของคุณสามารถติดตั้งได้ (manifest ที่ถูกต้อง + service worker ที่ลงทะเบียน + HTTPS) จะยิง event beforeinstallprompt บน window โดยค่าเริ่มต้น browser จะแสดง install badge หรือ prompt ของตัวเองทันที — แต่คุณสามารถดักจับ event นั้น ซ่อน UI เริ่มต้น และแสดงปุ่มติดตั้งของคุณเองในเวลาที่เหมาะสม
ขั้นตอนที่ 1 — เก็บ event ไว้
หัวข้อที่มีชื่อว่า “ขั้นตอนที่ 1 — เก็บ event ไว้”let deferredPrompt = null;
window.addEventListener('beforeinstallprompt', (event) => { // ป้องกันเบราว์เซอร์แสดง mini-infobar ของตัวเอง event.preventDefault(); // เก็บ event เพื่อเรียกใช้ในภายหลัง deferredPrompt = event; // แสดงปุ่มติดตั้งของคุณเอง document.getElementById('install-btn').hidden = false;});ขั้นตอนที่ 2 — เรียก prompt จาก user gesture
หัวข้อที่มีชื่อว่า “ขั้นตอนที่ 2 — เรียก prompt จาก user gesture”คุณต้องเรียก deferredPrompt.prompt() จากภายใน handler ที่เริ่มต้นโดยผู้ใช้ (การคลิก) การเรียกนอก user gesture จะทำให้เกิด error
document.getElementById('install-btn').addEventListener('click', async () => { if (!deferredPrompt) return; // แสดง install dialog ของเบราว์เซอร์ deferredPrompt.prompt(); // รอการเลือกของผู้ใช้ const { outcome } = await deferredPrompt.userChoice; console.log('User choice:', outcome); // 'accepted' หรือ 'dismissed' deferredPrompt = null; document.getElementById('install-btn').hidden = true;});ขั้นตอนที่ 3 — ตอบสนองต่อการติดตั้งที่สำเร็จ
หัวข้อที่มีชื่อว่า “ขั้นตอนที่ 3 — ตอบสนองต่อการติดตั้งที่สำเร็จ”event appinstalled ยิงหลังจากผู้ใช้ยืนยันการติดตั้ง:
window.addEventListener('appinstalled', () => { console.log('PWA installed successfully'); deferredPrompt = null;});ความแตกต่างบน iOS
หัวข้อที่มีชื่อว่า “ความแตกต่างบน iOS”Safari บน iOS ไม่ ยิง beforeinstallprompt ไม่มีวิธีการเรียก install dialog แบบ programmatic ทางเลือกเดียวคือแสดง banner แนะนำที่แนะนำผู้ใช้ให้ทำด้วยตนเอง:
- แตะปุ่ม Share ใน Safari
- เลื่อนลงแล้วแตะ 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 จริงเพื่อทดสอบ
ข้อแลกเปลี่ยน
หัวข้อที่มีชื่อว่า “ข้อแลกเปลี่ยน”| ตัวเลือก | Benefit | Cost |
|---|---|---|
| ดักจับ 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
💡 ตัวอย่างจากของจริง
Pinterest — แสดงปุ่มติดตั้งของตัวเองหลังจากผู้ใช้มี engagement ระดับหนึ่งแล้ว แทนที่จะโชว์ตั้งแต่หน้าแรก ทำให้ conversion สูงขึ้น
Starbucks — ดักจับ beforeinstallprompt แล้วผูกกับปุ่ม “Add to Home Screen” ที่ออกแบบเข้ากับ branding ของแอปเอง