Chrome 安装提示优化:触发时机、自定义安装按钮与提示不出现的排查顺序(2026)
Chrome 安装提示优化包含三件事:先让页面通过 Chrome 的可安装性检查,beforeinstallprompt 事件才会触发;然后捕获这个事件,用你自己的安装按钮在合适的时机替代 Chrome 默认的底部小横幅;最后把按钮文案和位置写好,给访客一个点下去的理由。下面逐层讲清楚每一部分怎么工作、哪些设置决定提示会不会出现,以及提示不出现时的排查顺序。
你优化的到底是什么
安卓上的 Chrome 不会因为你想弹安装提示就弹。只有当页面满足可安装性条件、访客又表现出一定互动之后,Chrome 才会触发 beforeinstallprompt 事件,这时你的代码才能调用 prompt() 弹出原生对话框。你能影响的东西分三层:
- 可安装性:manifest、HTTPS、service worker,以及尚未安装这一条。这层不过,后面全白搭。
- 触发时机:相对于访客刚做了什么,你在什么时候调用
prompt()。 - 呈现方式:你展示的自定义按钮或横幅、文案、位置,以及访客接受或关闭之后发生什么。
如果你需要先了解平台背景,比如安卓和 iOS 的提示机制有什么不同、各自会发生什么,可以看我们关于添加到主屏幕提示的文章。本文只讲 Chrome 这条路怎么调。
Chrome 安装提示优化从可安装性开始
Chrome 的可安装性条件在 web.dev 和 Chrome for Developers 上有文档,它是第一道闸。按当前 Chrome 版本,清单是:
- 通过 HTTPS 提供(开发时 localhost 例外)。
- 页面链接了一个 Web 应用 manifest,至少包含:
name或short_name、start_url、display设为standalone、fullscreen或minimal-ui(或display_override里含其中之一),以及icons里包含 192 乘 192 和 512 乘 512 的 PNG。 prefer_related_applications不存在或为false。它为true时,Chrome 会把用户引导到related_applications里列出的原生应用。- 该应用尚未安装在这台设备上。
- 用户互动启发式:访客在这个域名上停留了一小段时间并至少点击过一次页面。Chrome 不公布具体数字,而且会变,但首次加载、零互动时什么都不触发,是设计如此。
有两条旧教程还在列的要求已经放宽。Chrome 几个版本前取消了离线可用这条检查,后来又放宽了 service worker 对可安装性的要求。实践中你仍然应该注册 service worker:安卓上的旧版 Chrome 还会检查它,其他 Chromium 内核浏览器可能不同,而且 service worker 是安装后的应用能快速启动、在弱网下不白屏的基础。
一个能通过检查的最小 manifest:
{
"name": "Example App",
"short_name": "Example",
"start_url": "/?source=pwa",
"display": "standalone",
"background_color": "#ffffff",
"theme_color": "#0a84ff",
"icons": [
{ "src": "/icons/icon-192.png", "sizes": "192x192", "type": "image/png" },
{ "src": "/icons/icon-512.png", "sizes": "512x512", "type": "image/png", "purpose": "any" }
]
}如果希望启动器图标填满安卓的自适应形状,而不是缩在一个白圆圈里,再加一条单独的 maskable 图标。这是主屏幕上肉眼可见的质量信号,直接决定安装后的图标看起来像不像一个真正的应用。
捕获 beforeinstallprompt,做自定义安装按钮
安卓 Chrome 的默认行为是在条件满足后,在底部弹一个小横幅(mini-infobar)。它很容易被忽略、也很容易被划掉,而且一旦划掉,Chrome 会等很久才再次显示。自定义安装按钮的全部意义,就是把这个时刻的控制权拿回来。
let deferredPrompt = null;
const installButton = document.getElementById('install-btn');
window.addEventListener('beforeinstallprompt', (event) => {
// 阻止 Chrome 立刻显示底部小横幅
event.preventDefault();
deferredPrompt = event;
// 事件证明可安装之后,再显示你自己的按钮
installButton.hidden = false;
});
installButton.addEventListener('click', async () => {
if (!deferredPrompt) return;
deferredPrompt.prompt();
const { outcome } = await deferredPrompt.userChoice; // 'accepted' | 'dismissed'
// 被延迟的事件只能用一次
deferredPrompt = null;
installButton.hidden = true;
// 在这里把 outcome 发给统计
});
window.addEventListener('appinstalled', () => {
// 从任何入口安装成功后都会触发,包括 Chrome 自己的菜单
deferredPrompt = null;
installButton.hidden = true;
});由事件设计推出来的几条规则:
prompt()必须在用户手势(点你的按钮)里调用。放在定时器或页面加载里调用会被忽略。- 每个
beforeinstallprompt事件只能支撑一次prompt()调用。访客关闭后不能立刻再调,要等新事件,而 Chrome 一段时间内不会再触发。 - 事件到来之前安装按钮要保持隐藏。一个点了没反应的按钮(因为事件根本没触发)比没有按钮更糟。
- 监听
appinstalled来清理界面并记录转化。userChoice的结果告诉你访客点了安装,appinstalled告诉你安装完成了。
触发时机:什么时候显示按钮
事件只说明可以安装,不代表访客准备好了。Chrome 在 web.dev 上的建议是等访客有了想要这个应用的理由之后再推广安装,我们在安装类投放上的经验也指向同一个方向。有效的模式:
- 完成一个动作之后:访客读完了内容、提交了表单、加了东西、走到了流程结尾。在确认状态上显示安装按钮。
- 再次访问时:同一域名的第二次会话比第一次是更强的兴趣信号。用 localStorage 计数,在第二或第三次访问时推广。
- 内容页按滚动深度或停留时长:访客滚过首屏并停留一会儿之后再显示,而不是第一秒就显示。
- 当安装本身就是 offer,比如落地页的目的就是把应用装到主屏幕,那就把按钮放在首屏当主行动按钮,但仍然要等事件触发之后才显示。在那之前隐藏它,或者显示一个带一句简短说明的不可用状态。
有害的模式:在 setTimeout 里调 prompt()(会静默失败并消耗掉手势);在访客还没看到任何内容之前就用安装横幅盖住页面;被关闭之后每个页面都再弹一次。关闭是一种信息,按你自己定的周期尊重它(存一个时间戳,几天或几周内不再推广)。
安装按钮的文案与位置
Chrome 的原生对话框显示你的应用名、图标和一个安装按钮,那段文字你改不了。你能控制的是访客点下去走到那一步的元素,以及它周围的文字。
- 按钮写收益而不是机制:加到主屏幕一键打开、安装后加载更快且离线可用,都比安装 PWA 好。多数访客不知道这个缩写是什么。
- 说清楚代价:不用去商店下载、不需要注册账号、可以像任何应用一样删除。常见的犹豫是觉得安装意味着一个很大的下载包。
- 把按钮放在自然会点的位置:安装优先的落地页放首屏,文章页放内容末尾,回访用户放页头。避免和浏览器自己的底栏抢位置的悬浮层。
- 在按钮旁边放应用图标。它预告了主屏幕上会出现什么,也和接下来的原生对话框对得上。
- 一屏只放一个安装提示。把它和通知权限请求、订阅弹窗放在同一时刻,会把三者的接受率一起拉低。
对安装优先的页面来说,落地页本身就是提示的环境,按钮周围的页面结构怎么搭,见我们的PWA 落地页指南。
Chrome 安装提示不出现:排查顺序
beforeinstallprompt 一直不触发时,按下面的顺序查。Chrome DevTools 的 Application 面板下的 Manifest 页会逐条列出可安装性错误,多数问题在那里就有答案。
- 打开 DevTools,Application,Manifest,看可安装性部分。缺图标尺寸、
display值不对、start_url跳到别的域名或返回非 200 状态、manifest 解析错误,都会显示在这里。 - 确认访客实际落到的那个 URL 是 HTTPS,包括广告点击之后的所有跳转。
- 检查应用是否已经安装。已安装的应用 Chrome 不会再触发事件。用新的浏览器配置测,或者先卸载。安卓上 Chrome 的
chrome://webapks页面列出了已安装的 Web 应用。 - 检查是否最近被关闭过。如果测试人员之前在同一设备上划掉了提示,Chrome 会在一段冷却期内压制它,web.dev 对 mini-infobar 的描述是大约三个月。测试请用全新的配置。
- 检查浏览器。
beforeinstallprompt是 Chromium 的特性,Safari 里没有,Firefox 里不触发,在 Facebook、Instagram、TikTok 和大多数应用的内嵌浏览器里也不触发,因为那些是 WebView,不是 Chrome。对广告流量来说这通常才是真正的原因:访客在应用的浏览器里,事件永远不会触发,安装按钮永远不会出现。修法在落地页而不在 manifest:识别应用内浏览器,先把访客引到 Chrome,再推广安装。 - 检查
prefer_related_applications。它为true且列了关联的原生应用时,Chrome 会推广那个应用。 - 检查互动启发式。先和页面互动(点一下、停几秒)再期待事件。
- 检查你自己的代码。调了
preventDefault()却从未调用prompt(),提示就被截住再也不用了;监听器在事件已经触发之后才挂上,也会错过。监听器要尽早在页面加载时挂上。 - 在 Application,Service Workers 里检查 service worker。即使它已经不是硬性要求,旧版 Chrome 上一个注册失败的 service worker 仍会挡住提示。
九条都过、在安卓上干净的 Chrome 配置里事件仍不触发,先记下 Chrome 版本并用 Chrome 自己的可安装性工具测一遍,再怀疑页面。
怎么衡量优化有没有效果
把提示当成四步漏斗,每一步都记录:
beforeinstallprompt触发(这位访客通过了可安装性)。- 安装按钮显示(你的时机规则触发了)。
prompt()被调用(访客点了你的按钮)。userChoice为接受且appinstalled触发。
第一步和最后一步之间的比值告诉你弱点在页面、时机还是文案;按流量来源对比,能看出差距里有多少是应用内浏览器的问题。这些事件怎么发到 GA4、怎么归因到投放,见我们关于衡量添加到主屏幕转化的文章。
ROIBest 的 PWA 落地页就是围绕这条序列为广告流量搭建的:从应用内浏览器切换到 Chrome,自定义安装按钮绑定 beforeinstallprompt,安装事件按漏斗分步记录,你可以看到访客在哪一步流失。
常见问题
为什么我的网站上 beforeinstallprompt 不触发?
最常见的是四种原因之一:manifest 没通过可安装性检查(看 DevTools 的 Application,Manifest)、应用已经安装、提示最近被关闭过而 Chrome 处于冷却期、页面是在非 Chrome 浏览器里打开的,比如根本没有这个事件的应用内 WebView。
能不能在页面加载时自动弹出 Chrome 安装提示?
不能。prompt() 只能在点击这类用户手势里调用,而且要等 beforeinstallprompt 触发之后。事件到来后你可以自动显示自己的安装按钮,但原生对话框需要访客点一下。
安装提示可以显示几次?
每个 beforeinstallprompt 事件一次。被关闭之后 Chrome 会等一段时间才再次触发事件,你自己也应该把关闭记录下来,几天或几周内不再推广,而不是每个页面都弹。
安装提示在 Facebook 或 TikTok 的应用内浏览器里能用吗?
不能。这些应用用内嵌的 WebView 打开页面,WebView 没有实现 beforeinstallprompt。对广告流量,先识别应用内浏览器,引导访客在 Chrome 里打开页面,再显示安装按钮。


