InstructionalEngineer

How to Write Good xAPI Statements – Verbs, Objects and Context

By Instructional EngineerSCORM, xAPI and LMS7 min read

How to Write Good xAPI Statements – Verbs, Objects and Context - 3D Cutaway Animation

xAPI lets you record almost anything. That's the gift and the trap. Six months after launch, someone opens the Learning Record Store and finds "completed," "finished," "done" and "complete" all meaning the same thing, activity IDs that changed with every course update, and a learner who appears under three different email addresses. Nobody can build a report from it. The fix isn't more data; it's better xAPI statements from the start. How do you write statements that stay clean, consistent and useful?

Good xAPI statements are consistent, specific and designed backward from the questions you'll need to answer. Use established verbs from the ADL vocabulary or a published profile instead of inventing synonyms. Give every activity a stable, unique identifier you control, and identify learners the same way every time. Put the score, success, completion and duration in the result, and use context to link each statement to its course, registration and parent activity. Before you build anything, write the report you want, then design the statements that feed it.

What Makes Up an xAPI Statement?

An xAPI statement is a small JSON record built around actor, verb and object, with optional result, context and timestamp. Think of it as a sentence with a few footnotes. "Alex answered question 3 correctly in the hazard communication quiz in about 40 seconds" becomes:

{
  "actor": { "account": { "homePage": "https://lms.example.com", "name": "E10423" } },
  "verb": { "id": "http://adlnet.gov/expapi/verbs/answered",
            "display": { "en-US": "answered" } },
  "object": {
    "id": "https://training.example.com/xapi/hazcom/quiz/q3",
    "definition": {
      "name": { "en-US": "Hazcom quiz, question 3" },
      "type": "http://adlnet.gov/expapi/activities/cmi.interaction",
      "interactionType": "choice"
    }
  },
  "result": { "success": true, "response": "b", "duration": "PT40S" },
  "context": {
    "registration": "1b9c2f6e-5d7a-4c11-9d1e-0f2c7a8b3e44",
    "contextActivities": {
      "parent": [ { "id": "https://training.example.com/xapi/hazcom/quiz" } ],
      "grouping": [ { "id": "https://training.example.com/xapi/hazcom" } ]
    }
  },
  "timestamp": "2017-03-14T15:22:09Z"
}

Actor is who, verb is what happened, object is to what, result is how it went, and context is where it fits. The official xAPI specification defines every property if you need the exact rules.

How Do You Choose Good Verbs?

Choose verbs that already exist and mean exactly what happened. Verbs in xAPI are identified by web addresses (IRIs), not by their display words, so "completed" from your course and "completed" from someone else's only match if they use the same IRI.

Start with the ADL verb list, which covers the common cases, and check whether a published profile exists for your activity type before inventing anything. Here are verbs that cover a lot of training scenarios:

VerbUse it when
experiencedThe learner viewed or encountered content, such as a page or slide
attemptedThe learner started an activity that has a result, such as a quiz
answeredThe learner responded to a question
completedThe learner finished everything required in an activity
passed / failedThe learner met, or didn't meet, a defined standard
progressedThe learner moved partway through, often with a progress measure
interactedThe learner used an element without a scored outcome
commentedThe learner left feedback or a note

Two rules keep verbs clean. First, one meaning per verb across your whole program. Second, don't encode the result in the verb. "Answered" plus a result of success true is better than inventing "answered-correctly," because reports can filter on success without knowing your private vocabulary.

How Should You Identify Activities?

Give every activity an IRI that is unique, stable and under a domain you control. That last part matters: if you use a vendor's domain or a temporary URL, you lose control of your identifiers when things change.

How Should You Identify the Learner?

Identify the learner the same way everywhere, using an identifier that won't change. xAPI lets you use an email address (mbox), a hashed email, or an account made of a home page and a user ID. Emails change when people get married, change names or switch domains, so an account using a stable employee or LMS ID is usually the safer choice.

Agree on this across every system that sends statements. If your LMS sends one identifier and your mobile app sends another, the same person becomes two people in your data, and no reporting tool can safely merge them later. Also consider privacy: send only what you need to identify the learner, and avoid stuffing names or personal details into extensions.

What Belongs in Context and Result?

Result holds the outcome. Context holds the surroundings. Mixing them up is one of the most common design mistakes.

How to Write Good xAPI Statements – Verbs, Objects and Context - 3D Animation

Result

Use the result for score (scaled from -1 to 1, plus raw, min and max if you like), success, completion, the learner's response and duration in ISO 8601 format (for example, PT40S for 40 seconds). Only include properties you actually know. A statement saying "experienced" doesn't need a score.

Context

Use context to place the statement in its bigger picture:

The parent and grouping links are what let you ask "how did people do on this quiz across all three courses that include it?" Without them, each question floats alone.

Which Statement Habits Ruin Your Reports?

Most problems come from skipping the planning step. These are the habits I look for first in any review:

MistakeWhy it hurtsBetter approach
Made-up verbs for common actionsReports can't match them with other toolsUse ADL or profile verbs
Activity IDs that change on republishHistory splits into unconnected piecesFixed IDs under your own domain
Different learner IDs per systemOne person looks like severalOne agreed account identifier
No registration or parent contextCan't group attempts or roll up resultsAlways send registration and parent
A statement for every mouse clickNoise drowns the signal and costs storageTrack events that answer a question

How Do You Test xAPI Statements Before Launch?

Test statements the same way you'd proofread a document: send them, read them back, and have a second person check them against the plan. A sandbox LRS is ideal for this, and many LRS products offer a free or trial environment.

  1. Run through the activity as a learner and send every statement type at least once, including failures and exits.
  2. Check that the LRS accepted every statement. A rejected statement usually means a formatting error, such as a missing verb ID or an invalid duration.
  3. Query statements back by learner, by activity and by registration. If a query that should work returns nothing, an identifier is inconsistent.
  4. Compare every verb, ID and extension against your data dictionary. Small spelling differences are the most common problem.
  5. Build one draft report from the test data and confirm it answers its question.

Repeat a quick version of this test whenever the course or app is updated. Statements tend to drift over time as different developers touch the code, and a ten-minute check keeps your data consistent for years.

How Do You Design Statements from the Report Backward?

Start with the report, then design the data. Write down the questions managers and designers will ask, sketch the tables or charts that answer them, and list exactly which statements, with which properties, those charts need. Only then build.

  1. Write three to five questions, such as "Which scenario choices do new supervisors get wrong most often?"
  2. Sketch the report for each question.
  3. List the statements needed: verb, activity, result and context for each.
  4. Write a one-page data dictionary: verbs, ID patterns, learner identifier, extensions.
  5. Send test statements to a sandbox LRS and build the report from them before launch.

This is the same discipline that makes any report trustworthy. If you're deciding which numbers deserve a place on a dashboard at all, my guide to LMS reporting covers what's worth tracking and why.

Good xAPI Statements Are Written for the Reader, Not the Writer

Writing xAPI statements is a lot like writing for a person: clear words, consistent meaning, and enough context to understand what happened later. Use shared verbs, stable activity IDs and one learner identifier. Put outcomes in the result and relationships in the context. Design from the report backward.

Before the next xAPI project kicks off, agree on your verbs, ID patterns and learner identifier, and write them down where every developer will see them. It takes about an hour, and it's the difference between a Learning Record Store full of answers and one full of noise.

← All articles