I have Pageview
tag in Google Tag Manager that tracks SPA pageviews, identical to the one described in this guide. Basically it is Universal Analytics with linked Google Analytics ID that is triggered on History Change (at some point All Pages
trigger was also added with no success).
In my current app GTM skips Pageview
tag on initial pageviews on all routes that don't have async resolvers. Usually the routes fire the tag sometimes (1 of 5 times), this may vary a bit depending on conditions (cached vs uncached, localhost vs production).
On the routes that have resolvers with long durations (> 1s) Pageview
tag is always fired on initial pageviews (5 of 5 times).
Pageview
tag is fired normally on all routes after app initialization (pushState
).
This behaviour was confirmed with GTM debug console and GA realtime monitoring.
The setup seems to be the recommended one, GTM snippet is loaded in <head>
, Angular 2 app is loaded at the end of <body>
.
<html>
<head>
<script>/* Google Tag Manager snippet */</script>
...
</head>
<body my-app>
...
<script src="my-app-bundle.js"></script>
</body>
</html>
And Angular 2 is bootstrapped like usual:
platformBrowserDynamic().bootstrapModule(MyAppModule);
I've tried to move GTM snippet all around, before and after my-app-bundle.js
, even replace it with synchronous:
<script>
window.dataLayer = ...
</script>
<script src="https://www.googletagmanager.com/gtm.js?id=..."></script>
There was no difference with default snippet.
I've found by trial and error that Pageviews
start to work normally on initial pageviews if the app is bootstrapped with considerable delay, 200-1000ms (it seemed at first that DOMContentLoaded
does the trick but the delay wasn't enough):
setTimeout(() => {
platformBrowserDynamic().bootstrapModule(MyAppModule);
}, 1000);
I hope that this problem is familiar to the experts who've done GTM with SPA/Angular 2 applications. Unfortunately, I cannot provide MCVE for this case but I believe it can be replicated with any Angular 2 (2.3.1) app with routing and Google Tag Manager account.
Usually Angular 2 apps can be safely bootstrapped at the end of <body>
.
What is going on there and how pageview tracking should be properly handled with GTM without race conditions?
UPDATE: When switching from GTM to using GA directly with
router.events.subscribe(e => {
if (e instanceof NavigationEnd)
ga('send', 'pageview', location.pathname);
})
everything works fine on initial and subsequent pageviews with no race conditions.
UPDATE 2:
Here's a timeline of how it looks in the case of success with long-running route resolver, gtm.js
and main.bundle.js
are loaded in the beginning (it doesn't matter in which order), analytics.js
(analytics_debug.js
when GA Debugger is on) is loaded when route resolver completes and Pageview
tag is fired, i.e. after ~10s:
load
to fit it). – Convalescent