【问题标题】:How dangerous is e.preventDefault();, and can it be replaced by keydown/mousedown tracking?e.preventDefault(); 有多危险,可以用 keydown/mousedown 跟踪代替吗?
【发布时间】:2011-05-31 21:00:20
【问题描述】:

我正在为一个相当复杂的 CRM 编写跟踪脚本,用于跟踪 Google Analytics 中的表单操作。我试图平衡准确跟踪表单操作的愿望与需要永远不会阻止表单不工作。

现在,我知道这样做是行不通的。

$('form').submit(function(){
 _gaq.push(['_trackEvent', 'Form', 'Submit', $(this).attr('action')]);
});

DOM 在有机会处理之前卸载。

所以,很多示例代码都推荐这样的东西:

$('form').submit(function(e){
e.preventDefault();
var form = this; 
 _gaq.push(['_trackEvent', 'Form', 'Submit', $(this).attr('action')]);
//...do some other tracking stuff...
setTimeout(function(){
form.submit();
}, 400);
});

这在most cases 中是可靠的,但它让我感到紧张。如果在e.preventDefault(); 和我开始触发基于 DOM 的提交之间发生了什么事怎么办?我完全破坏了表格。

我一直在探索其他一些分析实现,我注意到something like this

$('form').mousedown(function(){
 _gaq.push(['_trackEvent', 'Form', 'Submit', $(this).attr('action')]);
});
$('form').keydown(function(e){
    if(e.which===13) //if the keydown is the enter key
    _gaq.push(['_trackEvent', 'Form', 'Submit', $(this).attr('action')]);
});

基本上,与其中断表单提交,不如通过假设有人按下鼠标或按下 Enter 键来抢占它,然后提交该表单。显然,这会导致一定数量的误报,但它完全消除了e.preventDefault(); 的使用,在我看来,这消除了我可能会阻止表单成功提交的风险。

所以,我的问题:

  • 是否可以采取标准 形成跟踪 sn-p 并防止它 从 ever 完全阻止表单 从提交?
  • 是 mousedown/keydown 替代方案可行吗?
  • 是否有可能遗漏的提交案例?具体来说,除了鼠标和键盘输入,还有其他的提交方式吗?在开始卸载页面之前,浏览器是否总是有时间处理 javascript?

【问题讨论】:

    标签: javascript jquery google-analytics analytics jquery-events


    【解决方案1】:

    Googleplex 那边的那些家伙非常聪明,他们认为总有一天会发生这样的事情,现在,果然,它已经发生了。为什么不好好尝试一下:

    $('form').submit(function(e){
      e.preventDefault();
      var form = this; 
      _gaq.push(['_trackEvent', 'Form', 'Submit', $(this).attr('action')]);
      //...do some other tracking stuff...
      _gaq.push(function(){
         form.submit();
        });
      });
    

    _gaq.pushthigamajigger 按顺序执行它的元素,所以你应该开玩笑。

    不,我不知道为什么我突然开始这样说话。

    【讨论】:

    • 嗯,让我再试一次。仅等待任意时间并假设现在可以安全离开页面的解决方案 保证 (a) 浪费用户时间或 (b) 提前离开而失败(您每次都能正确猜到的几率可以忽略不计)。相反,您需要一种技术,以便在跟踪完成时通知您。幸运的是,Google Analytics Queue 提供了:您所要做的就是在队列末尾推送一个函数对象。一旦队列中前面的所有内容都完成,该函数将被执行并提交您的表单。
    • 我现在意识到您可能还担心“某些跟踪内容”失败,从而导致表单永远无法提交。为此,您的两个选择是,将除提交之外的所有代码包装在一个 try-except 块中,这对于马虎来说是安全的,或者简单地在函数的最后一行之前不要调用 preventDefault ,所以如果有错误,它会赢' 不被调用并且提交应该仍然通过,这很优雅但应该仔细测试。
    • _gaq.push((function(){ 应该是_gaq.push(function(){
    【解决方案2】:

    我使用不同的方法,并在提交的页面中生成事件跟踪脚本。您可以将其称为延迟事件跟踪

    我写了一封blog post,详细介绍了我在后端操作中进行事件跟踪的方法。它偏向于 Java-Struts,但您可以大致了解一下。

    理由是我想在服务器端发生一些事情后对其进行跟踪。在这种情况下,表单被服务器提交并处理后。

    我所做的(非常概括):

    • 将事件存储在与会话相关的对象(列表/队列)中
    • 在下一页呈现时刷新这些事件(生成 javascript 并清空队列)

    【讨论】:

      【解决方案3】:

      如果您必须让表单始终有效,但如果绝对必要,可以牺牲跟踪,您可以尝试/捕获它。

      $('form').submit(function(e){
          try{
              e.preventDefault();
              var form = this; 
               _gaq.push('_trackEvent', 'Form', 'Submit', $(this).attr('action'));
              //...do some other tracking stuff...
              setTimeout(function(){
                  form.submit();
              }, 400);
          } catch (e) {
              form.submit();
          }
      });
      

      【讨论】:

      • 针对同样的问题实施了这个解决方案并且运行良好。谢谢。谷歌在表单提交和事件跟踪方面存在问题的确切原因是什么?起初我认为这是由于表单提交发生和页面重新加载太快而无法将数据发送到 Google,但即使我添加了 setTimeout 逻辑,它仍然会发生。只有当我添加了e.preventDefault 调用后,一切才重新开始工作。
      • 设置超时只是故事的一半。如果您为表单提交设置了超时,但没有 e.preventDefault,那么您将让表单提交立即发生(作为事件的默认设置),这仍然会抢占对分析的调用。
      【解决方案4】:

      e.preventDefault() 不必在函数调用的开头。为什么不只使用if 语句来验证一切是否正常工作,并且只在正常情况下调用e.preventDefault()。如果链中的任何函数未返回预期结果,请将submitted 变量设置为false,并且不要阻止默认值。

      当涉及到任何异步时(例如您的setTimeout,这可能会有点难以处理,但是有一些方法可以相当确定,具体取决于您的代码的样子。所以您可以检查 if 方法与if (_gaq.push) 一起存在(例如)。如果不测试每个浏览器中的每一个组合,您就无法 100% 确定,但我认为您可以通过此获得非常满意的结果。

      【讨论】:

        【解决方案5】:

        另一种方法:

        var pageTracker;
        _gaq.push(function() {
            pageTracker = _gat._getTrackerByName();
        });
        
        $('form').submit(function(e){
            pageTracker._trackEvent('Form', 'Submit', $(this).attr('action'));
        };
        

        我猜想这种方式 _trackEvent 会是同步的,但我还没有测试过。

        【讨论】:

        • GA 异步不是问题。异步方面是指最初加载脚本,而不是后续调用。加载 ga.js 后,_gaq.push('_trackEvent',...) 调用的执行速度与pageTracker._trackEvent(...) 一样快
        • 如果是这种情况,您可以考虑编写自己的 trackEvent 函数,并将 onload 处理程序附加到 __utm.gif 图像,但是我认为图像的 onload 处理程序在某些浏览器中不是那么可靠(例如当从缓存加载时不会触发,但在这种情况下永远不应该从缓存加载)。一个旧的 pageTrack 函数:code.google.com/p/google-analytics-js/source/browse/trunk/…
        【解决方案6】:

        您是否有理由不能根据接收到的 POST 从服务器端向 Google Analytics 发出调用?

        我不知道你的系统是内置什么的,比如这个PHP项目会调用GA,这样就解决了DOM卸载问题,需要破坏表单等等。

        http://code.google.com/p/serversidegoogleanalytics/

        我知道您可能需要捕获一个 cookie - 您可能会在提交之前将值写入表单中的隐藏字段?

        【讨论】:

        • 这可能适用于某些人,但不幸的是,在这个 CMS 环境中,我无法访问服务器端脚本。一切都需要在 JavaScript 中完成。
        • 即使你可以,也在为服务器付费;您的数百万客户都带来了自己的客户。
        • 为了后代:此答案中链接的项目已退役;而是查看较新的项目code.google.com/p/php-ga
        【解决方案7】:

        扩展@Malvolio 的回答: 一旦 gaq 发送事件,队列中的下一个项目将被处理。这意味着事件 HTTP 请求可能会在客户端中止,但 GA 将接收该请求。在响应完成之前,不要担心阻止脚本执行。这是一个一劳永逸的场景。

        【讨论】:

          猜你喜欢
          • 2019-04-26
          • 1970-01-01
          • 1970-01-01
          • 2018-10-17
          • 2011-12-31
          • 1970-01-01
          • 2013-06-16
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多