神奇的Cookie互通魔法
<p>有这么一种业务场景,让PD们很头痛。PD们绞尽乳汁想尽一切办法去引流用户下载自己设计的App,但是却无法统计真正用户的下载量,这样就无法得出准确的转化率。有没有办法,能统计用户通过引导页并且下载完app的真实体量呢?其实在iOS 9之后是可以做到的。</p> <h2>场景分析</h2> <p>用户通过浏览器打开一个H5页面,然后通过此H5页面打开App Store下载链接。这中间涉及到一个黑盒即App Store下载过程是不可见的,开发者完全感知不到。那么我们想想有没有一种方式,能取巧的破解这个难题。</p> <p>首先从浏览器开始分析,浏览器即WebView。这里会有两种情况:</p> <ul> <li>应用内的UIWebView、WKWebView</li> <li>应用外的Safari</li> </ul> <p>实际上,虽然很多用户会在应用内的Webview(下面简称WV)打开引导页,但是真正的场景下,例如在流量巨头微信里头,并不会机会给你引流到App Store,会将你拦截并且忽视请求(Deep Link是另一个玩意,这里不做讨论)。</p> <p>OK,所以我们反观很多引导用户下载的引导页,通常会检测WV的User-Agent,如果判断不是Safari,通常会引导用户到Safari打开这个链接。至此,其实对于需求来说,我们可以先排除应用内的WV,事实上排除这个对接下来的分析很有益处。</p> <h2>技术选型</h2> <p>有了具体的使用场景后,我们就可以分析,并且选出可行性的技术路线了。我们思考一下,其实归根结到,也就是如何将Safari访问过引导页的数据让开发者感知到,然后传输给后台就完成了。</p> <p>iOS独有的沙盒机制,导致如果想直接从Safari传输数据给App,是不可能的,更何况我们的App根本没下载完。如果是在引导页点击下载完,然后下载完App再跳回H5,接下来在H5再打开App确实是可以满足统计的。但是这么麻烦的步骤,有几个用户会遵循,并且不觉得用户体验实在是太low了吗?</p> <p>OK,回到根本,我们想在用户毫无感知的情况下,仅仅通过引导页打开App Store,并且确认下载动作。</p> <p>把思路转向Cookie,说到这里,每个应用内的WV之间的Cookie是独立的,不能共享,并且和Safari的Cookie也是独立的。</p> <p>这里思路卡住了,但是iOS 9有一个新东西:SFSafariViewController,它可以在App内用外部的Safari打开H5,并且与外部Safari共享缓存、Cookie等等。但是它却不能像应用内WV一样取得Cookie等,因为它没有Api给你取。</p> <p>好了,我们已经找到一条路径,能让Safari与App共享数据,接下来要解决的就是如何让Safari将数据传到App呢。思考一下,可以用scheme的方式唤起App,然后将参数通过URL带过去。至此,技术过程描述结束。</p> <h2>实现细节</h2> <p style="text-align:center"><img src="https://simg.open-open.com/show/d2cc6c3ec6bdae20312a03e8636b33c0.png"></p> <p>上面是细节流程图,实现上首先在Safari打开引导页时写入一段Cookie,然后在App下载完成后,打开App时通过SFSafariViewController加载引导页,然后通过window.location.href唤起已经打开的App(注意:如果在已经打开的App再通过这种方式唤起,用户将无感知,而开发者能感知到),这样就能在AppDelegate中拿到传进来的URL了。</p> <p>下面我们来看一下代码,首先是一个H5 Demo:</p> <pre> <code class="language-objectivec"><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> </code></pre> <p>大致解释下这里做了什么,在这个Demo中,在加载的时候判断是否已经存在Cookie,若存在则直接通过window.location.href隐式唤起App,否则写入Cookie。而在Safari中第一次打开,会写入Cookie。</p> <p>接下来上native代码:</p> <pre> <code class="language-objectivec">#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 </code></pre> <p>这里就很简单,加载一个小到用户看不见的SFSafariViewController,然后偷偷加载H5 Demo,由于共享Cookie的原因,会读取到有Cookie键值对downloadFlag=true,然后就直接window.location.href隐式唤起App了。然后在AppDelegate上传信息给后台吧!</p> <p>PS:这里必须得让SFSafariViewController在当前Window可见,否则iOS将不会加载请求。</p> <p>这里还要注意Cookie的失效时间,比如设置10分钟,20分钟(增强准确性,如果设置过长,那很有可能用户通过引导页打开过App Store但是不下载,然后很长一段时间后再下载,也许就是通过另一个渠道下载了)。</p> <h2>总结</h2> <p>市面上没有一个埋点平台能做到iOS下载统计,并且iOS 9之前的系统占有率已经很低了,完全可以试试这种方式,而且这种需求是非常旺盛的。</p> <p> </p> <p>来自:http://kuailejim.com/2017/03/06/神奇的Cookie互通魔法/</p> <p> </p>
本文由用户 aassbab1 自行上传分享,仅供网友学习交流。所有权归原作者,若您的权利被侵害,请联系管理员。
转载本站原创文章,请注明出处,并保留原始链接、图片水印。
本站是一个以用户分享为主的开源技术平台,欢迎各类分享!