-
Notifications
You must be signed in to change notification settings - Fork 52
Open
Labels
enhancementNew feature or requestNew feature or request
Description
Summary
Track how long users spend on pages. Requires client-side JS and backends that support updateEvent.
How other tools track duration
| Tool | Metric | Scope | Idle time included? |
|---|---|---|---|
| GA4 | Session duration | Session | Yes (includes idle) |
| GA4 | Engagement time | Per-page | No (pauses on tab switch) |
| Plausible | Engagement time | Per-page | No (pauses on tab switch) |
Session duration = time between first and last event. Simple but misleading - if user opens tab,
walks away for 10 min, comes back, that idle time counts.
Engagement time = actual active time on page. Pauses when tab loses focus or window is blurred.
More accurate measure of user attention.
Our approach: per-page engagement time
We'll track engagement time per page (like GA4's engagement time, not session duration):
- Start timer when page becomes visible
- Pause on
visibilitychange(tab switch) andblur(window focus lost) - Resume on visibility restore /
focus - Send duration when user leaves page
This gives accurate "time spent reading this page" metric.
Design
Client-side (NextlyticsClient component)
// Pseudocode
let startTime = 0
let accumulated = 0
function onVisible() {
startTime = Date.now()
}
function onHidden() {
accumulated += Date.now() - startTime
}
function sendDuration() {
const duration = accumulated + (document.hidden ? 0 : Date.now() - startTime)
fetch('/api/event', {
method: 'POST',
body: JSON.stringify({
type: 'updateEvent',
eventId: currentPageViewId,
patch: { properties: { duration } }
})
})
}Events to listen
visibilitychange- pause/resume timerpagehide- send final duration (more reliable thanbeforeunload)- Optional: periodic heartbeat every 30s for long sessions
Page navigation (SPA)
On client-side navigation:
- Send duration for current page
- Reset timer
- Start tracking new page
Backend requirements
Only backends with supportsUpdates: true can use this feature:
- ClickHouse: yes
- Postgres/Neon: yes
- Segment: no
- PostHog: no
- GA: no (but GA tracks in anyway)
Config
Nextlytics({
trackDuration: true, // default: false
durationHeartbeatMs: 30000, // optional, 0 to disable
})Changes needed
- Add
trackDurationanddurationHeartbeatMstoNextlyticsConfig NextlyticsClientcomponent:- Set up visibility/pagehide listeners
- Track accumulated time
- Send updateEvent on page leave
- Add
type: 'updateEvent'handling to/api/eventroute - Document which backends support this
Metadata
Metadata
Assignees
Labels
enhancementNew feature or requestNew feature or request