When to use
Choose your model
The SDK supports two activity models. Both use the same continuous time tracking under the hood; the difference is in how completion is handled.Single-session
Completed in one sitting. Client tracks time and reports completion.
Stateful
Spans multiple sessions. Client tracks time, server records completion.
How time tracking works
Both models use continuous heartbeat-based time tracking. Rather than accumulating time and reporting it once at the end, the SDK sends periodic updates throughout the session. Each update reconciles a time window, reporting how many milliseconds were active and how many were inactive. Heartbeats begin automatically when you callactivity.start() and repeat at a regular interval (default 15s), and are sent as TimeSpentEvents.
Why this matters
- Periodic delivery attempts reduce dependence on a final browser-exit request. They do not guarantee a maximum loss window: network failures and browser shutdown can lose reports.
- Accurate per-window timestamps: each event represents the actual engagement window
- Visibility-aware by default: visibility changes pause active-time accumulation. This measures visible time, not proof of attention.
Abandoned tab detection
If a tab stays hidden for an extended period (default 10 minutes), the SDK stops heartbeats entirely. When the student returns, tracking resets from a clean slate. This prevents counting hours of abandoned-tab time.Heartbeat windows advance before the network request. Failed sends are reported through
onError and are not durably buffered. Automatic heartbeat retries default to zero. Page-exit delivery is best effort.Event correlation with runId
Every activity is identified by a runId, a unique identifier generated at activity.start().
All heartbeats, as well as the final completion event, share the same runId, which allows downstream systems to correlate time-spent data with completion results.
For stateful activities, your app must persist and reuse the UUID runId when the student resumes, so heartbeats from different sessions are still correlated with the same completion event.
Pause and resume
Both models support pause and resume. Paused time is not counted as active. The SDK distinguishes active and inactive milliseconds in every heartbeat. When paused, the SDK flushes accumulated time and stops heartbeats. On resume, it starts a fresh tracking window. OptionalonPause and onResume callbacks fire on both explicit calls and automatic state changes like hidden timeouts.
See pause() and resume() in the reference for usage.
Configuration
Custom activity tracking requires a Caliper sensor URL in yourtimeback.config.json.
See the configuration reference for sensor resolution rules and environment overrides.
Next Steps
Single-session
Client-driven activities completed in one sitting
Stateful
Multi-session activities with server-side completion
Reference
Parameters, properties, methods, and callbacks
Configuration
Full timeback.config.json reference
Getting started
Step-by-step setup guide for integrating existing apps