
How to Track Scroll Depth in Google Analytics 4
Scroll depth is one of the simplest, most useful proxies for whether long-form content actually gets read, and GA4 tracks a basic version of it automatically. For most sites, the default is enough. For content-heavy sites that want finer detail — where exactly readers drop off, not just whether they reached the bottom — a small custom implementation adds meaningfully more insight.
How Automatic Scroll Tracking Works
If Enhanced Measurement is enabled (the default), GA4 automatically fires a scroll event once per page, when a user scrolls to 90% of the page's vertical depth. It's a single fixed threshold — there's no automatic tracking at 25%, 50%, or 75% out of the box, and no configuration option to change the 90% figure.
Verifying Automatic Scroll Tracking
- Open Admin → DebugView.
- Visit a long page on your site and scroll to near the bottom.
- Confirm a
scrollevent appears once you cross the 90% threshold.
If it doesn't fire, confirm the scroll toggle is enabled under Admin → Data Streams → [stream] → Enhanced measurement, and check that the page is actually tall enough to scroll meaningfully (a very short page might not have enough scrollable height to trigger it in a meaningful way).
Why the Default Might Not Be Enough
The single 90% threshold tells you whether someone reached near the bottom, but not where they gave up if they didn't. For a 2,000-word article, knowing that 60% of readers never passed the 90% mark is useful, but knowing whether most of that 60% dropped off at 20% (barely started) versus 70% (read most of it) tells a very different story about what to fix.
Building Custom Scroll Milestones
const milestones = { 25: false, 50: false, 75: false, 100: false };
function checkScrollDepth() {
const scrollTop = window.scrollY;
const docHeight = document.documentElement.scrollHeight - window.innerHeight;
const scrollPercent = Math.round((scrollTop / docHeight) * 100);
[25, 50, 75, 100].forEach((milestone) => {
if (scrollPercent >= milestone && !milestones[milestone]) {
milestones[milestone] = true;
gtag("event", "scroll_depth", {
percent_scrolled: milestone,
page_path: window.location.pathname,
});
}
});
}
let scrollTimeout;
window.addEventListener("scroll", () => {
clearTimeout(scrollTimeout);
scrollTimeout = setTimeout(checkScrollDepth, 100);
});
The setTimeout-based debouncing (checking at most every 100ms, rather than on every single scroll event) prevents this from firing excessively during a fast scroll gesture, which would otherwise generate a large number of unnecessary function calls in rapid succession.
Implementing via Google Tag Manager
GTM includes a Scroll Depth trigger type, letting you achieve custom milestones without writing JavaScript:
- Under Variables → Configure, enable Scroll Depth Threshold and Scroll Direction variables.
- Create a trigger: Scroll Depth, choosing Vertical Scroll Depths and entering percentages (e.g., 25, 50, 75, 100) as either percentages or pixel thresholds.
- Create a GA4 Event tag named
scroll_depth, mappingpercent_scrolledto{{Scroll Depth Threshold}}. - Set the trigger and test in Preview mode.
This built-in trigger type handles the debouncing and once-per-threshold logic internally, making it a simpler path than custom JavaScript if you're already managing tags through GTM.
Reading Scroll Depth Data
- Go to Reports → Engagement → Events, and click into your scroll event.
- Add Percent scrolled as a dimension (once registered as a custom dimension under Admin → Custom definitions) to see the distribution of how far readers typically get.
- Cross-reference with Page path to compare scroll depth patterns across different articles or page types.
A steep drop-off between 25% and 50% on a specific article, for example, suggests something in the early-to-mid content — a weak transition, an irrelevant tangent, a wall of text without a subheading break — is losing readers who were initially engaged enough to start.
Combining Scroll Depth with Average Engagement Time
Scroll depth alone doesn't tell you if someone paused to genuinely read, or just scrolled quickly without absorbing much. Pairing it with average engagement time for the same page gives a fuller picture: a page with strong scroll depth (people reach the bottom) but low engagement time suggests skimming rather than careful reading, while strong scroll depth combined with high engagement time is a much stronger signal of genuine, attentive consumption.
Marking a Scroll Milestone as a Conversion
For content specifically designed to build toward a conversion at the end (like a long-form guide ending in a call-to-action), marking a high scroll milestone (75% or 100%) as a conversion can be a reasonable proxy for "reached the point where the CTA appears," especially for pages without a more direct event tracking the CTA interaction itself. This is a softer, proxy-based conversion, and shouldn't be weighted the same as a direct action like a form submission or purchase.
Using Scroll Depth to Prioritize Content Edits
Once you have scroll depth data across a full content library, it becomes a practical prioritization tool for editing work. Rather than guessing which older posts might benefit from a rewrite, sort your content by a combination of high traffic and low scroll depth — these are pages already earning attention from search or referral sources but failing to hold it once readers arrive, making them the highest-leverage candidates for a content refresh, compared to a low-traffic page where even a perfect scroll depth wouldn't move much total engagement.
Scroll Depth on Non-Article Pages
Scroll tracking isn't only useful for blog posts. A long product page, a detailed FAQ page, or a pricing page with several tiers and add-ons can all benefit from the same milestone approach — a pricing page where most visitors never scroll past the first tier, for example, is a concrete signal that your most-viewed pricing option may need better positioning or that the page's ordering doesn't match what most visitors are actually looking for first.
FAQ about Tracking Scroll Depth in Google Analytics 4

Does GA4 track scroll depth automatically without any setup?
Yes, via Enhanced Measurement's scroll event, which fires once at the 90% depth threshold — no custom code required for this basic version.
Can I change the default 90% threshold for automatic scroll tracking?
No — the built-in Enhanced Measurement scroll event only supports the fixed 90% threshold; custom milestones require either GTM's Scroll Depth trigger or manual JavaScript implementation.
Is scroll depth a reliable proxy for actual reading?
It's a reasonable proxy for reaching content, but pairing it with average engagement time gives a more complete picture, since scroll depth alone can't distinguish careful reading from fast, shallow scrolling.
Should scroll depth be tracked on every page, or just long-form content?
It's most useful on genuinely long pages where reaching the bottom is meaningful; tracking it on very short pages adds little analytical value, since most visitors will naturally reach the bottom regardless of engagement quality.
Can I use GTM's built-in Scroll Depth trigger instead of custom JavaScript?
Yes — GTM's native Scroll Depth trigger handles multiple percentage thresholds and debouncing without requiring custom code, making it the simpler option for teams managing tags primarily through GTM.
Does scroll depth tracking work the same way on mobile as desktop?
The underlying mechanics are the same, but mobile scroll behavior (faster, more frequent small scrolls) can produce a somewhat different pattern — it's worth reviewing mobile and desktop scroll data separately rather than assuming identical behavior across devices.
Conclusion
Scroll depth tracking in Google Analytics works out of the box for a basic signal, but custom milestones give content-heavy sites a genuinely more diagnostic view of exactly where readers drop off. Pair it with engagement time for a fuller read on content quality, and use it to find the specific point in your website's long-form content that's actually losing people.


