最近總接到落地頁的需求店枣,落地頁的職責(zé)主要是引流速警,有以下幾種類型
1、引導(dǎo)已經(jīng)下載App的用戶打開App
2鸯两、引導(dǎo)未下載App的用戶下載App
3闷旧、引導(dǎo)未注冊的用戶注冊
4、引導(dǎo)已經(jīng)注冊的用戶進(jìn)入我們的主頁或者其他的操作
從數(shù)據(jù)上可以體現(xiàn)在用戶停留在App的時(shí)間多了钧唐,或者增加了用戶量
喚起App主要的媒介是什么呢忙灼?
URL Scheme
URL Scheme的組成
[scheme:][//authority][path][?query][#fragment]
App | 微信 | 支付寶 | 淘寶 | 微博 |
---|---|---|---|---|
URL Scheme | weixin:// | alipay:// | taobao:// | sinaweibo:// |
行為(應(yīng)用的某個(gè)功能)
|
scheme://[path][?query]
| |
應(yīng)用標(biāo)識 功能需要的參數(shù)
URL Scheme 在 ios 9+ 上諸如 safari、UC、QQ瀏覽器中该园, iframe 均無法成功喚起 APP酸舍,只能通過 window.location 才能成功喚端。
Intent
安卓的原生谷歌瀏覽器自從 chrome25 版本開始對于喚端功能做了一些變化里初,URL Scheme 無法再啟動(dòng)Android應(yīng)用啃勉。 例如,通過 iframe 指向 weixin://双妨,即使用戶安裝了微信也無法打開淮阐。所以,APP需要實(shí)現(xiàn)谷歌官方提供的 intent: 語法斥难,或者實(shí)現(xiàn)讓用戶通過自定義手勢來打開APP枝嘶。
安卓版本 4.4.4 以上機(jī)型的安卓自帶瀏覽器、chrome 瀏覽器哑诊,需要通過 intent 跳轉(zhuǎn)
intents文檔
- Intent 語法
intent:
HOST/URI-path // Optional host
#Intent;
package=[string];
action=[string];
category=[string];
component=[string];
scheme=[string];
end;
如果用戶未安裝 APP群扶,則會跳轉(zhuǎn)到系統(tǒng)默認(rèn)商店。當(dāng)然镀裤,如果你想要指定一個(gè)喚起失敗的跳轉(zhuǎn)地址竞阐,添加下面的字符串在 end; 前就可以了:
S.browser_fallback_url=[encoded_full_url]
- 示例
下面是打開 Zxing 二維碼掃描 APP 的 intent。
intent:
//scan/
#Intent;
package=com.google.zxing.client.android;
scheme=zxing;
end;
<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
傳統(tǒng)的 Scheme 鏈接有以下幾個(gè)痛點(diǎn):
- 在 ios 上會有確認(rèn)彈窗提示用戶是否打開暑劝,對于用戶來說喚端骆莹,多出了一步操作。若用戶未安裝 APP 担猛,也會有一個(gè)提示窗幕垦,告知我們 “打不開該網(wǎng)頁,因?yàn)榫W(wǎng)址無效”
- 傳統(tǒng) Scheme 跳轉(zhuǎn)無法得知喚端是否成功傅联,Universal Link 喚端失敗可以直接打開此鏈接對應(yīng)的頁面
- Scheme 在微信先改、微博、QQ瀏覽器蒸走、手百中都已經(jīng)被禁止使用仇奶,使用 Universal Link 可以避開它們的屏蔽( 截止到 18年8月21日,微信和QQ瀏覽器已經(jīng)禁止了 Universal Link比驻,其他主流APP未發(fā)現(xiàn)有禁止 )
如何讓 APP 支持 Universal Link
有大量的文章會詳細(xì)的告訴我們?nèi)绾闻渲酶盟荩阋部梢匀タ?a target="_blank">官方文檔,我這里簡單的寫一個(gè)12345别惦。
- 擁有一個(gè)支持 https 的域名
- 在 開發(fā)者中心 狈茉,Identifiers 下 AppIDs 找到自己的 App ID,編輯打開 Associated Domains 服務(wù)掸掸。
- 打開工程配置中的 Associated Domains 氯庆,在其中的 Domains 中填入你想支持的域名,必須以
applinks:
為前綴 - 配置
apple-app-site-association
文件,文件名必須為apple-app-site-association
点晴,不帶任何后綴 - 上傳該文件到你的 HTTPS 服務(wù)器的 根目錄 或者
.well-known
目錄下
Universal Link 配置中的坑
這里放一下我們在配置過程中遇到的坑,當(dāng)然首先你在配置過程中必須得嚴(yán)格按照上面的要求去做悯周,尤其是加粗的地方粒督。
- 域名問題
Universal Link 支持的域名最多只能支持到二級域名,如果你用到了三級域名禽翼,Universal Link 喚端是不會生效的屠橄。
- 跨域問題
IOS 9.2 以后,必須要觸發(fā)跨域才能支持 Universal Link 喚端闰挡。
IOS 那邊有這樣一個(gè)判斷锐墙,如果你要打開的 Universal Link 和 當(dāng)前頁面是同一域名,ios 尊重用戶最可能的意圖长酗,直接打開鏈接所對應(yīng)的頁面溪北。如果不在同一域名下,則在你的 APP 中打開鏈接夺脾,也就是執(zhí)行具體的喚端操作之拨。
- Universal Link 是空頁面
Universal Link 本質(zhì)上是個(gè)空頁面,如果未安裝 APP咧叭,Universal Link 被當(dāng)做普通的頁面鏈接蚀乔,自然會跳到 404 頁面,所以我們需要將它綁定到我們的中轉(zhuǎn)頁或者下載頁菲茬。
喚端方式
Android
中,不同瀏覽器對喚起APP有嚴(yán)重的兼容性問題,主要處理方案有以下幾種:
1灶似、window.location.href
2幻林、通過創(chuàng)建 iframe 并為其 src 賦值(主要)
3、通過 intent
4马胧、通過制造不可見 a 鏈接汉买,并觸發(fā)點(diǎn)擊ios
中,不同瀏覽器對喚起APP有嚴(yán)重的兼容性問題佩脊,主要處理方案有以下幾種:
1蛙粘、系統(tǒng)版本在 8 以下時(shí),可以監(jiān)聽頁面的 pagehide / visibilitychange 事件威彰。
2出牧、 window.location.href (主要)
系統(tǒng)版本大于 8 以后可以 URL scheme 進(jìn)行跳轉(zhuǎn)。 IOS9 可以使用 universal Link
這里我們結(jié)合了兩種來處理歇盼。
判斷喚端是否成功
在瀏覽器實(shí)際上是沒有能力判斷手機(jī)里是否安裝了某個(gè)App的舔痕,所以只能夠采取一種投機(jī)取巧的方式。APP 如果被喚起的話,頁面就會進(jìn)入后臺運(yùn)行伯复。setInterval 在 ios 中不會停止運(yùn)行慨代,在 android 中停止運(yùn)行。
- ios 通過 document.hidden 和 document.webkitHidden 屬性來判斷 APP 在 ios 中是否被正常喚起啸如,2000ms 內(nèi)侍匙,頁面轉(zhuǎn)入后臺運(yùn)行,document.hidden 會返回 true叮雳,代表喚端成功想暗,反之則代表失敗。
- Android 我們的判斷條件比預(yù)期時(shí)間多設(shè)置了 500ms帘不,所以如果安卓中 setInterval 內(nèi)的函數(shù)執(zhí)行 100 次以內(nèi)所費(fèi)時(shí)間超過 2500ms说莫,則說明 APP 喚起成功,反之則代表失敗寞焙。
在JavaScript中判斷頁面是否進(jìn)入后臺來判斷打開成功储狭。Html5提供了下列事件和屬性可以利用:
pagehide : 頁面隱藏時(shí)觸發(fā)
visibilitychange : 頁面隱藏沒有在當(dāng)前顯示時(shí)觸發(fā)(切換tab也會觸發(fā)該事件)
document.hidden : 當(dāng)頁面隱藏時(shí),該值為true捣郊,顯示時(shí)為false
const 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(); // 喚端失敗的回調(diào)函數(shù)
}
}, 20);
如果喚端失斁堋(APP 未安裝),我們總是要做一些處理的模她,可以是跳轉(zhuǎn)下載頁稻艰,可以是 ios 下跳轉(zhuǎn) App Store… 但是Js 并不能提供給我們獲取 APP 喚起狀態(tài)的能力,Android Intent 以及 Universal Link 倒是不用擔(dān)心侈净,它們倆的自身機(jī)制允許它們喚端失敗后直接導(dǎo)航至相應(yīng)的頁面尊勿,但是 URL Scheme 并不具備這樣的能力,所以我們只能通過一些很 hack 的方式來實(shí)現(xiàn) APP 喚起檢測功能畜侦。
代碼
const browser = {
getBrowser: function() {
var u = navigator.userAgent,
app = navigator.appVersion;
return {
trident: u.indexOf('Trident') > -1, //IE內(nèi)核
presto: u.indexOf('Presto') > -1, //opera內(nèi)核
webKit: u.indexOf('AppleWebKit') > -1, //蘋果元扔、谷歌內(nèi)核
gecko: u.indexOf('Gecko') > -1 && u.indexOf('KHTML') == -1, //火狐內(nèi)核
opera: u.indexOf('Opera') > -1,
chrome: u.indexOf('Chrome') > -1,
firefox: u.indexOf('Firefox') > -1,
safari: u.indexOf('Safari') > -1, //注意chrome瀏覽器此項(xiàng)也為true,非chrome且此項(xiàng)為true則可確定為Safari
ie: u.indexOf('compatible') > -1 && u.indexOf('MSIE') > -1 && u.indexOf('Gecko') == -1,
mobile: u.search(/AppleWebKit.*Mobile/) > -1, //是否為移動(dòng)終端
ios: u.search(/\(i[^;]+;( U;)? CPU.+Mac OS X/) > -1, //ios終端
android: u.indexOf('Android') > -1 || u.indexOf('Adr') > -1, //android終端
winPhone: u.search(/Windows Phone/) > -1, //windows phone終端
iPhone: u.indexOf('iPhone') > -1, //是否為iPhon
iPad: u.indexOf('iPad') > -1, //是否iPad
webApp: u.indexOf('Safari') == -1, //是否Safari web應(yīng)該程序旋膳,沒有頭部與底部
weibo: u.search(/WeiBo/i) > -1, //是否微博
weixin: u.search(/MicroMessenger/i) > -1, //是否微信
qq: u.search(/\sQQ/i) > -1, //是否QQ
mQQ: u.search(/MQQBrowser/) > -1, //是否QQ手機(jī)瀏覽器
uc: u.search(/UCBrowser/) > -1 //是否UC瀏覽器
};
}(),
getIOSVersion: function getIOSVersion() {
const verion = navigator.appVersion.match(/OS (\d+)_(\d+)_?(\d+)?/);
return parseInt(verion[1], 10);
}()
}
/**
* [evokeApp 喚起APP]
* @param {[Object]} config [跳轉(zhuǎn)的URL]
* config.ios.url {[String]} [iOS跳轉(zhuǎn)的URL]
* config.ios.data {[String]} [iOS URL參數(shù)]
* config.ios.callback {[function]} //android的回掉如果沒有下載app就執(zhí)行操作
* config.android.url {[String]} [android跳轉(zhuǎn)的URL]
* config.android.data {[String]} [android URL參數(shù)]
* config.android.callback {[function]} //android的回掉如果沒有下載app就執(zhí)行操作
*/
const evokeApp = (config) =>{
//對微信澎语,微博,qq做處理彈窗
if (browser.versions.weibo || browser.versions.weixin || browser.versions.qq) {
return;
}
//
let browserVersions = browser.versions;
let evokeAppURL = '';
let cb;
if (browserVersions.ios) {
evokeAppURL = config.ios.data ? 'authority://' + config.ios.url + '?' + config.ios.dataArr.join('&') : 'authority://' + config.ios.url;
cb = config.ios.callback;
} else if (browserVersions.android) {
evokeAppURL = config.android.data ? 'authority://' + config.android.url + '?' + config.android.dataArr.join('&') : 'authority://' + config.android.url;
cb = config.android.callback;
};
const initialTime = new Date();
let counter = 0;
let waitTime = 0;
const checkOpen = setInterval(() => {
count++;
waitTime = new Date() - initialTime;
if (waitTime > 2500) {
clearInterval(checkOpen);
cb && cb();
}
if (counter < 100) return;
const hide = document.hidden || document.webkitHidden;
if (!hide) {
cb && cb(); // 喚端失敗的回調(diào)函數(shù)
}
}, 20);
}
注意
1验懊、h5在微信中無法喚醒App擅羞,需要“用瀏覽器打開”
微信對所有的分享連接做了scheme屏蔽,也就是說分享連接中所有對于scheme的調(diào)用都被微信封掉了义图。
在詢問是否打開APP的時(shí)候减俏,如果選擇了“取消”,則再喚起APP的時(shí)候會不起作用碱工。目前并沒有什么解決方案娃承,在chrome Android,UC Android上會復(fù)現(xiàn)問題奏夫。需再次刷新頁面才行。
在ios手機(jī)中历筝,用location.href喚起app酗昼,本地如果沒裝app,會彈窗提示
safari瀏覽器打不開該網(wǎng)頁梳猪,網(wǎng)址無效
仔雷,后面在用location.href來下載安裝包的話也會顯示同樣的錯(cuò)誤,即使你的下載鏈接是有效的舔示。解決辦法:IOS9及以上使用 Universal Links。