最近总接到落地页的需求,落地页的职责主要是引流,有以下几种类型
1、引导已经下载App的用户打开App
2、引导未下载App的用户下载App
3、引导未注册的用户注册
4、引导已经注册的用户进入我们的主页或者其他的操作
从数据上可以体现在用户停留在App的时间多了,或者增加了用户量
唤起App主要的媒介是什么呢?
URL Scheme
URL Scheme的组成
1 | [scheme:][//authority][path][?query][#fragment] |
App | 微信 | 支付宝 | 淘宝 | 微博 |
---|---|---|---|---|
URL Scheme | weixin:// | alipay:// | taobao:// | sinaweibo:// |
1 | 行为(应用的某个功能) |
URL Scheme 在 ios 9+ 上诸如 safari、UC、QQ浏览器中, iframe 均无法成功唤起 APP,只能通过 window.location 才能成功唤端。
Intent
安卓的原生谷歌浏览器自从 chrome25 版本开始对于唤端功能做了一些变化,URL Scheme 无法再启动Android应用。 例如,通过 iframe 指向 weixin://,即使用户安装了微信也无法打开。所以,APP需要实现谷歌官方提供的 intent: 语法,或者实现让用户通过自定义手势来打开APP。安卓版本 4.4.4 以上机型的安卓自带浏览器、chrome 浏览器,需要通过 intent 跳转
intents文档
- Intent 语法如果用户未安装 APP,则会跳转到系统默认商店。当然,如果你想要指定一个唤起失败的跳转地址,添加下面的字符串在 end; 前就可以了:
1
2
3
4
5
6
7
8
9intent:
HOST/URI-path // Optional host
#Intent;
package=[string];
action=[string];
category=[string];
component=[string];
scheme=[string];
end;1
S.browser_fallback_url=[encoded_full_url]
- 示例
下面是打开 Zxing 二维码扫描 APP 的 intent。1
2
3
4
5
6intent:
//scan/
#Intent;
package=com.google.zxing.client.android;
scheme=zxing;
end;1
<a href="intent://scan/#Intent;scheme=zxing;package=com.google.zxing.client.android;S.browser_fallback_url=http%3A%2F%2Fzxing.org;end"> Take a QR code </a>
Universal Link
为什么要使用 Universal Link
传统的 Scheme 链接有以下几个痛点:
- 在 ios 上会有确认弹窗提示用户是否打开,对于用户来说唤端,多出了一步操作。若用户未安装 APP ,也会有一个提示窗,告知我们 “打不开该网页,因为网址无效”
- 传统 Scheme 跳转无法得知唤端是否成功,Universal Link 唤端失败可以直接打开此链接对应的页面
- Scheme 在微信、微博、QQ浏览器、手百中都已经被禁止使用,使用 Universal Link 可以避开它们的屏蔽( 截止到 18年8月21日,微信和QQ浏览器已经禁止了 Universal Link,其他主流APP未发现有禁止 )
如何让 APP 支持 Universal Link
有大量的文章会详细的告诉我们如何配置,你也可以去看官方文档,我这里简单的写一个12345。
- 拥有一个支持 https 的域名
- 在 开发者中心 ,Identifiers 下 AppIDs 找到自己的 App ID,编辑打开 Associated Domains 服务。
- 打开工程配置中的 Associated Domains ,在其中的 Domains 中填入你想支持的域名,必须以
applinks:
为前缀 - 配置
apple-app-site-association
文件,文件名必须为apple-app-site-association
,不带任何后缀 - 上传该文件到你的 HTTPS 服务器的 根目录 或者
.well-known
目录下
Universal Link 配置中的坑
这里放一下我们在配置过程中遇到的坑,当然首先你在配置过程中必须得严格按照上面的要求去做,尤其是加粗的地方。
- 域名问题
Universal Link 支持的域名最多只能支持到二级域名,如果你用到了三级域名,Universal Link 唤端是不会生效的。
- 跨域问题
IOS 9.2 以后,必须要触发跨域才能支持 Universal Link 唤端。
IOS 那边有这样一个判断,如果你要打开的 Universal Link 和 当前页面是同一域名,ios 尊重用户最可能的意图,直接打开链接所对应的页面。如果不在同一域名下,则在你的 APP 中打开链接,也就是执行具体的唤端操作。
- Universal Link 是空页面
Universal Link 本质上是个空页面,如果未安装 APP,Universal Link 被当做普通的页面链接,自然会跳到 404 页面,所以我们需要将它绑定到我们的中转页或者下载页。
唤端方式
Android
中,不同浏览器对唤起APP有严重的兼容性问题,主要处理方案有以下几种:
1、window.location.href
2、通过创建 iframe 并为其 src 赋值(主要)
3、通过 intent
4、通过制造不可见 a 链接,并触发点击ios
中,不同浏览器对唤起APP有严重的兼容性问题,主要处理方案有以下几种:
1、系统版本在 8 以下时,可以监听页面的 pagehide / visibilitychange 事件。
2、 window.location.href (主要)系统版本大于 8 以后可以 URL scheme 进行跳转。 IOS9 可以使用 universal Link
这里我们结合了两种来处理。
判断唤端是否成功
在浏览器实际上是没有能力判断手机里是否安装了某个App的,所以只能够采取一种投机取巧的方式。APP 如果被唤起的话,页面就会进入后台运行。setInterval 在 ios 中不会停止运行,在 android 中停止运行。
- ios 通过 document.hidden 和 document.webkitHidden 属性来判断 APP 在 ios 中是否被正常唤起,2000ms 内,页面转入后台运行,document.hidden 会返回 true,代表唤端成功,反之则代表失败。
- Android 我们的判断条件比预期时间多设置了 500ms,所以如果安卓中 setInterval 内的函数执行 100 次以内所费时间超过 2500ms,则说明 APP 唤起成功,反之则代表失败。
在JavaScript中判断页面是否进入后台来判断打开成功。Html5提供了下列事件和属性可以利用:
pagehide : 页面隐藏时触发
visibilitychange : 页面隐藏没有在当前显示时触发(切换tab也会触发该事件)
document.hidden : 当页面隐藏时,该值为true,显示时为false1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16const initialTime = new Date();
let counter = 0;
let waitTime = 0;
const checkOpen = setInterval(() => {
count++;
waitTime = new Date() - initialTime;
if (waitTime > 2500) {
clearInterval(checkOpen);
cb();
}
if (counter < 100) return;
const hide = document.hidden || document.webkitHidden;
if (!hide) {
cb(); // 唤端失败的回调函数
}
}, 20);
如果唤端失败(APP 未安装),我们总是要做一些处理的,可以是跳转下载页,可以是 ios 下跳转 App Store… 但是Js 并不能提供给我们获取 APP 唤起状态的能力,Android Intent 以及 Universal Link 倒是不用担心,它们俩的自身机制允许它们唤端失败后直接导航至相应的页面,但是 URL Scheme 并不具备这样的能力,所以我们只能通过一些很 hack 的方式来实现 APP 唤起检测功能。
代码
1 | const browser = { |
注意
1、h5在微信中无法唤醒App,需要“用浏览器打开”
微信对所有的分享连接做了scheme屏蔽,也就是说分享连接中所有对于scheme的调用都被微信封掉了。
在询问是否打开APP的时候,如果选择了“取消”,则再唤起APP的时候会不起作用。目前并没有什么解决方案,在chrome Android,UC Android上会复现问题。需再次刷新页面才行。
在ios手机中,用location.href唤起app,本地如果没装app,会弹窗提示
safari浏览器打不开该网页,网址无效
,后面在用location.href来下载安装包的话也会显示同样的错误,即使你的下载链接是有效的。解决办法:IOS9及以上使用 Universal Links。
问题跨域
前端开发经常面临跨域问题,恩Universal Link也有跨域问题,但不一样的是,Universal Link,必须要求跨域,如果不跨域,就不行,就失效,就不工作。(iOS 9.2之后的改动,苹果就这么规定这么设计的)
这也是上面拿知乎举例子的时候重点强调的一个问题,知乎为什么使用oia.zhihu.com
做Universal Link?
- 假如当前网页的域名是 A
- 当前网页发起跳转的域名是 B
- 必须要求 B 和 A 是不同域名,才会触发Universal Link
- 如果B 和 A 是相同域名,只会继续在当前WebView里面进行跳转,哪怕你的Universal Link一切正常,根本不会打开App
是不是不太好理解,那直接拿知乎举例子
https://www.zhihu.com/question/22914651
知乎的一般网页URL都是www.zhihu.com
域名,你在微信朋友圈看到了知乎的问题分享,如果copy url 你就能看到这样的链接
微信里其实是屏蔽Schema的,但是你依然能看到大大的一个按钮App内打开,这确实就是通过Universal Link来实现的,但如果知乎把Universal Link 配在了www.zhihu.com域名,那么即便已经安装了App,Universal Link也是不会生效的。
一般的公司都会有自己的主域名,比如知乎的www.zhihu.com,在各处分享传播的时候,也都是直接分享基于主域名的url,但为了解决苹果强制要求跨域才生效的问题,Universal Link就不能配置在主域名下,于是知乎才会准备一个oia.zhihu.com域名,专为Universal Link使用,不会跟任何主动传播分享的域名撞车,从而在任何活动WAP页面里,都能顺利让Universal Link生效。
简单一句话
只有当前webview的url域名,与跳转目标url域名不一致时,Universal Link 才生效
Universal Link不是必须通过a标签的href来跳转,我遇到一个问题就是我的页面没有识别Universal Link,因为异步渲染页面,导致没有解析出来Universal Link,加了一个隐藏的a标签,href配置上Universal Link,页面里面所有需要跳转Universal Link都会被识别