Track Scroll Depth Using GTM: 4 Easy Setup Steps

Santaji GadeDevelopmentJavaScript3 weeks ago25 Views

track scroll depth

GA4 gives you one scroll checkpoint at 90%. This guide covers GTM's native Scroll Depth trigger, the real gotcha where thresholds can fire without a scroll, and how to set it up correctly.

Development JavaScript Analytics

Hello again! If you've ever wondered whether people actually read past your first screen or bail out early, today's guide gets you a real answer.

Scroll depth is one of those metrics that sounds simple until you actually try to measure it precisely, at which point a handful of real, well documented quirks show up. Learning to track scroll depth using GTM properly, quirks included, is what separates a report you can trust from one you have to quietly caveat.

01

How Do You Track Scroll Depth Using GTM?

Similar to file downloads, GA4 already gives you something here for free. To track scroll depth using GTM specifically, though, the reason to reach past that free version comes down to control: how many thresholds you get, and exactly when each one counts as reached. Most teams that decide to track scroll depth using GTM do so the moment a single fixed checkpoint stops being enough for a real content decision.

To actually track scroll depth using GTM, GTM ships a native Scroll Depth trigger built for exactly this, no custom JavaScript required. It watches real scroll position against thresholds you define, in percentages or pixels, and pushes a real event you can wire straight to a GA4 tag.

The rest of this guide walks through what the free version already covers, then the two real behavioral quirks worth understanding before you flip the trigger on and start using it to track scroll depth using GTM across the rest of your site.

Tip

Brand new to Tag Manager itself? Our beginner's guide to GTM covers containers and workspaces before you get here.

02

What GA4's Automatic Scroll Event Already Covers

Enhanced Measurement already sends a real scroll event the moment a visitor reaches 90% of a page, and Loves Data's own guide to GA4 scroll tracking confirms that single fixed threshold is the whole feature. GA4 also builds a Percent Scrolled dimension and a Unique User Scrolls metric on top of it automatically.

That one threshold is genuinely useful as a rough "did they basically finish the page" signal, and it costs nothing to set up. The gap shows up the moment you want to know whether most visitors are dropping off at 25% or making it comfortably to 75%, since GA4's own automatic version simply has no setting to add more checkpoints. That's the exact moment most teams decide to track scroll depth using GTM instead of waiting on GA4 to add the option.

Analytics Mania's own comparison of GA4 and GTM scroll tracking makes the same point from a different angle: the automatic version is fine for a quick sanity check, but anyone building a real content engagement report needs the quartile level detail only a configured trigger provides.

Did You Know

Loves Data's own testing confirms GA4's automatic scroll event fires at exactly 90%, not 100%, a deliberate choice that accounts for footers, sticky elements, and browser chrome that can make a literal 100% scroll unreliable to detect consistently.

03

Setting Up GTM's Native Scroll Depth Trigger

Tag Manager's own help center article on the Scroll Depth trigger documents the real configuration: choose Percentages or Pixels, then enter one or more positive integers separated by commas, 25, 50, 75, 100 covers the classic quartile breakdown most sites want.

Three built in variables come along with it once enabled: Scroll Depth Threshold, the exact number reached, Scroll Depth Units, percent or pixels, and Scroll Depth Direction, vertical or horizontal. Map all three into your GA4 event tag and every report already knows exactly which checkpoint fired.

This is genuinely the entire setup needed to track scroll depth using GTM at whatever granularity your content strategy actually calls for. A long form guide might want five or six checkpoints spread evenly down the page, while a short landing page might only need one or two past the automatic 90% GA4 already gives you.

scrollDepthPush.js
// what a real gtm.scrollDepth push looks like once a
// threshold is reached
{
  event: 'gtm.scrollDepth',
  'gtm.scrollThreshold': 50,
  'gtm.scrollUnits': 'percent',
  'gtm.scrollDirection': 'vertical'
}

Here's what real, gradual scrolling looks like against that trigger logic, captured from a genuine browser session rather than the documentation alone.

Terminal output from real Chromium scrolling showing thresholds 25 and 50 firing for a gradual scroll, and thresholds 25, 50, and 75 firing all at once for a single fast scroll jump

A real gradual scroll past the halfway point, next to a single fast scroll jump that crosses three thresholds at once.

04

The Page Load Gotcha: Thresholds Firing Without a Real Scroll

This is the quirk worth knowing before it quietly skews the reports of anyone trying to track scroll depth using GTM for the first time. Simo Ahava's own deep dive on the Scroll Depth trigger lays it out directly: if a page loads already positioned past a threshold, a browser restoring scroll position on refresh, or an anchor link landing partway down, GTM fires every threshold already crossed immediately, with no real scrolling gesture involved at all.

That second real test above shows exactly this behavior: a single fast scroll jump fired 25%, 50%, and 75% together, the same way a page load landing at that position would. If those numbers feed a bounce or engagement calculation without accounting for this, a handful of instant page loads can quietly inflate how deeply your audience actually reads.

Tip

On a short page where this is likely, Simo Ahava recommends marking the trigger as a non interaction event in the GA4 tag, so an instantly fired threshold doesn't count toward session engagement time the way a genuine scroll does.

05

Why a Threshold Never Fires Twice

The flip side of that same design is reassuring: Google's own documentation confirms the trigger fires once per threshold per page, full stop. Scroll back up and back down again as many times as you like, and an already fired threshold stays fired, never double counted.

Terminal output from real Chromium showing the dataLayer push count stays at 3 both before and after scrolling back up to the top and back down again, confirming no threshold refires

Real scrolling up and back down again, confirmed not to refire an already crossed threshold.

That single design choice is what makes scroll depth trustworthy as a report metric in the first place, and it's a big part of why so many teams choose to track scroll depth using GTM instead of trying to reconstruct the same logic by hand. Without it, a visitor who idly scrolls up and down while reading would inflate every threshold's count far past the actual number of real readers who reached it.

06

Sending Scroll Depth to GA4 as Its Own Event

With the trigger built, a GA4 Event tag ties it together. Elevar's own walkthrough of the newer Scroll Depth trigger maps all three built in variables into event parameters directly, which is the same pattern worth following here. Google's own GA4 events reference is worth checking too, since reusing its standard parameter naming keeps a custom scroll event comparable to GA4's automatic one instead of living in its own disconnected report.

Naming the event consistently matters more than it sounds like once you're trying to track scroll depth using GTM alongside several other custom events in the same property. Google's own tag best practices guide makes the same broader point about keeping tag and event names predictable, which pays off every time someone new joins the team and has to make sense of the existing setup.

GA4 Event Parameter GTM Variable Example Value
percent_scrolledScroll Depth Threshold50
scroll_unitsScroll Depth Unitspercent
scroll_directionScroll Depth Directionvertical

MDN's own reference for scrollHeight is worth a read if you want to understand exactly how the underlying percentage calculation works, since GTM's trigger is ultimately built on the same real DOM properties.

07

Common Pitfalls When You Track Scroll Depth Using GTM

A handful of real mistakes show up repeatedly once a scroll depth setup goes live, and most of them are easy to avoid once you know to check for them ahead of time rather than after a stakeholder questions a strange number in a report.

  • Running both the automatic 90% event and a custom 90% threshold. That specific number reports twice under two different event names, which confuses any report comparing them side by side. Pick one source of truth for that particular checkpoint.
  • Forgetting horizontal direction exists. Most sites never need it, but a carousel heavy or unusually wide page might, and it's easy to leave configured as vertical only out of habit.
  • Not testing on a genuinely short page. The page load gotcha from earlier is far more likely to show up on a short page where a normal viewport already covers 50% or more of the total height, so a tall blog post alone won't reveal it.
  • Mixing pixel and percent thresholds without realizing it. A trigger meant to fire at fixed pixel depths behaves very differently across a mobile screen versus a wide desktop monitor than one set to percentages, since a fixed pixel count means something different on every screen size.
  • Never revisiting the threshold list. A redesign that changes page length can quietly shift what 25% or 75% actually means for real readers, worth a periodic check alongside common GTM mistakes that break your tracking.
  • None of these pitfalls are exotic once you're actively watching for them, and they're the same reason it's worth running a real Preview mode test after any change to the pages, templates, or thresholds involved, rather than trusting a setup that worked once to keep working forever.

    If you're building out a fuller engagement picture, pairing this with button click tracking and PDF download tracking gives you scroll, click, and download signals from the same GTM container, and our guide to the GTM data layer explains exactly where all three of those pushes actually land.

    GA4 already sends one automatic scroll event at 90%. GTM's native Scroll Depth trigger is what you need for multiple configurable thresholds like 25%, 50%, and 75%.

    If a page loads already positioned past a threshold, GTM fires every threshold already crossed immediately, with no real scrolling gesture involved. This is documented, expected behavior.

    No. Google's own documentation confirms the trigger fires once per threshold per page, no matter how many times a visitor scrolls back up and down again.

    Only if your layout genuinely uses horizontal scrolling, a wide carousel or gallery. Most standard content pages only need the vertical direction.

    It can if you set a custom threshold at exactly 90%, since that duplicates GA4's own automatic event. Stick to thresholds GA4 doesn't already cover to avoid overlap.

    Learn Today

    1

    Scroll Depth Trigger

    GTM's built in trigger type that fires at configurable scroll percentage or pixel thresholds.

    2

    gtm.scrollDepth Event

    The real event name pushed to the data layer each time a threshold is reached.

    3

    Scroll Depth Threshold

    A built in variable holding the exact percentage or pixel value that was just reached.

    4

    Once Per Page

    The rule that keeps an already fired threshold from ever firing again on the same page.

    5

    Page Load Gotcha

    Thresholds already crossed at load time fire immediately, without any real scrolling.

    6

    Enhanced Measurement Scroll

    GA4's own automatic scroll event, fixed at a single 90% threshold.

    Ready to Build Cleaner Tracking?

    Explore more Brandella Journal guides on how to track scroll depth using GTM, plus analytics and tag management.

    0 Votes: 0 Upvotes, 0 Downvotes (0 Points)

    Leave a reply

    Loading Next Post...
    Search
    Popular Now
    Loading

    Signing-in 3 seconds...

    Signing-up 3 seconds...