神奇的Cookie互通魔法

kuailejim發表於2019-02-14

有這麼一種業務場景,讓PD們很頭痛。PD們絞盡乳汁想盡一切辦法去引流使用者下載自己設計的App,但是卻無法統計真正使用者的下載量,這樣就無法得出準確的轉化率。有沒有辦法,能統計使用者通過引導頁並且下載完app的真實體量呢?其實在iOS 9之後是可以做到的。

場景分析

使用者通過瀏覽器開啟一個H5頁面,然後通過此H5頁面開啟App Store下載連結。這中間涉及到一個黑盒即App Store下載過程是不可見的,開發者完全感知不到。那麼我們想想有沒有一種方式,能取巧的破解這個難題。

首先從瀏覽器開始分析,瀏覽器即WebView。這裡會有兩種情況:

  • 應用內的UIWebView、WKWebView
  • 應用外的Safari

實際上,雖然很多使用者會在應用內的Webview(下面簡稱WV)開啟引導頁,但是真正的場景下,例如在流量巨頭微信裡頭,並不會機會給你引流到App Store,會將你攔截並且忽視請求(Deep Link是另一個玩意,這裡不做討論)。

OK,所以我們反觀很多引導使用者下載的引導頁,通常會檢測WV的User-Agent,如果判斷不是Safari,通常會引導使用者到Safari開啟這個連結。至此,其實對於需求來說,我們可以先排除應用內的WV,事實上排除這個對接下來的分析很有益處。

技術選型

有了具體的使用場景後,我們就可以分析,並且選出可行性的技術路線了。我們思考一下,其實歸根結到,也就是如何將Safari訪問過引導頁的資料讓開發者感知到,然後傳輸給後臺就完成了。

iOS獨有的沙盒機制,導致如果想直接從Safari傳輸資料給App,是不可能的,更何況我們的App根本沒下載完。如果是在引導頁點選下載完,然後下載完App再跳回H5,接下來在H5再開啟App確實是可以滿足統計的。但是這麼麻煩的步驟,有幾個使用者會遵循,並且不覺得使用者體驗實在是太low了嗎?

OK,回到根本,我們想在使用者毫無感知的情況下,僅僅通過引導頁開啟App Store,並且確認下載動作。

把思路轉向Cookie,說到這裡,每個應用內的WV之間的Cookie是獨立的,不能共享,並且和Safari的Cookie也是獨立的。

這裡思路卡住了,但是iOS 9有一個新東西:SFSafariViewController,它可以在App內用外部的Safari開啟H5,並且與外部Safari共享快取、Cookie等等。但是它卻不能像應用內WV一樣取得Cookie等,因為它沒有Api給你取。

好了,我們已經找到一條路徑,能讓Safari與App共享資料,接下來要解決的就是如何讓Safari將資料傳到App呢。思考一下,可以用scheme的方式喚起App,然後將引數通過URL帶過去。至此,技術過程描述結束。

實現細節

神奇的Cookie互通魔法
流程圖

上面是細節流程圖,實現上首先在Safari開啟引導頁時寫入一段Cookie,然後在App下載完成後,開啟App時通過SFSafariViewController載入引導頁,然後通過window.location.href喚起已經開啟的App(注意:如果在已經開啟的App再通過這種方式喚起,使用者將無感知,而開發者能感知到),這樣就能在AppDelegate中拿到傳進來的URL了。

下面我們來看一下程式碼,首先是一個H5 Demo:

<html>  
   <head>  
    <script type="text/javascript">
    function getCookie()
    {
        if (document.cookie.length>0)
        { 
        return document.cookie.replace("downloadFlag=", ``)
        }
    }

    function setCookie()
    {
        var Days = 30;
        var exp = new Date(); 
        exp.setTime(exp.getTime() + Days*24*60*60*1000);
        document.cookie="downloadFlag=true"+";expires="+exp.toGMTString();
    }

    function checkCookie()
    {
        downloadFlag=getCookie()
        if (downloadFlag=="true")
        {
            window.location.href = "testCookie://downloadFlag"
        }
        else 
        {
            setCookie()
        }
    }
    </script>

    <title>  
       SafariDataToAppDemo
    </title>  
       <meta charset="utf-8">  
   </head>  
   <body onLoad="checkCookie()"> 
<div>  
    SafariDataToAppDemo
</div>  
   </body>  
</html>複製程式碼

大致解釋下這裡做了什麼,在這個Demo中,在載入的時候判斷是否已經存在Cookie,若存在則直接通過window.location.href隱式喚起App,否則寫入Cookie。而在Safari中第一次開啟,會寫入Cookie。

接下來上native程式碼:

#import "ViewController.h"
#import <SafariServices/SafariServices.h>

@interface ViewController ()

@property (nonatomic, strong) SFSafariViewController *sfVC;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    self.sfVC = [[SFSafariViewController alloc] initWithURL:[NSURL URLWithString:@"http://127.0.0.1/test.html"]];
    [self addChildViewController:self.sfVC];
    [self.sfVC didMoveToParentViewController:self];
    [self.sfVC.view setFrame:CGRectMake(0, 0, 200, 200)];
    [self.view addSubview:self.sfVC.view];
}


- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}


@end複製程式碼

這裡就很簡單,載入一個小到使用者看不見的SFSafariViewController,然後偷偷載入H5 Demo,由於共享Cookie的原因,會讀取到有Cookie鍵值對downloadFlag=true,然後就直接window.location.href隱式喚起App了。然後在AppDelegate上傳資訊給後臺吧!

PS:這裡必須得讓SFSafariViewController在當前Window可見,否則iOS將不會載入請求。

這裡還要注意Cookie的失效時間,比如設定10分鐘,20分鐘(增強準確性,如果設定過長,那很有可能使用者通過引導頁開啟過App Store但是不下載,然後很長一段時間後再下載,也許就是通過另一個渠道下載了)。

總結

市面上沒有一個埋點平臺能做到iOS下載統計,並且iOS 9之前的系統佔有率已經很低了,完全可以試試這種方式,而且這種需求是非常旺盛的。

相關文章