So here we are again. Universal Analytics and Google Tag Manager, the dynamic duo, ready to strike again.

First, remember to check my previous two tips for UA and GTM use in custom scenarios:

In this post, I visit the idea of adjusted bounce rate, which I came across a year ago in the Google Analytics blog.

Adjusted bounce rate basically refers to tweaking the traditional bounce rate collection method (single engagement hits / total visits) so that visits which only included a single page view would not count towards a bounce, as long as they met some qualitative requirements.

By the way, check this great post on bounce rate by Yehoshua Coren if you need a refresher on what the term means.

For these custom events, I use the generic event container I created in my previous post.

The easy method: visit duration

This is the easiest to implement. It’s also the one in the Google Analytics blog post I referred to above.

What it does is fire a setTimeout() method as soon as the page has loaded. If the timer runs out (the time is 30 seconds in this script), an interaction event is fired, meaning the visit is not counted as a bounce.

The end result is this:

And here’s how to do it.

Steps:

  • Create a new custom tag called “Dwell time”
  • Set Tag Type as Custom HTML tag
  • Add the following code in the HTML field:
<script>
setTimeout("dataLayer.push({ 'event': 'GAEvent', 'eventCategory': 'NoBounce', 'eventAction': 'Over 30 seconds' })", 30000);
</script>
  • Add {{event}} equals gtm.dom as the firing rule
  • Save tag
  • Save container and publish

See, I told you it was easy. What happens here is that after the DOM has loaded (the firing rule), a timer starts. If the user stays on the page when the timer goes off, the event is fired. Remember, you need the generic event container for this to work. So remember to check my previous post for instructions how to build it (it’s easy, I promise!).

The intermediate method: measure scrolling

This method was inspired by a Google+ post I came across by Avinash Kaushik, where he detailed a script written by Nick Mihailovski. This script is used here extensively, with just the event call in a different format (to support UA and GTM).

What happens here is that the event listener waits for a scroll event (so you actually scroll the page down), and fires the no-bounce event after that. Interesting! The statement is that if you scroll, you read, and if you read, you’re engaged (with the content).

Steps:

  • Create a new tag “Scroll the page”
  • Set Tag Type as Custom HTML tag
  • Add the following code in the HTML field
<script>
window.addEventListener ?
  window.addEventListener('scroll', testScroll, false) :
  window.attachEvent('onScroll', testScroll);

var scrollCount = 0;

function testScroll() {
  ++scrollCount;
  if (scrollCount == 2) {
    dataLayer.push({ 'event': 'GAEvent', 'eventCategory': 'NoBounce', 'eventAction': 'Scrolled the page' });
  }
}
</script>
  • Set {{event}} equals gtm.dom as the firing rule
  • Save tag
  • Save container and publish

And you’re done. So what the script does is measure if a scroll event occurs during your page view. If it does, the event is fired. Note that it won’t fire the event with every subsequent scroll, so you don’t have to worry about clogging your 500 events per session quotas.

This isn’t fool-proof, of course. It just checks whether the user scrolls. What this DOES prevent is the miscalculation of page visit duration if the user just opens the page in a separate tab and leaves it be. Now you actually need interaction, albeit a very minimal one, to produce an engagement and neutralize the bounce.

The advanced method: page load AND scroll

So what about measuring whether there was a scroll event and the visit duration on the page was over 30 seconds? Wouldn’t that be an even better way to calculate engagement? I think so. So here’s what you do. First, make sure the two tags you just created are not active any more (otherwise you’ll be sending multiple bounce-wrecking events).

Steps:

  • Create new tag “Dwell and scroll”
  • Set Tag Type as Custom HTML Tag
  • Add the following code in the HTML field:
<script>
(function() {
  var visitTookTime = false;
  var didScroll = false;
  var bounceSent = false;
  var scrollCount = 0;

  setTimeout(timeElapsed, 30000);

  window.addEventListener ?
    window.addEventListener('scroll', testScroll, false) :
    window.attachEvent('onScroll', testScroll);

  function testScroll() {
    ++scrollCount;
    if (scrollCount == 2) { didScroll = true };
    sendNoBounce();
  }

  function timeElapsed() {
    visitTookTime = true;
    sendNoBounce();
  }

  function sendNoBounce() {
    if ((didScroll) && (visitTookTime) && !(bounceSent)) {
      bounceSent = true;
      dataLayer.push({
        'event': 'GAEvent', 
        'eventCategory': 'NoBounce', 
        'eventAction': 'Time spent and page scrolled'
      });
    }
  }
})();
</script>
  • Set {{event}} equals gtm.dom as the firing rule
  • Save tag
  • Save container version and publish

Here the timer starts first. As soon as it hits 30 seconds, it calls the sendBounce() method. This method checks if the user has also scrolled, and if they have, the event is fired. Note that I also make sure that the event is sent only once with the boolean variable bounceSent.

When the user scrolls, the same method is called and the same check is made.

So there are four different scenarios resulting from this script:

  1. The user doesn’t scroll, but stays on the page for 0-to-infinite seconds, and the event is not fired (visit is a bounce)
  2. The user scrolls, but the timer hasn’t gone off, and the event is not fired (visit is a bounce)
  3. The timer goes off, and the user has already scrolled, and the event is fired (visit is not a bounce)
  4. The user scrolls, and the timer goes off, and the event is fired (visit is not a bounce)

A much healthier way of calculating adjusted bounce rate, in my opinion.

Conclusion

The way you measure bounce rate should always be in relation to the goals you set for a page or for your site. If engagement is important, remember to add clear calls-to-action, so that you don’t have to resort to artificial adjustments like those depicted in this post.

However, for a simple blog like this, measuring engagement by a combination of visit time and scrolling interaction is probably a pretty good way of getting a more realistic metric for tracking visit quality.

An even more advanced (and qualitative) method would be to see just where the user scrolls to. Is it to the end of the post or just the first paragraph? In other words, does the user read or just skim. That’s a crucial question, and I might just return to the issue in a later post.