Data Driven: Your Bounce Rate and Time On Site are wrong


It’s hard not to look at your bounce rate and wonder why so many people hate your product isn’t it? This article explains how Google Analytics might be screwing you on your bounce rate and some methods you can use today to measure it more accurately. In doing so, you’ll also be improving the accuracy of your visitor’s Time On Site.

So what is bounce rate?
‘Bouncing’ is generally used to describe when a visitor comes to your website, doesn’t interact and leaves, similar to when you’re searching for something and land on a page that blatantly doesn’t have what you need. That’s a bounce.

How does Google measure bounce rate?
Google indeed measures a bounce as zero interaction. However, Google doesn’t measure interaction as clicks or scrolls as default, Google measures by pageviews, so:

If a user leaves your site after loading the first page, regardless of any interaction, this is considered a bounce.

Here’s a few product scenarios where this logic fails:

  1. You have all the information required on one page (a blog post, a landing page, a very long informed single page website) and your users spend minutes enthralled on this page before leaving totally satisfied.
  2. Your site deliberately suggests external sources to your users. Your users love you because you help them find other stuff online, and the first link they click is to an external website.
  3. Your users sign in with Facebook, Twitter etc and the next page you load is on or (for their sign in page).
  4. Your product has a landing page capturing interest using a form which is powered by another service like Mailchimp, Wufoo and users are directed to their site after successfully completing your objective.

I’m not saying Google’s methodology is useless, in fact, it’s pretty smart for most cases. But it can’t work perfectly everywhere and understanding how it works will help you understand if you’re really picking up the right data.

How does Google measure Time on Site?
Ever shocked at how that’s a little low? This is somewhat related to the shortcomings in Google’s bounce rate: by default, Google measures the time on site as the time between the first page loaded and the last page loaded. If your users flick through tens of your pages, then this won’t be much of an issue. However, if you’re a victim of the bounce rate issue above, you’re probably a victim here too:

If users are only loading one page on your site, irrespective of how much they interact with that page, their time on site is 0:00 to Google Analytics.

There’s no second page to close the loop. In any case, the last page your users visit on your website, no matter how much time they spend on it, will not be included as part of their time on site.

With me so far? OK let’s look at some solutions 🙂
Now that you understand how Google’s off-the-shelf metrics work, it’s possible to alter them to suit your product.

If you skipped to here and aren’t really a javascript expert, I recommend you go back and read the article. Sorry but while I have some copy and paste solutions, you need to think about which is going to work best for your product. Let me know in the comments if any of these need more descriptions.

We’re going to dabble in some event-tracking. If you haven’t done this before, don’t worry. Just start, and you’ll figure it out quickly after you get into it.

Solution 1. Measure Time on Site
Brian Cray has written an excellent blog post discussing much of what I talk about here and he provides a very concise solution: instead of letting the a page view measure the time on site, let’s just ask every 10 seconds if the user is still there and measure it ourselves. (Edit: Thanks Nick for pointing out Google Analytics’s limit of 500 data points per user session. If running this code, I’d recommend reducing to every 60 seconds to avoid hitting this limit.) This does not require jQuery, works with old (sync) or new (async) Google Analytics, and you can just stick this code at the bottom of your page before the closing </body> tag:

This data will appear in your Analytics Dashboard under Content > Events with the Category ‘Time’, the Action ‘log’, and the Value will be the time on site. This is an easy way to start but I do have some issues with Brian’s method. It’s more likely to err on the vanity side, that is, if your users open your page in a background tab and doesn’t view the page for a few minutes — this is all counted as time on site. It’s a good starter to give you a different time on site metric and there’s room to refine it a little more later.

Solution 2. Close the loop by Tracking Outbound Links.
I prefer this method to measuring time on site, but you also need a little more know-how. It has the added advantage of tracking which outbound links your users are clicking on and where they’re going. This does require jQuery and also works with old or new Google Analytics.

The principle here is that if users are clicking external links to leave your site, then let’s track those to better calculate the time on site. You’re still losing people who close the window and I’ll deal with that another time, but you are now accurately measuring another segment otherwise ignored.

The following code tracks clicks on <a> tags linking to an external site. If an external link is not set to open in a new window, it adds a 300millisecond delay before loading the new URL to allow the tracking to register with Google Analytics. In your Google Analytics dashboard, under Events, you will now see a category called ‘Outbound’, with Actions showing the URLs your exiting visitors are disappearing to and the Value showing the ID of the element they clicked. Nice.


So how does this fix my bounce rate?
Well, I mentioned earlier that Google measures bounces and times based on pageviews by default. Google also treats tracked events like a pageview (at least for the sake of calculating bounce rate and time on site). So now, after you track an event on your single page website, the user can exit and this will no longer be considered a bounce. Additionally, because of this reason, your time on site will also be considered as the time between first page load and the time of the last tracked event.

I think this is accounting for more real interaction and a slightly more accurate view of your users than what Google Analytics does by default. More can be done of course, and I’ll go there in another blog post. Time for some coffee.


Sam spends his days drinking Aeropress'd coffee and scribbling interface designs, roadmaps and product ideas on scraps of paper. You can follow him on twitter at @smcllns.

  • I’d be careful implementing the ‘Time on Site’ code featured above. Analytics has, I believe, a limit of 500 events, including pageviews, it can track per user session. This could quite easily eat into that  limit. Especially important if you’re doing other Event Tracking calls and/or have users opening your site in multiple windows.

    • Anonymous

      Thanks Nick, you’re right about the 500 events per user session limit. I’ve update the post to note this.

      • Anonymous

        Maybe the best way to deal with event limit is to increase the interval.  

        var interval = 5000;
        (function foo() {
          setTimeout(function() {
             // track event here
            interval *=  2;


        • Anonymous

          yeah, that’s not bad. Though I think that running it on a timer is kind of a hack anyway, it should be based on interaction e.g. scroll, mousedown, keydown. 

          • Anonymous

            Probably some sort of interaction is good, but you want to prevent the case where someone leaves the page open in a background tab, and Google Analytics records a 1 hour interaction while the user is actually off at lunch.  Then they return, scroll a bit, and close the page.  That is not really a 1 hour interaction, but probably quite common with tabbed browsing.  

            Maybe use the window blur and focus events somehow.  

  • Steve Moyer

    Why can’t the unload event trigger the final page tracker event?

    • Anonymous

      The problem with unload is that there usually isn’t enough time for the GA call to finish. It’s generally recommended to allow 100-300ms for the tracking call to finish. 

      • This was posted 2 years ago, so I am hoping they can handle it! About to implement this on my site

    • Glenn Birrell

      Nice post thanks for this great detail about bounce rate.

    • Glenn Birrell

      Nice post thanks for this great detail about bounce rate.

  • Scott

    Try triggering this with the window.onbeforeunload event paired with logic that makes sure the user has actually been on page for longer than X seconds/minutes.

    • Anonymous

      Scott—can’t use onbeforeunload for a couple of reasons: 1) destroys caching of page and 2) doesn’t guarantee that the analytics call will complete.

  • Shay

    Sending an event to Google Analytics after 10 seconds on the page will cause your bounce rate to be wrong, no? By doing that, the bounce rate will show you the percentage of people who bounced from your site in less than 10 seconds… 

    • Anonymous

      Correct. I do note that this is not a perfect solution but an easy fix to get started. The complete solution will be quite a bit more complicated (in progress).

      • Shay

        A possible solution is to create two profiles – one with the “time” events and one without (by setting an exclude filter on the profile).

        Also, what I noticed on my site when I used this trick was that many visitors got to the 500 events limit (I am pretty sure they did not spend that time on my site – probably opened it in a new window/tab and read or closed it later) – Eventually, I created a code that looks for mouse movements, key press and scrolling before I send the time event just to make sure the visitor was really active. You can find the code at the end of this post:

  • Pingback: links for 2011-08-12 « Gatunogatuno’s Weblog()

  • Hello there!

    That’s a very nice hint for counting the correct time on site. Though, it doesn’t quite work for me. The values are all zero, and averages are zeros too. 

    The actual time on site is being put in the Event Label column, and it just counts the number of times that event occurs. Though, there is no average value, so I cannot see what the actual average time on site is.

    Can you please, help me out? I am not a js programmer, so it would be nice if you were as detailed as possible

    Thank you much!

  • To add to the Bounce Rate issue, there are a lot of factors to be considered.

    The Bounce rate which we see in the Google Analytics is not something
    the search engines consider for quality purposes. Search engine
    consider the “Dwell Time” which is nothing but the time spent on a page
    by the visitor before leaving back to the search results page or closing
    the page (without going to any other page on the site).

    Also, there are two types of bounce rates: Actual Bounce Rate and Standard Bounce Rate

    Actual bounce rate: user visiting your page from search results page
    and leaving within a few seconds without navigating to any other page on
    the site. The bounce rate what you see in the Google Analytics program
    is nothing but the Actual Bounce Rate. This is a negative sign as the
    Dwell Time is just a few seconds.

    Standard bounce rate: A person visits a page with high quality
    content, reads the full content and then leave (spends more than 10
    mins). Also, he doesn’t visit any other page on the site. This is still a
    bounce, but “Standard Bounce Rate”. Here this is not considered as a
    negative sign by the search engines as the Dwell Time is more than 10

    • CMJS

      A bit behind the times, but the bounce rate you see in GA is actually the ‘Standard Bounce Rate’ as you describe it.

  • Pingback: What are some useful custom profile filter configurations for Google Analytics? - Quora()

  • Brilliantly helpful! Thank you.  I’m curious, you said, “You’re still losing people who close the window and I’ll deal with that another time”  Have you dealt with the close of the window and if so, where?

  • Pingback: Top 3 Ways to Increase Your Visitors Time on Site | Tribal Blogs()

  • Noob City

    Regarding the first solution:

    Solution 1. Measure Time on Site

    Would it be possible (or even wise) to only run it, maybe, 3 times per page load?

    I really only want to know if the user is on the page for, say, at least 30 seconds. If not, then they would be a “bounce” and if more than 30 seconds, they would not be a bounce.

    Any suggestions on how to do that?


  • Pingback: Decrease Your Bounce Rate in Google Analytics, Increase Visitors, and Improve Your Site Experience | Small Business and Local Search Engine Optimization and Marketing()

  • Hey Sam- thanks for posting this, I found this after reading Brian Cray’s post. Both were very helpful.

    Thanks again – Matt

  • Rolland Winters

    nice trick, bookmarked! Thanks sam

  • Internet marketing

    Hi, Nice post on reducing bounce rate.. Thanks for sharing

  • Is there a way to do this without logging each incremental time on page? I’m having trouble filtering through all the 10,20,30,40 seconds page page to find which was the final time on page

  • I still can’t figure out how to interpret the “logs” and “times” to figure out the actual or average visit time in method 1.

  • abhishek agarwal

    I have using first sciprt and it is runnning smoothly but i want that it stops after a user is for a hour on my site can;t figured out how to do it !!

  • Rob Aaron

    Hey Sam,

    This is exactly what I am looking for, but apparently – and not surprisingly – google has changed analytics significantly since your post a couple of years ago. I put the code into my WP site, but when I go to analytics – following your direct tins to look in “Analytics Dashboard under Content > Events with the Category ‘Time’, the Action ‘log’, and the Value will be the time on site.” I can’t find this anywhere!??? Help??? Advice?

    • Guido

      This works for me:

      // from

      (function (tos) {

      window.setInterval(function () {

      // Every 10,000 milliseconds, calculate the time

      tos = (function (t) {

      return t[0] == 50 ? (parseInt(t[1]) + 1) + ‘:00’ : (t[1] || ‘0’) + ‘:’ + (parseInt(t[0]) + 10);


      // Collect and send the time to Google Analytics

      window.pageTracker ? pageTracker._trackEvent(‘Time’, ‘Log’, tos) : ga(‘send’, ‘event’, ‘Time’, ‘Log’, tos);

      }, 10000);


  • Edward Upton

    Hi all – we’ve created an updated version of that time-on-site script which

    (a) works with Universal Analytics

    (b) won’t alter your existing bounce rate reports, if other business users are used to seeing this value in a certain range

    (c) only tracks time that was spent when the page was in focus (not open in a background tab)

    (d) cuts off after 10 minutes to get around the maximum events limit

  • Hugh Hopkins

    This is a good hack around Sam. In production we have found 60 seconds to be too long though. It’s best to have a variable ping that gets longer with the time on site. You might be interested in some of our recent work: