使用JavaScript记录用户数据以生成热图

40
我想知道像crazyegg.com这样的网站如何在会话期间存储用户点击数据。显然,有一些底层脚本正在存储每个点击的数据,但是这些数据是如何填充到数据库中的呢?我觉得简单的解决方案是通过AJAX发送数据,但是考虑到几乎不可能设置跨浏览器页面卸载函数,我想知道是否存在其他更先进的获取度量数据的方法。
我甚至看到一个记录每个鼠标移动的网站,我猜他们肯定不会在每个鼠标移动事件上将数据发送到数据库。
简而言之,要监视用户在我的网站上的活动并存储此信息以创建度量数据,我需要什么样的技术?我不想重新创建GA,我只是非常想知道这种事情是如何完成的。
提前致谢。
5个回答

41

热力图分析比捕捉鼠标坐标要复杂得多。一些网站是右对齐的,一些是左对齐的,一些是100%宽度的,一些是固定宽度“居中对齐”的...... 页面元素可以绝对或相对定位,浮动等等。哦,还有不同的屏幕分辨率甚至是多显示器配置。

以下是 HeatTest 的工作原理(我是创始人之一,根据规则必须透露):

  1. JavaScript 处理 onClick 事件:document.onclick = function(e){ } (这不适用于元素,必须找到解决方法)
  2. 脚本记录所点击元素的 XPath 地址(因为坐标不可靠,请见上文)以及元素内的坐标。
  3. 脚本向服务器发送 JSONP 请求(由于浏览器的跨域限制而使用 JSONP)
  4. 服务器将此数据记录到数据库中。

现在,有趣的部分 - 服务器。

  1. 为计算热力图,服务器会在内存中启动一个虚拟的浏览器实例(我们使用 Chromium 和 IE9)
  2. 渲染页面
  3. 截屏
  4. 找到元素的坐标,然后构建热力图。

这需要大量的 CPU 力和内存使用。非常多。因此,包括我们和 CrazyEgg 在内的大多数热力图服务都有一堆虚拟机器和云服务器用于此任务。


你能详细说明一下 #1 吗?为什么它不能在可点击的元素上工作,比如 input/a 等? - Eugene M.
1
@EugeneMyunster 抱歉刚看到你的评论。它不能与<a>一起使用,因为浏览器会跟随链接! :) 并卸载页面。所以你没有时间完成执行脚本的操作。 顺便说一句,我们现在已经“日落”了这个项目。 - Alex from Jitbit
我认为如果有人使用了stopPropagation,它也不会起作用,你同样可以监听所有事件吗?所有的事件监听器(click、mousemove等)都只放在document上吗?我问这个问题是因为在面试中被问到过,当我谈到这种方法时,面试官说这不是我想要的,所以我相信有一种更有效的方法来跟踪所有事件。 - darKnight

32

许多跟踪系统使用一个带有额外GET参数的1x1像素图像的基本想法。请求被添加到服务器日志文件中,然后处理日志文件以生成一些统计信息。 因此,极简的点击跟踪函数可能如下所示:

document.onclick = function(e){
  var trackImg = new Image();
  trackImg.src = 'http://tracking.server/img.gif?x='+e.clientX+'&y='+e.clientY;
}
由于同源策略的限制,AJAX不会很有用(您将无法向跟踪服务器发送请求)。而且,您需要在跟踪脚本中添加AJAX代码。 如果您想要发送更多数据(例如光标移动),则可以将坐标存储在变量中,并定期轮询带有更新路径的新图像的GET参数。
现在存在许多问题:
- 跨浏览器兼容性 - 要使上面的函数在目前所有重要的浏览器中正常工作,您可能还需要添加20行代码 - 获取有用数据
- 许多页面都是固定宽度、居中的,因此原始的X和Y坐标无法让您创建页面上点击的可视化叠加效果 - 有些页面具有液态宽度元素,或使用最小和最大高度的组合 - 用户可能使用不同的字体大小 - 在响应用户操作时出现在页面上的动态元素
- 等等。
当您完成跟踪脚本后,您只需要创建一个工具,将原始服务器日志转换成闪亮的热力图即可 :)

7
我不知道crazyegg的具体实现细节,但我会将鼠标事件存储在数组中,并定期通过AJAX发送到后端。例如,捕获的鼠标事件每30秒收集并发送到服务器。这样可以减轻创建每个事件请求的负担,同时也确保最多只会丢失30秒的数据。您还可以将发送添加到卸载事件中,这会增加您获取的数据量,但您不会依赖它。
以下是我如何实现它的示例(使用jQuery作为我的纯JS技能有点生疏):
$(function() {

    var clicks = [];

    // Capture every click
    $().click(function(e) {
        clicks.push(e.pageX+','+e.pageY);
    });

    // Function to send clicks to server
    var sendClicks = function() {
        // Clicks will be in format 'x1,y1;x2,y2;x3,y3...'
        var clicksToSend = clicks.join(';');
        clicks = [];
        $.ajax({
            url: 'handler.php',
            type: 'POST',
            data: {
                clicks: clicksToSend
            }
        });
    }

    // Send clicks every 30 seconds and on page leave
    setInterval(sendClicks, 30000);
    $(window).unload(sendClicks);
});

请注意,我没有以任何方式测试或尝试过这个,但这应该给你一个大致的想法。

2
如果你只是想实现交互,你可以将 <input type="button"> 替换为 <input type="image">。这些元素会自动提交用户点击时的 X 和 Y 坐标。
jQuery 也提供了一个良好的 mousemove 事件绑定 实现,可以跟踪当前鼠标位置。我不知道你希望最终达到什么目标,但你可以使用 setTimeOut(submitMousePosition, 1000) 每秒发送一次带有鼠标位置的 Ajax 请求。

1

我真的不明白为什么你认为将所有点击点存储到一个用户会话中的数据库是不可能的。

他们的座右铭是“看人们如何点击”。一旦收集足够的数据,批处理中制作热图就变得相当容易了。

人们真的低估了数据库、索引和分片。唯一困难的事情就是为基础架构筹集足够的资金 :)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接