GTM Tags & Custom Scripts I Find the Most Useful in My Projects: part three — Website Engagement Tracking and Micro Conversions

Table of Contents

website engagement tracking, micro conversions, gtm, google tag manager, oneivan
Part three: website engagement tracking and micro conversions. Learn how to track important micro conversions via GTM in a few simple steps.

Website engagement tracking and micro conversions

In this post I’m gonna focus on website engagement tracking from an advertising perspective. Website engagement tracking might not seem so important at first, since your end goal is either to get leads or make sales. Nonetheless, website engagement tracking or rather said micro conversions tracking gives you important insights on your users’ behavior. More importantly, micro conversions help machine learning algorithms optimize ad delivery for user actions that matter more business-wise such as leads or purchases.

This is the final post in GTM Tags & Custom Scripts series. The other two posts can be found here:

There are plenty of client-specific micro conversions such as visiting a particular web page or clicking on important CTA button that you may need to track. However, besides case-specific micro conversions I always tend to track user engagement and micro conversions with one of following methods:

  • Native GTM scrolling + timer triggers
  • Visible time on page (reading content without tabbing out).

It depends on what’s better in a particular case I’m working on.

Website engagement tracking via scrolling and time on page

This one is pretty simple to pull out using only native Google Tag Manager variables and triggers. The idea is to combine Scroll depth and Timer into a trigger group that will fire only if both conditions are met.

Step 1 – Scroll depth

Create a new scroll depth type trigger and select vertical scroll depths in percentages. You can go with any percentage here, but I like to either keep it at 70% or 75% that is usually scrolling-wise just at the beginning of footer, which means that only users that read or skim through most of the page content can trigger this.

website engagement tracking, micro conversions, scroll depth trigger gtm

Step 2 – Timer

Create a new timer type trigger and leave the Event Name as it is: gtm.timer. The next step is to define the interval for triggering the timer function. Again, you can go with anything here, but I usually go with 40000 milliseconds, which equals to 40 seconds. I find it to be the most optimal time interval for a user to properly consume your content. Anything above might be too much, especially if your site does not have much written content… and anything less is just not enough to properly consume the website content.

I keep the limit field blank, as I don’t want to limit this trigger from firing through the session. Finally, enable this trigger when Page URL contains your domain name if you want it site-wide, or narrow it down to a specific subdomains or pages if needed.

website engagement tracking, micro conversions, timer trigger gtm

Step 3 – Trigger group

Create a new Trigger group type trigger and choose two previously created triggers to be included in the trigger group. This trigger group will fire only if both of the conditions (triggers) are fulfilled.

website engagement tracking, micro conversions, trigger group gtm

Step 4 – Tags

Use the newly created “Trigger group” as the trigger for your Google Ads conversion tracking tag, Facebook Pixel custom event or any other conversion tracking tag to measure user website engagement.

website engagement tracking, micro conversions, google conversion tracking gtm

How to track user’s visible time on page, i.e. actively reading your content and time when they tab out from your site

Scrolling + timer can make user website engagement tracking pretty accurate. However, there is one other method that goes a step further, and I like to use it with Facebook Pixel in order to create powerful custom conversions such as 1 minute visible time, 3 min visible time etc. I am talking about tracking active time on page, i.e. when someone is not tabbed out and is actively consuming your website content.

Step 1 – Custom HTML tag

To implement this type of tracking, you’ll first need to create a custom HTML tag containing the listener script which measures user’s active and hidden (tabbed out) time on page and pushes it into dataLayer. To be honest, I found this script years ago somewhere on the web and I cannot remember exactly where. However, since I’m not a coder, it’s a good thing I’ve saved it!

  // Initialize time 
  var startTime = new Date().getTime();
  var totalTime = {};
  if (typeof prefix() !== 'undefined') {
  var prevTime = 0;
  var visibilityEvent = prefix() + 'visibilitychange';
  var tabPath = 'visibleTab';
//Initialize the listeners
  var isHidden=visibilityState(prefix())
  if (typeof isHidden !== 'undefined') {
  prevTime = 0 ? new Date().getTime() - startTime : new Date().getTime() - startTime - prevTime;  
    //Total Time for previous visibility state 
    if(isHidden) { totalTime.visibleTime=prevTime; tabPath+=">hiddenTab"} 
     else {totalTime.hiddenTime=prevTime; tabPath+=">visibleTab" } 
         //////Debugging Datalayer Event ///////// 
              'event' : 'visibilityChange',
              'visibleTime' : totalTime.visibleTime,
              'hiddenTime': totalTime.hiddenTime,
              'hidden' : isHidden,
              'tabPath': tabPath  
}, false);
window.addEventListener('beforeunload', function(e)  
var isHidden=visibilityState(prefix())

if (typeof isHidden !== 'undefined') {
prevTime = 0 ? new Date().getTime() - startTime : new Date().getTime() - startTime - prevTime;  
else {totalTime.hiddenTime=prevTime} 

if(tabPath.split('>').length > 3) {
var len = Math.floor(tabPath.split('>').length / 2);
var adtxt = ''
if(tabPath.split('>').length / 2 % 1 !== 0){adtxt+=' > visibleTab';}
tabPath = '(visibleTab > hiddenTab) x '+len+adtxt
'event' : 'sendTimings',
'visibleTime' : totalTime.visibleTime,
'hiddenTime': totalTime.hiddenTime,
'hidden' : isHidden,
'tabPath': tabPath
  // reset the variables after sending data to analytics  
  startTime = new Date().getTime();
  totalTime = {};
  tabPath = 'visibleTab';
}, false);

  function prefix() {
  var prefixes = ['moz', 'ms', 'o', 'webkit'];
    if ('hidden' in document) {
    return '';
   // Loop through each prefix to see if it is supported. 
  for (var i = 0; i < prefixes.length; i++) {
    var testPrefix = prefixes[i] + 'Hidden';
    if (testPrefix in document) {
      return prefixes[i];


 function visibilityState(pref){
    switch (pref) {
    case '':
      return document['hidden'];
    case 'moz':
      return document['mozHidden'];
    case 'o':
      return document['oHidden'];
    case 'webkit':
      return document['webkitHidden'];

Configure it to fire on All Pages, or on any subset of pages if you don’t want to measure visible and hidden timings site-wide. The listener script measures time in milliseconds, so keep that in when creating custom conversions on Facebook.

Step 2 – dataLayer variables

Listener script pushes information about visible and hidden time via two dataLayer variables. In order to be able to use them in GTM, you’ll first need to create them as new user-defined variables. Create two new variables as following:

  • visibleTime – Data Layer Variable, Version 2
  • hiddenTime – Data Layer Variable, Version 2

Step 3 – Custom event trigger

In order to send visible and hidden timings to Facebook Pixel custom event tag, you’ll need to create a Custom event trigger. Name it sendTimings and make it fire on all custom events.

website engagement tracking, micro conversions, custom event trigger gtm

Step 4 – Facebook Pixel custom event

Finally, we need to create a custom Facebook Pixel event to track active and inactive user time on the website. There are few important things to remember here:

  • Don’t forget to specify your Pixel base tag as a setup tag for Pixel event. It is not necessary, but it will prevent event tag from firing before base tag which can lead to data loss.
  • You need to use ‘trackCustom’ parameter in Pixel event code, since we’re not tracking a standard Pixel event here.
  • Pass dataLayer variables you’ve specified earlier as event parameters together with a Page URL parameter that will tie timings to a specific URL.

website engagement tracking, micro conversions, Facebook Pixel gtm

Conclusion on GTM series (for now)

The third part in post series on GTM tags I find the most useful in my projects brings Google Tag Manager story to an end, at least for now. I will update posts with newer content once I find and test other stuff I stumble upon. In the meantime, I am already thinking about the next two topics I want to write about:

  1. A more GDPR friendly analytics
  2. Facebook Ads campaign budget optimization (CBO) and scaling

I will try to publish at least one from these two topics in 2020, but I cannot promise anything since holiday season is always super busy for digital marketers. Also, you can always reach out to me if you have suggestions or cool GTM tricks to share. I will be more than happy to include it in the updated version of GTM posts.

Share on linkedin
Share on twitter
Share on reddit
Share on xing
Share on telegram
Share on facebook
Share on pocket
Share on whatsapp
Share on email