Engagement
Clamp measures engagement the honest way: visible seconds only. A tab in the background does not count. A user who opens a page and walks away does not count after they stop looking.
How time is counted
When a pageview fires, the SDK starts a per-second counter gated on document.visibilityState === "visible". Every second the tab is visible, the counter ticks. Background tabs, minimized windows, and the prerender state all pause it.
When the user leaves the page (navigation, tab close, SPA route change), the SDK sends a pageview_end event with the accumulated engagement_seconds value. The event is sent via navigator.sendBeacon so it survives unload.
The pageview_end event
pageview_end is a system event emitted automatically after each pageview. It does not count against your plan limits and you cannot emit it manually.
{
"name": "pageview_end",
"pathname": "/pricing",
"properties": {
"engagement_seconds": "42"
},
...
}Pages with less than 1 second of visible time are dropped. This eliminates noise from prefetches, bfcache restores, and SPA thrash.
Bounce rate
A bounce is a session with exactly one pageview. The overview bounce rate is bounced_sessions / total_sessions. Clamp does not try to get clever with time thresholds — one pageview, you bounced; two or more, you did not.
Bounce rate is available on get_overview, per-page viapathname filter, and by cohort via get_funnel on a single-step funnel.
Per-page engagement
The get_page_engagement MCP tool returns per-page median and average engagement seconds, plus bounce rate for each page.
"Which pages hold attention the longest?"
→ get_page_engagement({ period: "30d", sort: "median_engagement_desc" })
"What's engagement like on /pricing?"
→ get_page_engagement({ pathname: "/pricing" })The tool returns median alongside average because page engagement distributions are skewed: one reader who leaves a tab open for an hour can pull the mean in directions that are not useful.
Session paths
A session path is the ordered sequence of pages a visitor viewed in one session. The get_session_paths tool returns the most common paths, with entry page, exit page, and visitor counts.
"What's the most common path through the site?"
→ get_session_paths({ period: "30d", limit: 10 })
"Where do visitors who land on /blog go next?"
→ get_session_paths({ entry: "/blog" })Useful for finding unexpected navigation patterns: which blog posts drive signups, which feature pages lead to pricing, where people get stuck in loops.
Sessions
A session ends after 30 minutes of inactivity. The SDK stores the session ID in sessionStorage, so it survives reloads within the same tab but not across tabs or browser restarts. Average session duration in the overview is derived from pageview_end events summed within each session.
Pitfalls
- Prerender and bfcache.Pages restored from bfcache fire a new pageview, so engagement resets. Prerendered pages don’t accumulate visible time until the user focuses them.
- Zero-second visits. Intentionally dropped. If you need to know a page was opened at all, use the
pageviewcount, not the engagement seconds. - SPA apps.Route changes fire a new pageview and finalize the previous page’s engagement. A user scrolling through many routes will generate many
pageview_endevents, each with the visible time for that specific route.