Scroll depth tracking is one of the most valuable engagement metrics for content-heavy websites. Most tutorials require Google Tag Manager, but you can track scroll depth in GA4 without GTM using native JavaScript and GA4’s Measurement Protocol. This guide covers everything from basic scroll tracking to advanced milestone detection—no Tag Manager required.

GA4 scroll depth JavaScript tracking

Why Track Scroll Depth in GA4?

Scroll depth reveals whether your content actually gets read. A page with 10,000 monthly visitors where only 20% scroll past 50% has a fundamental content problem. Without scroll depth data, you can’t distinguish between visitors who read every word and those who immediately left. GA4 makes this measurable with custom events, and when you track scroll depth in GA4 without GTM, you have full control over the implementation.

The JavaScript Implementation

The approach uses the Intersection Observer API to detect when users reach scroll milestones (25%, 50%, 75%, 90%) and fires GA4 events via gtag.js. Add this code directly to your website’s HTML before the closing body tag:

// Scroll depth tracking for GA4 - no GTM required
const milestones = [25, 50, 75, 90];
const fired = new Set();

function getScrollDepth() {
  const scrollTop = window.scrollY || document.documentElement.scrollTop;
  const docHeight = document.documentElement.scrollHeight - window.innerHeight;
  return Math.round((scrollTop / docHeight) * 100);
}

document.addEventListener('scroll', function() {
  const depth = getScrollDepth();
  milestones.forEach(milestone => {
    if (depth >= milestone && !fired.has(milestone)) {
      fired.add(milestone);
      gtag('event', 'scroll_depth', {
        percent_scrolled: milestone,
        page_title: document.title,
        page_location: window.location.href
      });
    }
  });
}, { passive: true });
GA4 scroll milestone events dashboard

Viewing Scroll Data in GA4 Reports

Once your scroll tracking is live, find the data in GA4 under Reports > Engagement > Events. Look for “scroll_depth” events. Click into the event to see the percent_scrolled parameter breakdown. Create a custom dimension for percent_scrolled to use it in Explorations. A scroll depth funnel (25% → 50% → 75% → 90%) instantly reveals where readers abandon your content.

MethodWithout GTM (This Guide)With GTM
Setup complexityLow — edit one fileMedium — configure tags & triggers
Deployment speedImmediateRequires container publish
CustomizationFull JS controlLimited to GTM fields
Best forDevelopers, single sitesMarketing teams, multiple sites

Advanced: Single-Page App (SPA) Scroll Tracking

If your site uses React, Vue, or another SPA framework, you need to reset scroll tracking on route changes. Listen for the history.pushState event and reset the fired milestones set. For SPAs, also ensure your gtag.js snippet sends page_view events on route change so scroll events are attributed to the correct page.

FAQ

Does GA4 have built-in scroll tracking? Yes—GA4 auto-tracks scroll events at 90% by default, but only at that one threshold. To track 25%, 50%, and 75% milestones, you need custom implementation like the code in this guide. Will this slow my site down? No—the implementation uses passive scroll listeners and fires events asynchronously via gtag.js, adding negligible overhead. Can I track scroll depth per blog post category? Yes—add a page_category parameter to your gtag event call and create a custom dimension in GA4 to filter by category.

Conclusion

You can successfully track scroll depth in GA4 without GTM using a simple JavaScript implementation. The Intersection Observer approach is performant, customizable, and gives you milestone data at 25%, 50%, 75%, and 90% scroll depth. Once deployed, use GA4’s Exploration reports to build scroll depth funnels and identify exactly where readers drop off your most important content pages—then use that data to improve structure, add jump links, or restructure content flow.

Leave a Comment