
April 1, 2025
Scroll tracking with Google Analytics 4 (GA4 Scroll Depth Tracking)
Updated: April 1st, 2025
Compared to previous versions, Google Analytics 4 offers more built-in tracking capabilities. This includes file downloads, outbound clicks, scroll tracking, and more. But did you know that the built-in scroll tracking in Google Analytics 4 tracks only when someone scrolls below the 90% percent mark of the page height?
What if you also want to track other thresholds (e.g., 25%, 50%, 75%)?
In this blog post, I wanted to show you how to implement scroll tracking with Google Analytics 4 and Google Tag Manager and customize it based on your needs. There are two possible approaches here, and I’ll explain them both.
Also, I’ll show several examples of the Free Form Exploration reports where you can see your scroll data.
Table of Contents
– Here’s what you will learn in this guide –
- Two Approaches
- Disable automatic scroll tracking in GA4
- Configure a Scroll Trigger
- Enable Scroll Variable(s)
- Configure the GA4 event tag
- Test Everything and Publish
- Scroll tracking reports in Google Analytics 4
- Final words
Video tutorial about scroll tracking in GA4
If you prefer video content, here’s a tutorial from my Youtube channel.
Note: The GA4 interface has slightly changed since I recorded this video. Debugview is not located at Admin > Debugview.
Google Tag Manager template
I also prepared a Google Tag Manager container template (a.k.a. recipe) to save you some time. You can download it here.
Two Approaches of Scroll Tracking in GA4
You have probably heard that Google Analytics 4 has a much more flexible data model than its predecessors. But with great flexibility comes greater responsibility. Thus, you have to decide beforehand how you will name and structure your scroll events. There are mainly two approaches:
- One event name scroll with the parameter percent_scrolled (this approach is based on what Enhanced Measurement is tracking)
- Unique event name for every scroll threshold, e.g., scroll_25, scroll_50, scroll_75, scroll_90 (or any other similar taxonomy). In this case, there is no need to have the percent_scrolled parameter because we can already see it in the list of events.
Which one should you choose?
The first approach (event name scroll + percent_scrolled parameter) requires registering a custom dimension (if you want to see it in Looker Studio), and you can have up to 50 custom dimensions per GA4 property. If you are close to reaching the limit, this option might not be right for you. But if you want to see/use the dimension only in the GA4 interface, then there is a built-in “Percent scrolled” dimension for that.
The second approach (unique event name for each scroll threshold, e.g., scroll_25, scroll_50). This solution is a bit more convenient in reports like Path exploration, but if you decide to go with 10 thresholds, it means 10 different event names in the list/report. Will that be convenient for you?
So it’s up to you to decide which option to choose.
Actually, right now I prefer the 3rd approach, a combination of both: send event names like scroll_25 and then also include a percent_scrolled parameter if I ever decide to use the Percent scrolled dimension in your GA4 reports (and sometimes that is useful).
Now, let’s move to the actual configuration.

Disable automatic scroll tracking in GA4
Since we will configure custom scroll tracking with Google Analytics 4, there is no need to keep the native one enabled. We are taking over control!
In Google Analytics, go to Admin > Data Streams > Select your web data stream. Then click the Gear Icon…
…and disable Scroll tracking. Click Save.
Configure a Scroll Trigger
Even though Google Tag Manager has scroll-tracking capabilities, they are disabled by default.
Go to Google Tag Manager > Triggers > New > Scroll Depth and enter the following settings:
If you want, you can change the percentages or apply other tweaks. The configuration you see above is the most common one.
Save the trigger.
Enable Scroll Variable(s)
Even though we need just one scroll variable in this setup, you can enable all of them in the container (there won’t be any significant negative impact on your page performance). Go to Variables > Configure (in the Built-in variables section) and enable all scroll-related variables:
Configure the GA4 event tag
Now, it’s time to configure the GA4 event tag that will send the scroll event. In this part, I presume that you already know some GA4 basics and have installed the GA4 tag in GTM.
But if you haven’t created the new Google tag yet, let’s start by navigating to Tags > New > Google Analytics > Google Tag. Enter your Tag ID (a.k.a. measurement ID) in the box, and the final settings should look like this.
If you are wondering why do I have something with curly braces {{, that’s because it’s possible to store the GA4 measurement ID in a variable and then use it in the tag.
Once you have the Google tag created in Google Tag Manager, it’s time for you to choose which approach you are going to implement:
- One event scroll with the parameter percent_scrolled?
- Multiple scroll event names (one for each threshold) and no custom scroll-related parameters
Option #1: One scroll event with a parameter
In Google Tag Manager, go to Tags > New > Google Analytics > GA4 Event and enter the following settings.
Here, we are following the naming convention of Enhanced Measurement. Every time a visitor passes a certain scroll threshold (that is configured in your scroll trigger), this event tag will fire, and together with the scroll event, you’ll also send the percent_scrolled custom parameter.
If you want to use the percent_scrolled parameter in reports, there is a default Percent Scrolled dimension. I will later show it to you.
Once you start sending scroll events, you will start seeing them in your reports within 24-48 hours.
Option #2: Multiple event names (one for each scroll threshold)
If you decide to go with this approach, go to Tags > New > Google Analytics > GA4 Event and enter the following settings (that’s in Google Tag Manager):
Here, we are using the same Scroll Depth Threshold variable, but this time, it’s inserted in the event name. So if a visitor scrolls past the 25% threshold, the event’s name will be scroll_25. If it’s 50% — scroll_50, etc.
Also, I think a good practice would be to include the percent_scrolled parameter in this event, too (even though I did not display it in the screenshot above).
Test Everything and Publish
Now, let’s test everything. In Google Tag Manager, click the Preview button in the top-right corner. Then enter the URL of your website where you will test the scroll tracking and click Start.
After being redirected to your website, scroll down (at least below the 50% threshold).
Then go back to the Preview mode (make sure you are checking your current container).
You should see at least two Scroll Depth events in the preview mode. Click any of them and check if your GA4 event tag is fired. Then check another one:
You can also click on a tag, then switch to Values, and see what kind of data was sent to Google Analytics.
And now, we have to check whether GA4 actually received the data. In Google Analytics, go to DebugView (it’s located at Admin > Debugview). If there is more than one device, you’ll have to find yours (in the top-left corner of the DebugView).
How can you know which one is yours? Well, one of them should be sending scroll events. Maybe that will help to distinguish.
If everything is configured correctly, you should start seeing either scroll or scroll_xx events. You can click them and check what other parameters were sent with it.
In the screenshot below, you will see what the event should look like by following the first approach.
If everything is good, go to Google Tag Manager, click SUBMIT in the top-right corner, and then PUBLISH.

Scroll tracking reports in Google Analytics 4
Once you start tracking scroll in Google Analytics 4, you must wait up to 24-48 hours to see the data in regular reports.
You will see the new scroll event(s) in Reports > Engagement > Events list (on the left sidebar).
If you click that event, you will see several additional charts about it.
If you want to see scroll data on a particular page of your website, you can go to Explore > Free Form report and do some additional configuration.
Configuration #1a: If you use one scroll event name + you want to analyze scrolling on one page
In the Variables column of Exploration, click the plus icon next to Dimensions.
- Find and add the Percent Scrolled dimension (it’s available in the GA4 interface by default).
- Also, add the Page Path dimension
Then in the Tab Settings column, add the Percent Scrolled dimension in the Rows section.
Leave nothing in the Columns section.
In the Values section, add Active Users and Event Count.
In the Filters section, add two filters:
- The event name exactly matches scroll
- And if you want to narrow down to a particular page, you can enter another filter with Page Path contains xxxxx (for example, /pages/contact-us/). Remember, Page Path does not contain a domain. You can see the examples of Page Paths in your GA4 > Engagement > Pages and Screens (and then switch to the Page Path and Screen Class above the table).
Then the report might look something like this:
In this report, you can see how many people on a particular page reached certain scroll thresholds.
Configuration #1b: If you use one scroll event name + analyze multiple pages
This is an alternative variation of the previous configuration. In #1a example, we narrowed it down just to a single page. In this example, we will see multiple pages in the same table.
In the Variables column of Exploration, click the plus icon next to Dimensions.
- Find and add the Percent Scrolled dimension (this is a built-in GA4 dimension).
- Also, add the Page Path dimension
Then in the Tab Settings column, add the Page Path dimension in the Rows section. Select to show 25 rows (or even more).
Add Percent Scrolled dimension in the Columns section
In the Values section, add Event Count.
In the Filters section, add the following filters:
- Event name exactly matches scroll
- Percent Scrolled does not exactly match (not set) (if this is bothering you and there aren’t many events that meet this criterion. Otherwise, you should identify and fix the “not set” problem.).
Then the report might look something like this:
As of the moment of recording this video, it looks like you can sort data only by the Totals column. Hopefully, that will change in the future.
Configuration #2a: If you use multiple scroll event names + analyze one page
If you decided to go with distinct events for each scroll threshold (e.g., scroll_25, scroll_50, etc.), then here’s a sample report that you could create for a particular page.
In the Variables column of Exploration, click the plus icon next to Dimensions. Find and add the Page Path dimension and Apply it.
Then in the Tab Settings column, add the Event Name dimension in the Rows section.
Leave nothing in the Columns section.
In the Values section, add Active Users and Event Count.
In the Filters section, add the following filters:
- The event name contains scroll (if your event names are scroll_25, scroll_50, etc.). That way, we will match all scroll events regardless of the full event name.
- And if you want to narrow down to a particular page, you can enter another filter with Page Path contains xxxxx (for example, /pages/contact-us/). Remember, Page Path does not contain a domain. You can see the examples of Page Paths in your GA4 > Engagement > Pages and Screens (and then switch to the Page Path and Screen Class above the table). See configuration #1a in this blog post for more details.
Then the report might look something like this:
Here we see how many users have scrolled past 25%, 50%, and other thresholds on a particular page of the website.
Configuration #2b: If you use multiple scroll event names + analyze multiple pages
This is an alternative variation of the previous configuration. In the #2a example, we narrowed it down just to a single page. In this example, we will see multiple pages in the same table.
In the Variables column of Exploration, click the plus icon next to Dimensions. Find and add the Page Path dimension and Apply it.
Then in the Tab Settings column, add the Page Path dimension in the Rows section. Select to show 25 rows (or even more).
Add the Event name dimension in the Columns section
In the Values section, add Event Count.
In the Filters section, add the following filter: Event name contains scroll.
Then the report might look something like this:
Here you can see your “most scrolled” pages and how the drop-off changes on each threshold.
Scroll Tracking with Google Analytics 4: Final words
And that’s the end of yet another Google Analytics 4 blog post here on Analytics Mania. There are mainly two approaches you can choose from if you decide to customize scroll tracking:
- Track a single event with an additional parameter for scroll thresholds
- Or not use any parameters but include the threshold in the event name instead
In the beginning, I was using the “single event name” approach, but over time, the 2nd approach became more and more appealing.
If you are just starting with GA4 in general and it looks confusing, download my free GA4 ebook below.
33 COMMENTS
Hey Julius,
Pablo here, new to GTM. (:
I have found an interesting thing:
When then page is reloaded and its position is not at the top, it still triggers the vars, when in reality I have not scrolled.
I read an article by Simoa on how to fix that with U GA:
function() {
return {{Scroll Depth Threshold}} === 25;
}
However, how am I able to fix it with GA4?
Thank you very much!
The solution does not care whether this is GA4 or UA. It will work anyways. Just insert variables in GA4 event tag
Hey Julius, I am glad I have found this website. Thanks.
I have been trying to come up with a solution to differentiate scroll tags on my pages because of my comments. Basically, I set 80% for full post scroll. However, when I have many comments, full post scroll would actually be 50%, but others page it will roughly be at 80%. Is there another calculation to resolve that?
Thanks
Hi Tiago,
You could try an impression event for an element on the bottom of the page. That way, no matter how many comments get added on, it will always be in the same spot. Use the element visibility trigger in GTM and set it to only fire on a specific element at the bottom of the content portion of the page.
Hello Julius,
Thanks for the blog !
I have a question : If an user scroll after the 50% of the page, does it counts like scroll_25 and scroll_50 or only scroll_50 ?
scroll_25 and scroll_50
Hi Julius, how would scroll events affect the bounce rate? In GA4, engagement is defined as a session that includes two or more engaged events. If someone scrolls 50% of the page and bounces, wouldn't website with short pages have biased representation of the bounce rate and engagement rate? How would you approach the issue?
Scroll tracking does not affect bounce rate in GA4
Sounds like it works fine. If you want to see percentages in GA4 interface, custom dimension is no longer needed. There is a standard dimension for that.
Hey Julius,
when using approach one with the default "scroll" event it's not necessary to setup a custom dimension for percent_scrolled. percent_scrolled is (now) a default Dimension of GA4.
Event Name: scroll
Event Parameters:
Parameter Name: percent_scrolled
Value: {{Scroll Depth Threshold}}
________
Please don't delete comments when they are good quality and help others. Or was there any Problem with my comment?
Hi, thanks. I just updated the article 30 minutes ago to include that update
Hi, I am taking your classes and find EVERYTHING very helpful. At the end of this blog, you say "In the beginning, I was using the “single event name” approach, but over time, the 2nd approach became more and more appealing."
Why is that? Do you think there is more flexibility in reporting when you use the second approach? Can you give us any examples?
+1. Looking for the reasoning behind suggesting the second approach
Because of the Path Exploration. In path exploration, you see just event names, no parameters. So if you see "Scroll", you don't know if that was a 25% scroll, 50, or more
Hi Julius,
The issue I'm having is when there's a history change, or when I go to another page on the website and scroll, it doesn't trigger another scroll depth event. Any advice on how to address this issue?
Hi Julius, your guides have been incredibly helpful to me - thank you
I have implemented the scroll events (scroll_50, etc). What I would like to do is for the engagement time to update whenever one of these scroll events fires.
In the example below I would like user engagement to be 1 minute instead of 0 seconds.
I have the following data:
User Engagement: 0m 00s
page_view: 4:29:56
session_start: 4:29:56
first_visit: 4:29:56
scroll_10: 4:30:00
scroll_20: 4:30:03
...
scroll_90: 4:30:56
How could we track certain sections of the page instead of just the percentage? For instance if the user scrolls to a specific paragraph.
Hi Julius,
Huge fan here, thank you so much for your guidance on all things GA. Quick question: using exploration Configuration #1a I am seeing only scroll_90 in the columns. I've confirmed in GTM that scroll_25,50, and 75 are all firing correctly - do you know why they may not be populating in the exploration?
Thank you!
Best,
Chris G.
Hi Julius
I'm having awful trouble trying to get data from the 'One scroll event' approach.
I've followed your instructions, and debug in GTM and GA4 both are picking up the percentage scrolled value - but in Explore reports and Looker Studio it won't come up.
The Custom Definition just comes back with a 'null' value for each - despite the fact the value is showing up in both debugs modes and occasionally real time tracking.
I've also tried using a custom field to pull and label the data in Looker, but it isn't working either. All custom labels still show as 'Null' (despite having some counts).
Did I miss something?
Hi Julius,
I have a question, I did exactly what the guide said, nevertheless I keep getting the tag fired when my home screen is loaded, with all of the percentages, and when I actually scroll the tags are not activated, I configured it with option #2. Could you help me? Thanks a lot for the info.
I am having scroll depth is not a function issue. the same code works on other pages but on one of my pages the scroll depth fails. I have tried adding the script dynamically, the script loads but scroll depth still fails . how else can i tackle this issue ?
What if I am trying to track infinite scroll?
I've experimented with how I display the the scrolls, an d sometimes, it tells me there have been 0 views but 1 instance of "scroll_50". How can this be? It was an active session, yet the page view is 0. Hmm.
Hi Julius, thanks for all these very useful tips! I manage to get the scroll tag fire and see the percent scrolled but ine thing seems wrong. I have double checked everything and I only get :
Type
Unknown Tag Type
Firing Status
Succeeded
in tne GTM preview window. Therefore, I don't see the percentage and other infos as in your video (5:01). Any clues?
How can we see the the Scroll Depth analysis on Google Analytics-4 reports for a website?
I have added a custom parameter of scroll depth on google tag manager and configured the event by adding custom event on Google Analytics-4 it worked fine at the start and have reflected on reports after 24hours.
Issue Now: In Google Analytics the the reports for scroll depth parameter come up as the (not set) and is not reflecting on reports even though there is traffic and can see data for custom scroll depth parameter is fetched in debug mode of GA-4.
As I am beginner encountered this issue anyone who can help on this would be great!
xHi Julius, well done for your guide, thanks for share with us. I followed the guide with Option #2: Multiple event names (one for each scroll threshold), but it doesn't work properly with a website developed as a Single Page Application. On the landing page Scroll Depth Event work properly, but when continue browsing, event doesn't fired. Also if I used as trigger, History Source matches the regular expression pushState.
How can fix it? Thanks for your answer.
I admire your blog.
Following the comment of Pier
Hi Julius,
thank you for your great guide!
I have a similar issue with the scroll depth event but on normal websites as well (not SPA):
With deleted cache/cookies gtm.scrollDepth is pushed automatically into the dataLayer without any problems.
But few clicks later or in the next browser session it's not pushed anymore.
Have anybody of you the same issue and/or know how to fix this?
Thanks and best regards
Hagen
Hi,
So I have been trying to add the scroll dept to a particular section of the website, basically I have a div with a particular id and I want tag manager to trigger a scroll event event when a user scrolls on this particular div, can you please give steps or explanation on how to do that.
Thank you
having an issue where the {{Scroll Depth Threshold}} doesn't return a number. Any ideas why this would be.
What does it return?
It was only returning 90, so i turned off scroll in enhanced measurements (web data stream) to see if that was causing the issue and now it doesn't show anything. thanks for responding so quickly
Scroll variables start working only after you create the scroll trigger