Engagement
Clickport measures engagement beyond simple pageviews. The tracker automatically records how far visitors scroll and how long they actively spend on each page. These signals combine into a unified engagement score that appears across dashboard panels.
Scroll depth
Scroll depth is the maximum vertical scroll position a visitor reaches on a page, expressed as a percentage from 0 to 100. The tracker calculates this by dividing the current scroll position by the total scrollable height of the document.
For each page a visitor views, Clickport records the furthest point they scrolled to. The value only increases. If a visitor scrolls to 78% of a blog post, that 78% is stored. If they scroll back up, the maximum remains 78%.
How it works
The tracker listens for scroll events and computes the percentage on every scroll. A ResizeObserver monitors the document body so that the scrollable height is recalculated when the page layout changes. This keeps percentages accurate on responsive pages or single-page applications where content loads dynamically.
Per-page vs session averages
Scroll depth is tracked per page, not per session. If a visitor views three pages with scroll depths of 60%, 80%, and 40%, those individual values are stored separately. The Pages panel shows per-page scroll, while the KPI bar and Sources panel show session-level averages.
Session duration
Duration measures how long a visitor actively spends on your site. It is calculated from the first event to the last event in each session, but only counts time when the page is actually visible.
Visibility-aware timing
The tracker uses a start-stop timer. When the page loads, the timer starts. When the visitor switches to a different tab or minimizes the browser window, the timer pauses. When they return, it resumes. This prevents inflated durations from abandoned tabs.
Pausing is triggered by two signals:
- Page Visibility API: The
visibilitychangeevent fires when the tab becomes hidden or visible again. - Window focus: The
blurandfocusevents fire when the browser window itself loses or gains focus.
How engagement data is sent
When the visitor navigates away or closes the tab, the tracker sends a final engagement update. This is triggered by both pagehide and beforeunload events for maximum browser coverage. The data is sent using fetch with the keepalive flag, which allows the request to complete even after the page has unloaded.
The tracker also sends incremental updates while the visitor is active. An update is only sent when duration changes by at least 3 seconds or the maximum scroll depth increases. This avoids unnecessary network requests.
30-minute session cap
Individual sessions are capped at 30 minutes (1,800 seconds) when calculating averages. This prevents a single outlier session from skewing your numbers. The cap applies to the KPI averages and panel aggregations. Individual session records in the Sessions panel still show the actual duration.
Engagement score
The engagement score is a 0-100 metric that combines scroll depth and duration into a single number. It appears as a colored percentage in the Sources, Pages, Countries, and other panels.
The formula
The engagement score averages two components, each normalized to a 0-100 scale:
Worked examples
A long blog post averaging 82% scroll and 240 seconds (4 minutes) duration:
- Duration score: min(100, 240 / 6) = 40
- Engagement: (82 + 40) / 2 = 61
A product page averaging 95% scroll and 720 seconds (12 minutes) duration:
- Duration score: min(100, 720 / 6) = 100 (capped)
- Engagement: (95 + 100) / 2 = 98
A landing page averaging 18% scroll and 8 seconds duration:
- Duration score: min(100, 8 / 6) = 1
- Engagement: (18 + 1) / 2 = 10
Color thresholds
Engagement scores are color-coded in dashboard panels to indicate quality at a glance:
- Green (50% and above): High engagement. Visitors are reading thoroughly and spending significant time.
- Orange (25% to 49%): Moderate engagement. Visitors are consuming some content but may not be fully engaged.
- Red (below 25%): Low engagement. Visitors are leaving quickly or not scrolling far.
Bounce rate
Engagement metrics directly influence bounce rate. Clickport defines a bounce as a session meeting all four of these criteria:
This multi-criteria approach is more forgiving than traditional bounce rate, which only checks whether the visitor viewed a single page. For more details, see the KPIs documentation.
Copy detection
Clickport also tracks when visitors copy text from your pages. When a visitor selects and copies content, the tracker captures the event along with the first 200 characters of the copied text. This appears in the Sessions panel when you drill into individual sessions.
Copy events are a useful engagement signal. They often indicate that a visitor found your content valuable enough to save or share.
Data flow
Engagement data follows this path from the visitor's browser to your dashboard:
- Tracker monitors activity: The engagement module tracks scroll position and accumulated visible time in real-time as the visitor interacts with the page.
- Incremental updates: The tracker sends updates only when duration changes by at least 3 seconds or the maximum scroll depth increases. This keeps network overhead low.
- Pageleave event: When the visitor navigates away or closes the tab, a final
pageleaveevent carries the total duration (in milliseconds) and maximum scroll depth (0-100). - Session update: The API receives the event and updates the session record.
max_scroll_depthis set to the highest value seen across all pages in the session.durationis calculated as the time between the session start and the latest event. - Bounce recalculation: On every session update, the bounce flag is recalculated using the four criteria above.
- Dashboard queries: Panels aggregate scroll depth and duration across sessions, apply the engagement formula, and display the color-coded result.
pagehide and beforeunload events to maximize reliability across browsers. Data is sent with fetch and keepalive: true, which allows the request to complete after the page begins unloading.