如何向没有名称的跟踪器发送 ga 命令?

How to send a ga command to a tracker with no name?

我们有一个自定义 Google 分析插件,它将发送命令来跟踪自定义网页浏览和日志事件。这是我们场景的简化重现:

// Version 1: only works with analytics.js, not with GTM

function GaPlugin(tracker, config) {
    // Simplified for SO, we actually use the config argument
    // to track more interesting pages and events...
    ga(tracker.get('name') + ".send", "pageview", "/virtual/page/view");
}

var ga = window[window["GoogleAnalyticsObject"] || "ga"];

if (typeof ga == "function") {
    ga("provide", "myAnalytics", GaPlugin);
    ga("require", "myAnalytics", { /* omitted for simplicity */ });
}

如果 analytics.js 直接包含在页面上,则此方法工作正常。但是,我们现在使用 Google 标签管理器在页面上包含通用分析。因此我们 运行 陷入了可怕的错误...

Command ignored. Unknown target: undefined

...如 Google Analytics 调试 Chrome 插件中所见,当 require 命令正在执行时。

and this blogpost 暗示需要设置跟踪器名称(在 GTM 中,使用:编辑标签 => 更多设置 => 高级配置 => 设置跟踪器名称复选框)但工具提示显示“在 GTM" 中非常不鼓励使用命名跟踪器。所以我改为这样:

// Version 2: crashes with GTM because ga is loaded after this code

function GaPlugin(tracker, config) {
    // Simplified for SO, we actually use the config argument
    // to track more interesting pages and events...
    ga(tracker.get('name') + ".send", "pageview", "/virtual/page/view");
}

var ga = window[window["GoogleAnalyticsObject"] || "ga"];

if (typeof ga == "function") {
    ga("provide", "myAnalytics", GaPlugin);
    ga(ga.getAll()[0].get("name") + ".require", "myAnalytics", { });
}

但现在我遇到了一个错误,因为当上述执行时 gaundefined,因为 GTM 将异步加载通用分析,我想 运行 我的代码立即 bootstrap 插件。这也意味着我无法在 ga 命令队列上放置回调,因为:它还不存在。

本质上,事情的顺序(我认为)现在是:

  1. GTM 片段开始加载(异步)。
  2. 我自己的javascript代码运行s.
  3. GTM 将开始加载分析(异步)。
  4. 分析已加载并可以使用。

我能想到的唯一解决方法是:

// Version 3: ugly workaround...

function GaPlugin(tracker, config) {
    // Simplified for SO, we actually use the config argument
    // to track more interesting pages and events...
    ga(tracker.get('name') + ".send", "pageview", "/virtual/page/view");
}

var interval = setInterval(function() {
    var ga = window[window["GoogleAnalyticsObject"] || "ga"];

    if (typeof ga == "function" && typeof ga.getAll == "function") {
        ga("provide", "myAnalytics", GaPlugin);
        ga(ga.getAll()[0].get("name") + ".require", "myAnalytics", { });
        clearInterval(interval);
    }
}, 250);

没有更好的方法吗? GTM 文档和 GA 插件文档似乎都没有这方面的信息。


作为脚注,我刚刚意识到,如果我通过自己创建 ga 作为命令队列来模仿 the tracking snippet,它也可能会起作用。但这也感觉像是一种解决方法,而不是解决方案...

不令人满意,但让我分享我的解决方法作为答案,因为它实际上是我现在正在使用的解决方案。它建立在最后的脚注之上:模仿 Google Analytics 引导代码片段的作用。

我正在设置 ga 对象,或者至少是它的 q 属性,我自己:

function createGoogleAnalyticsQueueIfNeeded() {
    // As a workaround for: 
    // We mimick: https://developers.google.com/analytics/devguides/collection/analyticsjs/tracking-snippet-reference
    var gaKey = window["GoogleAnalyticsObject"] || "ga";
    var ga = window[gaKey] || function () {
        (window[gaKey]["q"] = window[gaKey]["q"] || []).push(arguments);
    };
    window[gaKey] = ga;
    return ga;
}

调用上述方法后,您可以在该队列上放置一个命令,只要 GTM 完成加载 GA 就会执行该命令(其中还包括对 运行 插件的优化 all 跟踪器):

var ga = createGoogleAnalyticsQueueIfNeeded();

ga(function() {
    ga("provide", "myAnalytics", GaPlugin);
    ga.getAll().forEach(function(t) {
        ga(t.get("name") + ".require", "myAnalytics", { });
    });
});

Et voila,provide.require 现在调用 运行 每当 GA(通过 GTM 加载)在回调时大喊。