page_leave

A page was left. Carries visible time and how far down the reader got.

FieldValue
Namepage_leave
Severity9 (INFO)
Written byBrowser tag.
Turned off bydata-track-leave="false"

When it fires

Once per page view, at whichever comes first of the tab being hidden, the page unloading, and a client-side navigation to a different path.

Once, not twice. visibilitychange and pagehide both fire on the way out of a visit, and a second entry would double the denominator of every average built on this one.

A single-page app gets one before each new page_view, so time on page describes every route rather than only the last one somebody happened to be standing on.

Attributes

AttributeTypeWhat it holds
firstrun.duration_msnumberVisible milliseconds. The clock stops while the tab is hidden and starts again when it comes back.
firstrun.scroll_pctnumber0 to 100. The deepest point reached, not where they happened to be at the end.

Every entry also carries the resource its client sends once per batch: session.id, user.id once you have called user(), and the rest of the list on the overview. Anything you pass yourself lands in the same map, and your key wins on a collision.

What it never carries

No url. The entry says how long and how far, not where, so a page_leave cannot be grouped by page on its own. Its session.id is the join back to the page_view that preceded it.

The clock is visible time and not wall clock. A tab left open behind twelve others for an hour did not hold anyone's attention for an hour, and an average that says it did is worse than no average. There is no mouse track, no heatmap and no per-element dwell.

Questions it answers

A widget is a filter, a group by, an aggregate, a time bucket and a limit. These are those five parts written out, and every one of them is something you can build yourself.

QuestionThe query
Average time on pageName is page_leave . average of firstrun.duration_ms
How far people scrollName is page_leave . average of firstrun.scroll_pct
Whether engagement is movingName is page_leave . average of firstrun.duration_ms . bucket by day
The slow tailName is page_leave . 90th percentile of firstrun.duration_ms

See also