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 AssessmentResult metadata field.
It is also recommended to include masteredUnits 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
AssessmentResult.metadataas 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 all AssessmentResult.metadata entries for the student |
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% |
Not every session results in mastery. Students may need multiple attempts before meeting mastery thresholds.
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.
OneRoster Assessment Results
Query all AssessmentResult entries for a student and sum the masteredUnits from metadata:
STUDENT_ID="student-123"curl -X GET "$TIMEBACK_API_URL/ims/oneroster/gradebook/v1p2/students/$STUDENT_ID/assessmentResults" \ -H "Authorization: Bearer $ACCESS_TOKEN"const studentId = 'student-123'const path = `${TIMEBACK_API_URL}/ims/oneroster/gradebook/v1p2/students/${studentId}/assessmentResults`const response = await fetch(path, { headers: { Authorization: `Bearer ${accessToken}`, },})const { assessmentResults } = await response.json()Then aggregate metadata.masteredUnits across all results for the course:
// Sum masteredUnits from all assessment results
const totalMasteredUnits = assessmentResults
.filter(result => result.courseId === 'math-grade-3')
.reduce((sum, result) => sum + (result.metadata?.masteredUnits || 0), 0)
// Calculate completion (you provide totalUnits from your app config)
const pctCompleteApp = (totalMasteredUnits / totalUnits) * 100