测试实现方法
上文介绍了AB测试的基本概念,接下来我们继续探讨如何实现AB测试。
我们先来看一个图:
(注:感谢Algo提供本图。)
上图展示了AB测试的实现原理。从左到右,四条较粗的竖线代表了AB测试中的四个关键角色:客户端(Client)、服务器(Server)、数据层(Data)、数据仓库(DataWarehouse)。从上到下代表了三种访问形式:无AB测试的普通访问流程(NoABtest)、基于后端的AB测试访问流程(BackendABtest)、基于前端的AB测试访问流程(FrontendABtest)。
一般情况下,用户在一次浏览中,会从客户端(Client)发起一个请求,这个请求被传到了服务器(Server),服务器的后台程序根据计算,得出要给用户返回什么内容(Data),同时向数据仓库(DataWarehouse)添加一条打点信息,记录本次访问的相关信息。这个过程也就是图上横向的流程。数据仓库收集到足够的数据之后,就可以开始进行分析(Analytics)了,这也即是图中右上角的部分。
AB测试需要将多个不同的版本展现给不同的用户,即需要一个分流的环节。从上图中我们可以看到,分流可以在客户端做,也可以在服务器端做。传统的AB测试一般是在服务端分流的,即基于后端的AB测试(BackendABtest),当用户的请求到达服务器时,服务器根据一定的规则,给不同的用户返回不同的版本,同时记录数据的工作也在服务端完成。
基于后端的AB测试技术实现上稍微简单一些,不过缺点是需要技术部工程资源介入,另外收集到的数据通常是比较宏观的PV(PageView)信息,虽然可以进行比较复杂的宏观行为分析,但要想知道用户在某个版本的页面上的具体行为往往就无能为力了。
基于前端的AB测试则可以解决上面的问题。它的特点是,利用前端JavaScript方法,在客户端进行分流,同时,可以用JavaScript记录下用户的鼠标行为(甚至键盘行为,如果需要的话),直接发送到对应的打点服务器记录。这样的好处是不需要技术部(如果你们和我们一样,前端工程师与后端工程师分属不同部门的话)参与,并且可以比较精确地记录下用户在页面上的每一个行为,甚至包括后端方法难以记录到的无效点击!
下面,我将重点介绍一下我们在基于前端的AB测试上的一些实践。
一、分流
首先遇到的问题是如何分流的问题。对于大部分需求来说,我们希望各个版本的访问人数平均分配。解决办法有很多种,比较简单的一种即是前面提到过的,根据某一个CookieID来划分用户,前提是你的网站上每一位访客在第一次访问时就要有一个不重复的CookieID,比如123。180。140。。1267882109577。3。然后,可以根据这个CookieID的最后一位(在本例中是3)来划分人群,比如单数的显示A版本,偶数的显示B版本。
因为CookieID一般设定后不会轻易改变,基于CookieID的好处是我们能很好地对访客保持一致性,某个用户如果第一次看到的是A版本,那他刷新后看到的还是A版本,不会一会儿看到A版本一会儿看到B版本。但不足之处就是如果用户浏览器不支持Cookie的话,分流就不能正常进行了。不过,现代浏览器默认情况下都是支持Cookie的,如果真有用户的浏览器不支持Cookie,那也应该是极少数特殊情况,对结果的影响非常微小,对于这些特殊情况,我们一般可以安全地忽略掉。
还有一点需要注意的是,AB测试的页面必须有较高的UV(UniqueVisitor,独立访客数),因为分流带有一定的随机性,如果页面UV太小,分到每一个版本的人数就更少,结果很有可能被一些偶然因素影响。而UV较大时,根据大数定理,我们得到的结果会接近于真实数据。就像想知道一个地方的成年人的平均身高,当然是取的样本越大结论越可信。
二、展示
决定向当前访问者显示哪个版本后,怎么用前端的方法加载对应的版本呢?这需要分情况处理。
一般情况下,如果两个版本只有一个较小的区域不一样,我们可以同时将两个区域的HTML都加载到当前页面中,先用CSS把它们隐藏起来(也可以默认显示一个版本),等JS判断出该显示哪个版本后,再控制对应版本的CSS显示。
有时候,测试区域比较大,代码比较多,或者需要后台较多的计算资源,如果一开始就把两个版本的HTML全加载到当前页面中,就会需要比较大的开销(比如带宽、后台计算量)。这种情况下,我们可以先把测试区留空,之后再用Ajax的方式延迟加载。
还有的时候,测试区域非常大,几乎占了整个页面,或者完全就是不同的页面,这时,用Ajax方式加载也不适合了,可以将不同的版本做成不同的页面,然后再用JS跳转。不过这样的方式并不是很好,因为前端JS跳转需要一定的时间,这个过程很有可能被用户感受到,并且留下不好的体验。对这个问题,似乎没有很好的解决办法,至少在前端层面很难完美解决,所以并不是非常推荐这种跳转方式,如果真的需要跳转,最好是在服务器端由后端代码来操作。
三、数据采集
正确展示对应的版本后,就要开始采集需要的数据了。有一个可选的数据,是当前版本有多少PV(PageViews,访问量),如果需要记录这个数据的话,在正确版本加载完成之时就要发送一个打点信息。不过很多需求中,具体版本的PV的精确数值可能不是很重要,而且要收集这个信息需要多一次打点操作,所以一般情况下这个数据是可选的。
必须的数据是测试区域内用户的点击信息。当用户在测试区域点击了鼠标左键(无论这个点击是点击在链接、文字、图片还是空白处),我们就需要发送一条对应的打点信息到打点服务器。一般来说,这个打点信息至少需要包含以下数据:
当前AB测试以及版本标识
点击事件的位置
点击时间戳(客户端时间)
当前点中的URL(如果点在非超链接区域,此项为空)
用户标识(比如CookieID)
用户浏览器信息
为了尽可能精确地还原用户的点击位置,我们的页面对前端有比较高的要求,要求页面在不同的浏览器下有基本一致的表现,至少在IE6、7、8以及Fiefox下,页面横向的元素要精确一致,纵向上很难做到完全一致,但也要尽可能保持统一。另外,这样的测试也不太适合自适应宽度的页面,比较适合定宽的页面,为了避免不同分辨率下页面左右空白不同导致鼠标点击位置的不同,点击位置取的应该是相对于测试区域左上角的位置。除此之外,最好再记录一下测试区域相对于页面内容左上角的位置,在后面还原点击分布图以及绘制热区图时会用到这个数据。
这一阶段的流程大致如下图所示:
数据打点该如何发送以及如何存储呢?这要取决于你的打点服务器如何存储信息。
四、数据存储
我们使用了一台专用的服务器收集打点信息,为了能支持尽可多尽可能密集的打点请求,这台服务器的apache服务网站目录下只有两个静态文件,分别是abtest。html和abtest。gif,两者都是非常小的空白文件(空白图片)。访客端进行打点时,只需要以GET的方式带上相关的参数请求两个文件中的任意一个即可。比如:
http:abtest。xxx。comabtest。gif?abid1aamp;amp;clickBlockX244amp;amp;clickBlockY372amp;amp;clickBlockW392amp;amp;clickBlockH76amp;amp;clickTime
1263264082137amp;amp;clickRX233amp;amp;clickRY47amp;amp;clickURLamp;amp;clickBeaconID
123。180。140。。1267882109577。3amp;amp;browserTypeFireFox
这个请求可以通过Ajax的方式发送,也可以通过JS在页面上创建newImage()对象的方式完成。
对打点服务器来说,这只是一条普通的HTTP请求,它会在日志里留下一条普通的日志记录,形如:
日韩神仙打架内存又要成为理财产品了在网购江湖之中,有那么一群人。他们的购物车里永远不缺想要买的东西,但他们的下单次数却远没有普通买家的多。他们憧憬着明天肯定降价,嘴上哼着Intel的等,等等等等,永远只会在商品……
心里有些伤感的说说一、是不是我从来不当着你的面哭你就认为我很坚强然后把我往死里伤。二、每一次的被丢下都让我觉得我始终就应该一个人一个人生一个人死不想喜欢任何人不想舍不得任何人我是最嘴硬的那……
老鼠开会猫头鹰常在夜间以迅雷不及掩耳之势捕食老鼠,等老鼠们发现扑来的猫头鹰时已经逃不及了,鼠类们为此苦恼不已,于是老鼠王就召集众鼠聚在一起召开了一个防鹰会议。老鼠王说:在夜间,我……
渐行渐远七七:那是我的半截的诗,不许别人更改一个字。你是我的半截的诗,半截用心爱着,半截用肉体埋着,你是我的半截的诗,不许别人更改一个字。海子‘‘文夕同学,你也喜欢海子……
只爱法圆师妹(一)我是有大男子主义情结的人,我喜欢的女人是小鸟依人型的,温柔款款,善良美好。又不筏坚强与反叛的性格。不要太现实,女人越现实越显得俗气,最好会做点梦的,有点文艺气质的就……
小酒不小经常可以听到朋友约:周末有空没有?一起喝点小酒。朋友不说吃饭,不说聚会,但说小酒。一说小酒,大家就放松了,不必刻意穿着打扮,不必精神紧张。这种放松绝不同于吃业务饭,不同于婚丧嫁……
最常用的电话招聘超级话术大全HR在邀约人才面试中,总会遇到这样的情况:打了电话过去,明明说好都来的,到面试那天来的人却很少,这是为啥呢?原因在于电话招聘话术没有达到多大的效果。那怎么提高电话邀约面试的成功……
女生流行发型更显清爽靓丽棕色的长发松散随意得侧扎成麻花放于胸前,温暖知性。刘海用花饰扎于脑后,干净清爽,又觉风情万种。这是一款女人味十足的长发编发哦!复古风盘发发型,采用麻花编发将头发盘起,简单……
夏季柔顺马尾辫发型清爽时尚长发营造淑女气质这款发型进行了中分的设计,这样两边的刘海都自由的散落下来,营造出了精致的小脸来,并且顺着耳朵的方向将后面的发丝都绑起来形成了一个蓬松的马尾,这样就显得更加的文静了。这款发……
时尚梨花头发型图片优雅整个夏季浅棕色的梨花头更能够衬托女生白皙的肌肤,简约的斜刘海甜美可爱,充满淑女感的内扣梨花烫发打造完美的瓜子脸型。韩式风格,前面斜开刘海,看上去觉得很甜美呢?萌范儿十足!内扣的短……
献给妈妈的菜谱《春暖花开庆三八,妈妈爱我我爱她》。瞧,刚刚进入三月份,我们班的壁报就开始用这个题目征文了。如果选登在壁报上,真的有奖吗?最不爱写稿的穆雷生同学问道。当然!壁报主编……
防晒衣真的可以防晒吗时髦又防晒夏日无负担防晒衣真的可以防晒吗?可以的,但是存在防晒功能高低之分。就像我们买防晒霜要看防晒系数一样,我们买防晒衣的也要要看UPF值的,UPF也就是俗称防晒指数。UPF值越高,对紫外……
搜狗浏览器抢票助手怎么用工具材料aclasstaghrefwiki10351IQEOPLB。html搜狗a浏览器;操作方法01:hr打开最新版本的搜狗浏览器,搜索‘搜狗抢票助手‘并进……
怎样使用手机浏览器收藏网页今天小编要和大家分享的是怎样使用手机QQ浏览器aclasstaghrefwiki10751IQhr1D74。html收藏a网页,希望能够帮助到大家。操作方法01:h……
如何提高自己的口才方法很简单你知道如何aclasstaghrefwiki10728IQESYk736。html提高a自己的口才吗?一起来看看吧操作方法01:hr在我们平时的生活中应该多与人交流……
总有这样两个人从无知到成熟,从牙牙学语,蹒跚学步到善于做事,独力行事,是谁教会我们这一切?是父母。是谁给了我们幸福生活?是父母。没错,从小到大都是父母在照顾,教导我们。是他们让我们懂得坚持,……
洗菜星期六,午饭的时间快到了,我的肚子唱起空城计,心想:妈妈怎么还没下班,不如我帮她分担家务吧。说做就做,我走进厨房,打开冰箱,冰箱里有各种各样的东西,有鸡蛋、鱼肉、牛奶、白……
厉害了我的国随着时代的变迁,技术的发展,我们热爱的祖国中国迎来了全新的面貌。近年来,中国的发展受全世界的关注,也成为了世界上方瞩目的一颗璀璨耀眼的明珠。祖国在七十年的弹指间发生……
美丽的四季在大自然中,美丽的季节给自然添了几分姿色它有时是山清水秀,有的是郁郁葱葱,有的是天高云淡,有时白雪皑皑,有时烈日烈烈像一幅五彩缤纷,千变万化的水彩画一样。春天带着青草的味……
幸福你我他我是一个普通的小学生,过着平凡的生活,但是在生活中也十分快乐,和任何人在一起,都能擦出幸福火花。在家里,爸爸妈妈和我,每周末都有在一起玩耍的亲子时间。有一次,我们一起玩谁……
记一段难忘的记忆今日语文课听了沈宇扬同学的演讲,不禁想起我曾经养宠物的生涯。大约是在刚开学的几周,爸爸突然说要给我带回来一只狗,起初我非常惊喜,因为家里可以多一个新的生命,而等他长大,我……
岁月神偷一眨眼,20年过去了,我从一个上班族打拼成了一家上市公司的总裁。周末在家整理书柜,手中的旧书中掉出了一张老照片,我拾起来一看,那是我小学的毕业照,毕业照下面还有一行字:20年后……
糗人糗事弟弟以前有个坏毛病,但现在他已经改掉了。他的坏毛病可不是一般人有的,是什么呢?一般人放屁后不一定会承认是自己放的,弟弟倒相反,他的坏毛病是对人放屁,对人放屁还不算大事,但……
温暖亲情固然令人温暖,可有一种发自肺腑的同学情谊同样让人感动。早上醒来,揉揉惺松的睡眼,向窗外望去,外面飘着雪花,房上,树上,地上,到处白茫茫的。我愣了一下,昨晚上睡得有那么……