How it works
Once started, the SDK sends periodic TimeSpentEvents throughout the session. When the student finishes, the SDK sends one final TimeSpentEvent followed by an ActivityCompletedEvent. All events share the samerunId for correlation.
Starting an activity
Every single-session activity starts the same way:See the
reference for
full parameter documentation including time options, callbacks, and
runId.Ending an activity
How you end an activity depends on whether the student completed the activity. In both cases, accumulated time data is flushed. The difference is whether a completion result is also recorded.With completion
When a student finishes, callactivity.end() with completion metrics:
- Flushes a final heartbeat (
TimeSpentEvent) - Submits the completion (
ActivityCompletedEvent)
See the reference
for full completion data documentation.
Without completion
Callactivity.end() without arguments to flush time data only; in this case, no completion event is recorded.
- Flushes a final heartbeat (
TimeSpentEvent) - Stops the heartbeat timer
- Cleanup: the component unmounts before the student finishes (e.g. navigating away mid-activity). You want to flush accumulated time without recording a result.
- Stateful activities: the activity spans multiple sessions, so the client only tracks time per visit. Completion is recorded by the server when the student eventually finishes.
Framework integration
Start tracking after the browser client is initialized and the current user is verified. Use the React, Vue, Svelte, or Solid verification API. A client object alone does not establish authentication. Keep one activity owner for your lesson screen. Awaitend() before starting the next activity, including navigation and development-mode remounts. Async cleanup is not awaited by framework unmount hooks; starting immediately in the next mount can otherwise throw “An activity is already active.”
This example is a browser event handler after initialization and verification. timeback is the initialized SDK client and showLesson is your app’s rendering function:
start(). Capture the activity created by that screen in its cleanup; end it without metrics. Handle a rejected completion in your UI and let the student retry before starting another activity.
Best practices
Start activities in useEffect/onMount
Start activities in useEffect/onMount
Start after initialization and user verification, and serialize activity transitions. Register time-only cleanup for the owning screen.
Flush time on cleanup, complete on user action
Flush time on cleanup, complete on user action
Use
activity.end() (no args) in cleanup functions. Only call activity.end(metrics) when
the student has actually finished the activity.Handle missing timeback client
Handle missing timeback client
Check client initialization and user verification separately.
Use meaningful activity IDs
Use meaningful activity IDs
Use stable, unique IDs that identify the specific lesson or content piece.
Next steps
Stateful activities
Multi-session activities with server-side completion
Reference
Parameters, properties, methods, and callbacks