Skip to main content

Client

activity.current

The currently active activity instance, or null if none is running.

activity.start(params)

Creates and starts a new activity tracker. Heartbeats begin immediately unless time: false is passed.
Only one activity can be active at a time. Calling start() while an activity is already running throws an error. Await end() on the current activity before starting the next one.
string
required
Activity slug: a stable, URL-safe identifier for the learning object (e.g. "fractions-with-like-denominators"). Used to construct the canonical activity URL in Caliper events.
string
required
Human-readable display name (e.g. "Fractions with Like Denominators"). Sent as object.activity.name in Caliper events.
object
required
Course selector: must match a course in timeback.config.json. Either { subject, grade } or { code }.
string
UUID for correlating events across sessions. Arbitrary strings are rejected by the HTTP handlers. If omitted, the SDK generates a new UUID. Pass the same runId when resuming a stateful activity to link heartbeats with the eventual completion event.
object | false
Time tracking configuration. All fields are optional: defaults work well for most apps.
Set to false to disable client-side time tracking entirely. When disabled, no heartbeats are sent, no visibility handlers are registered, and end() skips the final time flush. Use this when e.g. time is managed server-side.
(error, context) => void
Called when a time-spent flush or completion submission fails. For regular heartbeats, fires after the configured retries are exhausted. Completion sends and page-exit sends do not use that retry schedule. Time-spent errors are non-fatal: the SDK continues tracking. Completion errors (from end()) are also surfaced here before being re-thrown.
() => void
Called when the activity is paused, either explicitly via pause() or automatically when the hidden timeout fires.
() => void
Called when the activity resumes, either via resume() or when the user returns after a hidden timeout.
(elapsedMs: number) => void
Called after a heartbeat request succeeds, or after the browser accepts a page-exit beacon for delivery. Beacon acceptance does not confirm server storage. The argument is the active milliseconds in that window.

Examples

Activity instance

The object returned by activity.start().

Properties

string
The activity slug passed to start().
Date
When the activity was started.
boolean
Whether the activity is currently paused.
boolean
Whether end() has completed successfully.
Once true, the activity is no longer active and a new one can be started.
string
Unique identifier correlating heartbeats and completion events for this run.
number
Cumulative locally measured active time, including windows whose sends failed, plus the current window. This is not a server-confirmed total.
number
Active time for the current heartbeat window only. Resets to 0 after each flush.

Methods

Flushes accumulated time, then stops heartbeats until resume() is called. Fires onPause if provided.
Starts a fresh tracking window and restarts heartbeats. Fires onResume if provided.
Promise<void>
Attempt to flush accumulated time to the server. Failures are reported to onError and swallowed, so a resolved promise is not proof of delivery. No-op when time tracking is disabled or the activity is paused. Serialized — only one flush can be in flight at a time.
onPause and onResume callbacks also fire for automatic state changes like hidden timeouts — use them to keep your UI in sync without polling isPaused.

activity.end(data?)

Ends the activity. Attempts a final time flush when automatic time tracking is enabled. If completion data is provided, also sends an ActivityCompletedEvent.
If the completion call fails, the activity remains usable so the caller can retry. A heartbeat failure alone does not reject end(). onError fires with { type: 'completion' } before the error is re-thrown.

Completion data

number
required
App-supplied XP for this activity. Follow the agreed XP policy; the SDK cannot infer it from time spanning multiple sessions.
number
Total questions in the activity. Must be paired with correctQuestions.
number
Questions answered correctly. Must be paired with totalQuestions.
number
Number of new units (lessons) the student mastered during this activity. This is an incremental count, not a cumulative total. The server sums these across submissions and divides by totalLessons to auto-compute pctComplete when it is omitted. See Course progress for details.
number
Course completion percentage (0—100). If omitted and masteredUnits is provided, the server auto-computes this from EduBridge enrollment analytics when available. The browser submission handler clamps explicit values to 0–100; the TypeScript server recording API rejects values outside that range.
The reviewed browser implementation does not read end({ time: ... }), even though the exported type contains a time field. Do not use it for offline time imports. Report explicit time through the server activity.record({ time: ... }) API below, and disable automatic heartbeats for the same time interval.
totalQuestions and correctQuestions must be provided together.
If you provide one, you must provide the other.

Server

timeback.activity.record(params)

Records an activity completion from the backend. Sends an ActivityCompletedEvent to the Caliper API after resolving the user and synced course. Gradebook and XP processing continues downstream; this promise does not acknowledge those outcomes. At 100% progress an additional mastery-completion write is attempted; its failures are logged rather than propagated.
The optional time event is sent after completion, in a separate request. Failure can leave partial success; your app must reconcile retries. A shared runId correlates events and does not make these writes one transaction.
See the server adapter docs for setup.
object
required
Student identity. Provide email (required) and optionally timebackId. See Identity for how users are resolved.
object
required
Activity identity.
object
required
Completion metrics.
object
Optional time data. Include when the backend tracks accumulated session time — for example, when the frontend uses time: false, or for offline sync and batch imports.
string
UUID correlating this completion with frontend heartbeats. Should match the runId persisted when the activity was started on the client.
totalQuestions and correctQuestions must be provided together.
If you provide one, you must provide the other.

Examples

With time data

Only include time when the frontend uses time: false, meaning your server owns time tracking. Do not pass time here if the frontend is sending heartbeats (the default), or time will be double-counted.