捕获 GA 事件发送失败

Catch ga event send failures

我注意到 ga 发送调用将失败,就像禁用 cookie 时一样 例如 ga('send', 'event', 'Videos', 'play', 'Fall Campaign'); 控制台将显示 'Storage not available. Aborting hit.'

我尝试使用回调 'hitCallback',但成功或失败都会触发。

如何知道 http 调用是否真的通过了?

正在观察 analytics.js 图书馆中的任务

Analytics 库有一些内部验证处理称为任务。如果其中任何一个失败,脚本将抛出中止并取消命中。

任务是:

  • 预览任务
  • 检查协议任务
  • 验证任务
  • 检查存储任务
  • historyImportTask
  • 采样器任务
  • buildHitTask
  • 发送HitTask
  • 计时任务
  • displayFeaturesTask

最有趣的任务是sendHitTask

追踪器回调

我们可以像这样将回调传递给 ga 跟踪器:

ga(function(tracker) {
  var originalHitTask = tracker.get('sendHitTask');   
  tracker.set('sendHitTask', function(model) {
    originalHitTask(model);    
  });
});

当验证任务没有失败时,回调:

function(model) {
    originalHitTask(model);    
}

已处理。

但是如果跟踪失败,则不处理回调。所以我尝试通过 setTimeout 检测这种行为并将 tmp 变量设置为 true 或 false。

元检测

ga(function(tracker) {
   var originalbuildHitTask = tracker.get('sendHitTask');
   var tmp = false;
     setTimeout(function(){
        if(tmp) {
            console.log("Success");
        }
        else {
            console.log("Failure");
        }
    },500);
  tracker.set('sendHitTask', function(model) {
    originalbuildHitTask(model);
    tmp = true;  
  });
});

工作示例

ga('create', 'UA-XXXXX-Y', {
  'cookieDomain' : 'bad.cxf', // set wrong domain, tracking will fail
});

// add task into tracker
ga(function(tracker) {
   var originalbuildHitTask = tracker.get('sendHitTask');
   var tmp = false;
   setTimeout(function(){
    if(tmp) {
      console.log("Success");
    }
    else {
      console.log("Failure");
    }
  },500);
  tracker.set('sendHitTask', function(model) {
    originalbuildHitTask(model);
    tmp = true;  
  });
});

ga('send', "pageview");

结论

这种技术绝对不是最好的,但却是我在互联网上开发和发现的唯一一种。如果有人能够改进它,我将非常高兴。

其他可能的解决方案

检测中止 analytics.js

在分解的分析库中有抛出中止的方法,所以也许有可能直接观察中止:

sc = function(a) {
        if (K(a[0])) this.u = a[0];
        else {
            var b = td.exec(a[0]);
            null != b && 4 == b[y] && (this.c = b[1] || "t0", this.e = b[2] || "", this.d = b[3], this.a = [][ha][C](a, 1), this.e || (this.A = "create" == this.d, this.i = "require" == this.d, this.g = "provide" == this.d, this.ba = "remove" == this.d), this.i && (3 <= this.a[y] ? (this.X = this.a[1], this.W = this.a[2]) : this.a[1] && (qa(this.a[1]) ? this.X = this.a[1] : this.W = this.a[1])));
            b = a[1];
            a = a[2];
            if (!this.d) throw "abort";
            if (this.i && (!qa(b) || "" == b)) throw "abort";
            if (this.g &&
                (!qa(b) || "" == b || !K(a))) throw "abort";
            if (ud(this.c) || ud(this.e)) throw "abort";
            if (this.g && "t0" != this.c) throw "abort";
        }
    };

并且:

function Ja(a) {
    if (100 != a.get(Ka) && La(P(a, Q)) % 1E4 >= 100 * R(a, Ka)) throw "abort";
}

function Ma(a) {
    if (xa(P(a, Na))) throw "abort";
}

function Oa() {
    var a = M[B][E];
    if ("http:" != a && "https:" != a) throw "abort";
}

另一个解决方案可能是访问某些任务并尝试找到一些关于中止命中的指示。