Skip to content

Commit 49448f5

Browse files
authored
[Tracker] Use ResizeObserver instead of polling for document height (#6174)
* Use ResizeObserver instead of polling for document height * fix: avoid forced reflow in getCurrentScrollDepthPx window.scrollY and window.innerHeight are compositor-cached values that never trigger layout recalculation, unlike el.scrollTop and el.clientHeight. The fallbacks only existed for IE which is already unsupported. * disable engagement tracking in compat mode * Add changelog entry * Bump tracker script version * Add COMPAT fallback for engagement tracking * Fix lint * Fix formatting issues * fix: use hkps keyserver to avoid blocked port 80 in CI * fix: fetch ClickHouse key via curl instead of keyserver * chore: print PR labels in workflow for debugging * Revert "chore: print PR labels in workflow for debugging" This reverts commit 4fb22a7. * Add tracker script changelog entry
1 parent a2c8765 commit 49448f5

5 files changed

Lines changed: 39 additions & 26 deletions

File tree

.github/workflows/tracker-script-update.yml

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,12 @@ jobs:
3030

3131
- name: Install jq and clickhouse-local
3232
run: |
33-
sudo apt-get install apt-transport-https ca-certificates dirmngr
34-
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 8919F6BD2B48D754
35-
echo "deb https://packages.clickhouse.com/deb stable main" | sudo tee \
36-
/etc/apt/sources.list.d/clickhouse.list
33+
curl -fsSL 'https://packages.clickhouse.com/rpm/lts/repodata/repomd.xml.key' \
34+
| sudo gpg --batch --yes --dearmor -o /usr/share/keyrings/clickhouse-archive-keyring.gpg
35+
echo "deb [signed-by=/usr/share/keyrings/clickhouse-archive-keyring.gpg] https://packages.clickhouse.com/deb stable main" \
36+
| sudo tee /etc/apt/sources.list.d/clickhouse.list
3737
sudo apt-get update
38-
39-
sudo apt-get install jq clickhouse-server -y
38+
sudo apt-get install -y jq clickhouse-server
4039
4140
- name: Compare and increment tracker_script_version
4241
id: increment

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ All notable changes to this project will be documented in this file.
2727
- Moved graph interval picker, export button, imported data toggle and notices out of the graph and into a new options menu in the top bar
2828
- Standardised and improved segment and filter modals styling
2929
- Changed graph tooltip positioning logic: it now aligns to the top of the chart, to the right of the hovered data point
30+
- Use ResizeObserver instead of polling in tracker for scroll depth. Removes forced reflows caused by the tracker script.
3031

3132
### Fixed
3233

tracker/npm_package/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## Unreleased
99

10+
## [0.4.5] - 2026-05-05
11+
12+
- Use ResizeObserver over polling for getting scroll metrics
13+
1014
## [0.4.4] - 2025-10-31
1115

1216
- Convert all TypeScript definition comments from `//` style to JSDoc `/** */` style for better IDE integration and TypeScript tooling support

tracker/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"tracker_script_version": 33,
2+
"tracker_script_version": 34,
33
"type": "module",
44
"scripts": {
55
"lint": "eslint",

tracker/src/engagement.js

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -137,11 +137,21 @@ function getDocumentHeight() {
137137
}
138138

139139
function getCurrentScrollDepthPx() {
140-
var body = document.body || {}
141-
var el = document.documentElement || {}
142-
var viewportHeight = window.innerHeight || el.clientHeight || 0
143-
var scrollTop = window.scrollY || el.scrollTop || body.scrollTop || 0
144-
140+
var viewportHeight, scrollTop
141+
if (COMPILE_COMPAT) {
142+
var el = document.documentElement || {}
143+
var body = document.body || {}
144+
viewportHeight = window.innerHeight || el.clientHeight || 0
145+
scrollTop =
146+
window.scrollY ||
147+
window.pageYOffset ||
148+
el.scrollTop ||
149+
body.scrollTop ||
150+
0
151+
} else {
152+
viewportHeight = window.innerHeight
153+
scrollTop = window.scrollY
154+
}
145155
return currentDocumentHeight <= viewportHeight
146156
? currentDocumentHeight
147157
: scrollTop + viewportHeight
@@ -151,23 +161,22 @@ export function init() {
151161
currentDocumentHeight = getDocumentHeight()
152162
maxScrollDepthPx = getCurrentScrollDepthPx()
153163

154-
window.addEventListener('load', function () {
155-
currentDocumentHeight = getDocumentHeight()
156-
157-
// Update the document height again after every 200ms during the
158-
// next 3 seconds. This makes sure dynamically loaded content is
159-
// also accounted for.
160-
var count = 0
161-
var interval = setInterval(function () {
164+
if (COMPILE_COMPAT) {
165+
window.addEventListener('load', function () {
162166
currentDocumentHeight = getDocumentHeight()
163-
if (++count === 15) {
164-
clearInterval(interval)
165-
}
166-
}, 200)
167-
})
167+
var count = 0
168+
var interval = setInterval(function () {
169+
currentDocumentHeight = getDocumentHeight()
170+
if (++count === 15) clearInterval(interval)
171+
}, 200)
172+
})
173+
} else {
174+
new ResizeObserver(function () {
175+
currentDocumentHeight = getDocumentHeight()
176+
}).observe(document.documentElement)
177+
}
168178

169179
document.addEventListener('scroll', function () {
170-
currentDocumentHeight = getDocumentHeight()
171180
var currentScrollDepthPx = getCurrentScrollDepthPx()
172181

173182
if (currentScrollDepthPx > maxScrollDepthPx) {

0 commit comments

Comments
 (0)