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:
Sometimes a tag is not firing where it should because of multiple triggers or multiple rules within a trigger. The Solution: As all tags fire as a result of trigger configurations, this is normally the best place to start when tags are not firing as intended. Start by double checking your trigger settings.
In order to track clicks on a form submit button via virtual pageviews in GTM, you need to do the following: #1 Find the web page which contains the form and note down the URL. #2 Find the ID attribute of the form. #3 Create a trigger in GTM which can check click on the form submit button.
As @kemsky suggested, GTM lifecycle is tied to internal gtm.load
event, which happens on window onload
. So DOMContentLoaded
may be too early to bootstrap.
Considering that GTM script was loaded prior to SPA script,
window.addEventListener('load', () => {
platformBrowserDynamic().bootstrapModule(MyAppModule);
});
callback will be triggered when GTM is ready to receive history change events, and there should be no race conditions.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With