GTM在单页面应用程序中随机跳过初始页面视图

18

我在Google Tag Manager中有一个Pageview标签,用于跟踪SPA页面浏览量,与此指南中描述的相同。基本上它是使用已链接的Google Analytics ID的通用分析,并在历史更改时触发(有些时候也添加了All Pages触发器,但没有成功)。

在我的当前应用程序中,如果所有路由都没有异步解析程序,GTM会跳过初始页面上的Pageview标签。通常情况下,路由仅偶尔触发该标签(5次中的1次),这可能会因条件(缓存与未缓存、localhost与生产环境)而有所不同。

对于具有长时间解析程序(> 1秒)的路由,Pageview标签始终会在初始页面浏览量上触发(5次中的5次)。

在应用程序初始化(pushState)之后,Pageview标签在所有路由上正常触发。

该行为已通过GTM调试控制台和GA实时监视进行确认。

该设置似乎是推荐的,GTM片段<head>中加载,Angular 2应用程序在<body>末尾加载。

<html>
  <head>
    <script>/* Google Tag Manager snippet */</script>
    ...
  </head>

  <body my-app>
    ...
    <script src="my-app-bundle.js"></script>
  </body>
</html>

Angular 2 的启动方式与往常一样:

platformBrowserDynamic().bootstrapModule(MyAppModule);

我已经尝试将GTM代码片段放到各个位置,包括在my-app-bundle.js之前和之后,甚至替换为同步:

Translated:

我已尝试将GTM代码片段放置在各种位置,包括在my-app-bundle.js之前和之后,甚至使用同步方式替换:

<script>
  window.dataLayer = ...
</script>
<script src="https://www.googletagmanager.com/gtm.js?id=..."></script>

使用默认代码片段没有任何区别。

通过试错,我发现如果应用程序在引导时具有显著的延迟,即200-1000毫秒,则Pageviews会在初始页面视图上开始正常工作(起初似乎DOMContentLoaded可以解决问题,但延迟不够):

setTimeout(() => {
  platformBrowserDynamic().bootstrapModule(MyAppModule);
}, 1000);

希望熟悉使用SPA / Angular 2 应用程序的GTM专家能了解这个问题。不幸的是,我无法为此案例提供最小可重现示例,但我相信可以使用具有路由和Google标签管理器帐户的任何Angular 2(2.3.1)应用程序进行复制

通常,Angular 2应用程序可以安全地在<body>结尾处引导。

那里发生了什么以及如何正确处理带有GTM的页面视图跟踪而不会出现竞争条件?


更新:当从GTM切换到直接使用GA时

router.events.subscribe(e => {
  if (e instanceof NavigationEnd)
    ga('send', 'pageview', location.pathname);
})

初始加载和后续页面视图都没有竞争条件,一切正常。


更新2:

以下是成功长时间路由解析的时间轴:gtm.jsmain.bundle.js在开始时加载(无论顺序如何),当路由解析完成并触发Pageview标签(大约10秒后),analytics.js(GA调试器打开时为analytics_debug.js)被加载:


我不确定这是否有助于此情况;但是由于非常相似的问题,必须在NgAfterViewInit中手动呈现google-sign-in按钮。在此库中是否有您可以调用以触发所需行为的手动函数? - BradleyDotNET
很遗憾,不行。看起来A2应用程序应该适应GTM生命周期,而不是相反的方式(目前看起来应该在窗口“加载”时引导应用程序以适应它)。 - Estus Flask
3个回答

1
正如 @kemsky 建议的那样,GTM 生命周期与内部的 gtm.load 事件相关联,该事件发生在 window 的 onload 上。因此,DOMContentLoaded 可能过早进行引导。
考虑到 GTM 脚本是在 SPA 脚本之前加载的,
window.addEventListener('load', () => {
  platformBrowserDynamic().bootstrapModule(MyAppModule);
});

当GTM准备好接收历史更改事件并且不存在竞争条件时,将触发回调函数。


但这将延迟应用程序的引导过程。有没有办法在不影响性能的情况下解决这个问题? - hex
@hex 我猜这有两种方式。另一种方式是黑客攻击GTM源代码,但这不是一个选项。从我的经验来看,延迟可以忽略不计(无论如何都必须切换到GA以避免GTM的开销)。如果由于“window.addEventListener('load' ...)”而出现性能问题,请随时使用您的测量结果进行更新。 - Estus Flask

0

看起来分析脚本是使用<script async=true>加载的:

j.async = true;a.async = 1;

尝试移除async,看看是否有帮助。


1
问题中已经提到过了,“甚至将其替换为同步:”。 - Estus Flask
你已经尝试使用gtm.js,但实际上gtm.js会加载analytics.js,而且它也是异步加载的。看起来你应该要么不使用gtm,要么使用gtm.load事件来启动应用程序。 - kemsky
我不认为事情是这样的。很难相信GTM会那么愚蠢。我已经更新了问题,并附上了截图,证实它并非如此。 GTM按需加载analytics.js。问题不在于GA未加载,而是标签未触发(在GTM调试栏中可以看到)。 - Estus Flask
但你提到了一件有趣的事情。确实,GTM似乎区分了gtm.dom(文档加载?)和gtm.load(窗口加载?)事件。这可能解释了为什么我在使用DOMContentLoaded延迟引导时没有成功。你所说的“使用gtm.load事件启动应用程序”是什么意思? - Estus Flask
你是否有关于 gtm.load DOM 事件的具体信息?window.addEventListener('gtm.load'...document.addEventListener('gtm.load'... 监听器没有被触发。我猜已经将 zone.js 排除在外了,我尝试过将 GTM 加载为页面上的第一个和最后一个脚本。 - Estus Flask
显示剩余2条评论

0

您可以将UA页面视图标签的触发器从普通的“pageview”更改为在NavigationEnd时触发的自定义事件。

router.events.subscribe(e => {
  if (e instanceof NavigationEnd) {
    dataLayer = window.dataL
    dataLayer.push({'event':'custom pageview event'});
  }
})

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