Creating Custom xAPI Statements: A Step-by-Step Developer Guide
The Experience API (xAPI) is revolutionizing how learning is tracked, offering granular insights beyond the traditional SCORM model. While most Learning Record Providers (LRPs) send predefined statements, the real power of xAPI lies in creating custom xAPI statements that capture unique, meaningful learner actions.
In this guide, we’ll walk you through the anatomy, creation, and best practices of custom xAPI statements—so you can start tracking what truly matters in your eLearning experience.
๐ What is a Custom xAPI Statement?
An xAPI statement is a JSON object that follows the format:
[Actor] [Verb] [Object], with optional context, result, and attachments.
A custom statement is one you define (instead of using preset ones from authoring tools) to track learning experiences like:
- Clicking a specific button
 - Interacting with a simulation
 - Posting in a forum
 - Viewing a knowledge base article
 - Completing a real-world task
 
๐งฑ Anatomy of an xAPI Statement
Here’s a basic structure:
{
  "actor": {
    "name": "Jane Doe",
    "mbox": "mailto:jane@example.com"
  },
  "verb": {
    "id": "http://adlnet.gov/expapi/verbs/interacted",
    "display": {"en-US": "interacted"}
  },
  "object": {
    "id": "http://example.com/interactive-simulation",
    "definition": {
      "name": {"en-US": "Interactive Simulation"},
      "description": {"en-US": "A complex drag-and-drop chemistry lab simulation"}
    },
    "objectType": "Activity"
  },
  "timestamp": "2025-07-01T13:20:30Z"
}
๐ง๐ป Step 1: Define the Actor
"actor": {
  "name": "John Smith",
  "mbox": "mailto:john@example.com"
}
Or use account-based identifiers:
"actor": {
  "account": {
    "homePage": "https://yourlms.com",
    "name": "user_12345"
  }
}
๐ Step 2: Choose or Define a Verb
Standard verbs from the xAPI Verb Registry include:
experiencedinteractedcompletedansweredattempted
To define your own:
"verb": {
  "id": "https://xapiverse.com/verbs/flagged-content",
  "display": { "en-US": "flagged" }
}
๐ฏ Step 3: Define the Object
"object": {
  "id": "https://yourapp.com/lessons/simulation-chem-lab",
  "definition": {
    "name": { "en-US": "Chemistry Lab Simulation" },
    "description": {
      "en-US": "Drag and drop simulation for learning chemical reactions"
    }
  },
  "objectType": "Activity"
}
๐งช Step 4: Add Result (Optional but Powerful)
"result": {
  "score": {
    "raw": 85,
    "min": 0,
    "max": 100,
    "scaled": 0.85
  },
  "success": true,
  "completion": true,
  "response": "Selected H2 + O2",
  "duration": "PT5M10S"
}
๐ Step 5: Add Context (Optional)
"context": {
  "contextActivities": {
    "parent": [{
      "id": "https://yourlms.com/course/chemical-reactions"
    }]
  },
  "platform": "xAPILMS",
  "language": "en-US"
}
๐งต Step 6: Add Timestamp
"timestamp": "2025-07-01T13:20:30Z"
๐ Step 7: Send the Statement to Your LRS
Sending a statement to LRS using sing fetch() in JavaScript:
fetch("https://yourlrs.com/xAPI/statements", {
  method: "POST",
  headers: {
    "Authorization": "Basic " + btoa("key:secret"),
    "Content-Type": "application/json"
  },
  body: JSON.stringify(yourStatementObject)
});
✅ Best Practices
- Use consistent and unique IDs for verbs and objects
 - Avoid sending incomplete or duplicate statements
 - Validate your JSON using tools like xAPI Statement Validator
 - Secure your LRS endpoint with authentication
 - Store statement IDs or logs for audit and debugging
 
๐ง Real-World Example
Use Case: Track when a learner flags inappropriate content in a course.
{
  "actor": { "mbox": "mailto:dev@xapiverse.com" },
  "verb": {
    "id": "https://xapiverse.com/verbs/flagged-content",
    "display": { "en-US": "flagged" }
  },
  "object": {
    "id": "https://xapiverse.com/courses/module-3/slide-5",
    "definition": {
      "name": { "en-US": "Slide 5 - Discussion Thread" },
      "description": { "en-US": "User-flagged inappropriate comment" }
    },
    "objectType": "Activity"
  },
  "timestamp": "2025-07-01T13:21:45Z"
}
๐ Final Thoughts
Creating custom xAPI statements is a critical step toward truly personalized, data-rich learning analytics. It gives you power to track almost anything—from mouse clicks to offline tasks—in a standardized, machine-readable format.
Start small. Test. Validate. And soon, you’ll be building a learning ecosystem that’s as smart as the learners inside it.

Comments
Post a Comment