Tracking Scroll Depth with jQuery and Google Analytics

(Update: You can view the updated plugin and new project page here.)

Scroll depth—the measure of how far a user scrolls on a particular page—is an interesting but lesser-known engagement metric. It’s not something you can find in your Google Analytics or Omniture account but you may be familiar with it from other analytics services (e.g., Chartbeat).

If you’ve ever participated in an ontological debate about “the fold”, you know that how far users are willing to scroll down a page (and whether they’re willing to scroll at all) is an important concern for both designers and business stakeholders.

So how can we measure it? One option is to sign up for a service like Chartbeat that offers scroll depth as a reporting metric. Another option is to use a little jQuery to record the data in Google Analytics. Here’s a plugin for that.

jQuery Scroll Depth

This is a plugin that watches for scroll events and then reports data back to Google Analytics using the Events API. By the default the plugin will record Baseline (0%), 25%, 50%, 75%, and 100% scroll events. You can find the data in the Events section of Google Analytics. The category is “Scroll Depth”, the action is “Percentage” and the label is the scroll depth percentage.

Google Analytics Events can be viewed at both the site and page level. This means you can see site-wide scroll depth as well as scroll depth for individual pages.

In addition to the 25%, 50%, 75%, and 100% marks you can record scroll events for specific elements on the page. Has an ad been scrolled into view? Did the user scroll down to the article comments section? To track these elements you just pass the selector as one of the plugin options.

Setting it up

It’s easy to set up. First, make sure you’re using the Google Analytics asynchronous tracking code. This is required; the plugin will not work with the old version of the tracking code. Then include jQuery and the plugin. After that you just have to initialize the plugin. It looks like this:

<script src=""></script>
<script src="jquery.scrolldepth.js"></script>
$(function() {

The code should be placed after your Google Analytics snippet and preferably at the bottom of the page, just before the closing body tag. (Note: If you’ve put the code at the bottom of the page, wrapping the plugin initialization in jQuery’s document ready event is not necessary.)

Try it out

To download the plugin or read more about the options, check out the jQuery Scroll Depth project page. If you have suggestions for improvement or would like to report bugs, please visit the Github repo.

Update (5/11/12)

I’ve posted a one-question poll asking for people’s opinion about what goal the “scroll depth” metric really tracks. If you have an opinion on this and would like to help advance this plugin, please take a second to weigh in!

Update (5/29/12)

The plugin now tracks timing, enabling you to see how much time it takes for users to reach the various scroll points. Thanks to Ilya Grigorik for the great suggestion!

Both comments and pings are currently closed.


Newer Comments »

Very cool! Thanks for sharing this!!

Couldn’t you use the opt_noninteraction from GA Events to have it not affect the calculated bounce rate? Or am I missing something?

Either way, thanks for sharing. I do believe I’m going to use this for some testing.

Is that a new option? I’ve been using GA events for years, have never seen that, and have always wondered why they didn’t have such an option. Regardless, thank you! I’ll add this to the plugin today.

Where should I put it in my WordPress theme?

Index or single.php

If you want it to run on every page of your site you should put it in footer.php.

How does it work if your pages use infinite scroll?

It’s a good question. I haven’t tested it with infinite scroll but the document height is recalculated on each scroll event, so there’s probably race condition between when the plugin thinks it’s reached the bottom of the page and when infinite scroll adds more content. I’m guessing the scroll depth plugin wins the race and fires the 100% event right before new content is added to the DOM.

I think for infinitive scroll the best way to track is by defining custom track elements that are unique. Like #image0, #image50, image100 or whatever you can control your source with.

Very nice. Thanks for sharing! I havent’ tried it yet, but the first thing that came to mind: with the option “minHeight” do you check, if it is at least x-times the view-port-height? Or could you maybe add that?

I’ve created a MooTools version of this for a client, so here it is in case anyone needs it:

Couple questions:
1. How does one know if their company’s site is using the Google Analytics asynchronous tracking code?
2. How long before these metrics appear in your GA account?


Do you mean instead of a min-height set in pixels the min-height should be based on x-times the viewport height? That’s not a bad idea.

Cool! Thanks for sharing.

1. Whoever implemented the Google Analytics tracking code should be able to tell you. Or let me know the URL for your site and I can look at it for you.
2. With Google Events data I think there’s a lag of 3 to 4 hours.

Thanks Rob, installing on my site now. Very interested to see the results.

Hi Rob. I was able to go into GA FAQ and noticed their code for asynchronous tracking differed from our code, which was likely implemented years ago. From there, I was able to generate new code, insert it into the header and also add your script. The analytics are working brilliantly.

As I was looking over the numbers with a co-worker, something occurred to us: Is there a way to find out if a user/event is “baseline” either because they aren’t scrolling down or because their monitor is large enough that they don’t need to scroll? I bring this up because my monitor is large enough to view about 90% of the page, but a co-worker can see only about 30%.


I’ve been considering something similar but just haven’t gotten around to this. My main question for now is do you check to “override” triggering the GA Event based on scroll speed? In other words, if someone zips quickly to the bottom then they probably didn’t read the content then flew past. Don’t get me wrong, knowing how deep they go on the page has value. But it would also help to know how quickly they got as far as they did.

“Couldn’t you use the opt_noninteraction from GA Events to have it not affect the calculated bounce rate?”

I think this should be an option. Or at the very least be able to set the “depth” that counts as an event. For example, if someone lands on a page and scrolls 50% (or more) that doesn’t sound like a bounce to me. At least not in the traditional, land, look, do nothing and leave sense of the word.

Great! I’m glad it’s working for you. The “Baseline” event is intended to simulate the Pageview, i.e. it fires immediately when the page loads so we have something to compare the other scroll events against. There is an option that lets you disable the plugin for pages with a height less than X number of pixels. But as one of the other commenters mentioned, it might make more sense for this minimum height to be based on viewport size instead of document size. I think that’s probably the way to go and I’ll likely work that into the next version.

Thanks for the feedback!

No, scroll speed is not considered. It simply fires GA events based on distance. I understand what you’re saying but making a time judgment adds complexity… where do you draw the line? If they scroll to the bottom within 5 seconds? 10? Variable based on content or height? Simplicity (especially for the person implementing the plugin) is something I’d like to preserve.

I added the `opt_noninteraction` option the same day I released the plugin :)

Rob, that would be a great addition. So if I understand correctly, there is no way to modify that part of the script currently.

As for the baseline numbers, tell me more about that. How should we quantify the numbers we have? Is it safe to say all baseline events mean the user is not scrolling down the page at all?


Rob, great stuff! Perhaps one thing to consider is to try using the new User Timings API. It’s effectively “events on steroids” and allows you to also specify an elapsed time for every event. This way, you can still see the total counts for each marker (10%, 25%), but in addition you will also see an average time it took the user to hit that scrolldepth, as well as a full histogram for the timing data.

At the moment the User Timing report lives in Content > Site Speed, but its a general API that is applicable to many different applications (anything timing related), and I think this would be a perfect case for it.

That’s a really great idea. I’m familiar with the site speed metrics in GA but I didn’t realize there was a general timing API. Very cool. Will definitely put this into a future release. Thanks!

Awesome, will look for it!

P.S. completely unrelated, but notifications on comments would be an awesome :-)

Another good point :) Done!


I’m very excited about the new ideas. You got it right with the vieport-height vs. document-height. I think with all these different “viewports” (mobile screen, 24″ lcd) it makes a big difference. Also timing would be a great addition. Any idea when you will get around to implementing it?

Not sure about timing… soon. But I have a couple of other projects I need to move along first. There’s one question I’m still unsure about, which is whether the intent of a scroll depth metric is to track literal scroll activity or page visibility. In the latter case scroll activity is just an indicator. I think it’s an important distinction. And the answer impacts decisions about how the plugin options should work.

I’ve put the question up on Github to ask for feedback. If you have any thoughts on it I’d love to hear them!


I’m running a wordpress theme and I put text from “jquery.scrolldepth.js” in the footer, but all it did was place the text at the very bottom of the page. Is there someplace specific that it needs to go in footer.php file?

Thank you

Instead of putting the contents of jquery.scrolldepth.js into the template you should add the plugin as an external file (like you see in the example in the blog post). If you must add the content directly, make sure to wrap it in SCRIPT tags. That should fix the problem you’re seeing.

Hi, I’ve made this compatible with jquery 1.4.4+ if you can’t upgrade to jquery 1.7.
It’s on my github here:

I have installed this on our site at to test it and I am not getting any other readings other than Baseline; can you let me know what I am doing wrong?

Looks like you’re using an old version of jQuery (1.5). The plugin requires 1.7+. Upgrade jQuery and it should work correctly.


I’ve been trying to figure out how to catch the data on the end of the Analytics interface. Am I supposed to be creating a new advanced segment or something like that? I’m assuming that the data will be sent to the Analytics service, so it will be popping up in one of the dropdown menus if I simply type in the first few letters?

You’ll have to excuse me, I’m rather new to Analytics.

Very cool … it’s reporting into GA perfectly.

Rob – I would like to make a tool-tip / floating dialogue fire at a certain scroll depth. What do I have to modify in jquery.scrolldepth.js for this? … then what to add to the HTML to trigger the event??

Thanks! … adding some documentation and an example on for this use case would make your great plugin even more valuable and useful.


I know that´s a pretty amateur question, but:
-how could I know my site is running jquery? I currently used the latest version.
-how could I know the plugin is working properly? Thanks.

I have been using your scrolldepth plugin for some time and its been great! Today I installed a jquery carousel on my site, and now scrolldepth no longer functions. Firebug reports the following error: TypeError: $ is not a function. Perhaps the carousel is also using the $ variable? Have any ideas on how I might fix this? Many thanks!

It sounds like you’re referencing a jQuery plugin before jQuery has loaded on the page. Check the order that you’re loading your scripts in.

Hi Rob, the plugin has been working great and the percentages are tracking appropriately. Time tracking was added and I have moved to the new version. I am unsure on how to see the time tracking results.

Thanks again.. awesome script!

This is a great plugin and will be really helpful since I have a lot of scrolling on my site. I do have one problem. I’ve had it running for about a day and all that’s being reported is “Baseline”. I don’t see 25%, 50%, 75% or 100%. Any help would be appreciated. Thanks.

This rules. You rule. Thank you.


I was wondering if there’s an easy way to see the scroll data for separate pages? I’d like to track every page, but I’d also like to see what happens on each page separately…

Also, is it possible to track the page more accurately? In other words, instead of just 25%, 50%, 75%, and 100% I’d like to have it in smaller increments.

Thanks :)

Within Google Analytics you should be able to see tracking for individual pages by using the Secondary Dimension option.

The plugin doesn’t offer an option to track smaller percentage increments but it does provide an option to track custom DOM elements. So you could specify a whole bunch of elements on the page that you want to track and that might get you the granularity you’re looking for.


Thanks. I’ll check it out :)

Hi, great plugin! Easy to set up also, have tried others but this works really well.

The plugin works great. I was checking a few pages and a couple have 25% with higher numbers than Baseline. How is this possible?

Hi thanks for sharing this, any plans to extend it to be compatible with the new universal analytics code

Hi Rob,

did you plan a wordpress plugin for that?


I’ve worked on the script of Rob a bit and build in support for Universal Analytics and Google Tag Manager. You can find the fork over here:

Check the script: jquery.scrolldepthMulti.js and index_multi.html

The plugin works great. Thanks for sharing.

great work works well

I have a quick question Rob,

Do I need to do anything besides add that code snippet to the footer.php file of my WordPress blog?

Hi Rob,

Is there a way to implement this using Google Tag Manager?