Course Progression
How Timeback tracks student progress through courses
Overview
This guide explains how to track a student's course progression using Timeback's mastery-based completion model.
Learning Loops
Every learning application operates on two fundamental time scales:
| Concept | Scope | Duration | Track |
|---|---|---|---|
| Session | Chain of activities in one sitting | Minutes | XP, accuracy, time |
| Unit | Mastery-based goal tied to a standard (may require multiple sessions) | Hours/Days/Weeks | masteredUnits |
Sessions
A session is a single, focused learning activity that students complete in one sitting.
Send an ActivityEvent when students complete sessions to track activity.
Units
A unit is a discrete mastery-based milestone that students work toward across multiple sessions.
When a student demonstrates mastery of a unit, report masteredUnits: 1 in the ActivityEvent sent to Caliper.
When to Report Mastery
Mastery is typically achieved when a session meets minimum accuracy and maximum time thresholds.
For example: completing a quiz with ≥90% accuracy in under 5 minutes might demonstrate mastery.
Your application defines the thresholds that determine when a unit is mastered.
Configuring Course Completion
To track course completion, you need to:
- Define the total number of units in your course/application
- Store this value in a way your application can access it
- Report mastery via activity-completion events as students complete units
Timeback itself does not prescribe where to store the total unit count; this is an application-level concern.
What Are Units?
What constitutes a "unit" depends on your application's structure:
| App Structure | Example Units |
|---|---|
| Level-based | Levels, stages, worlds |
| Rank-based | Ranks, tiers, badges |
| Skills-based | Skills, competencies, standards |
| Module-based | Modules, quizzes, chapters |
| Custom structures | Any discrete learning milestone |
Units are Mastery-Based
Choose units that represent meaningful mastery milestones, not just engagement metrics.
Units should reflect mastery of content, not just time spent or attempts made.
Calculating Progress
Progress Percentage
Course completion is calculated as:
pctCompleteApp = (masteredUnits / totalUnits) × 100| Variable | Description |
|---|---|
masteredUnits | Cumulative total from Timeback analytics or summed activity-completion events |
totalUnits | The total number of masterable units you've defined for your course |
Example Progression
Given a course with 5 total units:
| Session | masteredUnits Reported | Cumulative masteredUnits | pctCompleteApp |
|---|---|---|---|
| 1 | 1 | 1 | 20% |
| 2 | 0 | 1 | 20% |
| 3 | 1 | 2 | 40% |
| 4 | 1 | 3 | 60% |
| 5 | 0 | 3 | 60% |
| 6 | 1 | 4 | 80% |
| 7 | 1 | 5 | 100% |
| 8 | -1 | 4 | 80% |
Not every session results in mastery. Students may need multiple attempts before meeting mastery thresholds. Negative values subtract from cumulative mastery (session 8 above drops the student back to 80% and marks the course incomplete).
Retrieving Progress Data
EduBridge Analytics API
The EduBridge Analytics API provides aggregated progress data including cumulative masteredUnits:
STUDENT_ID="student-123"COURSE_ID="math-grade-3"curl -X GET "$TIMEBACK_API_URL/ims/edubridge/analytics/v1p0/enrollmentFacts?studentId=$STUDENT_ID&courseId=$COURSE_ID" \ -H "Authorization: Bearer $ACCESS_TOKEN"const studentId = 'student-123'const courseId = 'math-grade-3'const path = `${TIMEBACK_API_URL}/ims/edubridge/analytics/v1p0/enrollmentFacts?studentId=${studentId}&courseId=${courseId}`const response = await fetch(path, { headers: { Authorization: `Bearer ${accessToken}`, },})const data = await response.json(){ "enrollmentFacts": [ { "studentId": "student-123", "courseId": "math-grade-3", "xpEarned": 450, "masteredUnits": 3, "lastActivityDate": "2025-11-18T10:15:00Z" } ]}The masteredUnits value is the cumulative sum of all masteredUnits reported this student and course.
To calculate pctCompleteApp, divide masteredUnits by your application's total unit count.
Caliper Activity Events
Query the student's activity-completion events and sum the masteredUnits metric:
STUDENT_ID="student-123"curl -X GET "$TIMEBACK_API_URL/ims/caliper/events?actorId=$TIMEBACK_API_URL/ims/oneroster/rostering/v1p2/users/$STUDENT_ID" \ -H "Authorization: Bearer $ACCESS_TOKEN"const studentId = 'student-123'const actorId = `${TIMEBACK_API_URL}/ims/oneroster/rostering/v1p2/users/${studentId}`const path = `${TIMEBACK_API_URL}/ims/caliper/events?actorId=${encodeURIComponent(actorId)}`const response = await fetch(path, { headers: { Authorization: `Bearer ${accessToken}`, },})const { events } = await response.json()Then aggregate the masteredUnits metric across activity-completion events for the course:
const totalMasteredUnits = events
.filter(event => event.type === 'ActivityEvent')
.filter(event => event.object?.course?.id?.endsWith('/math-grade-3'))
.reduce((sum, event) => {
const masteredUnitsMetric = event.generated?.items?.find(
item => item.type === 'masteredUnits',
)
return sum + Number(masteredUnitsMetric?.value ?? 0)
}, 0)
// Calculate completion (you provide totalUnits from your app config)
const pctCompleteApp = (totalMasteredUnits / totalUnits) * 100