7.7 Using CBA ItemBuilder Items in Custom Web Applications (Taskplayer API)
This section briefly describes how software developers can use CBA ItemBuilder content in web applications.
The CBA ItemBuilder is the tool for creating individual assessment components. These can be items, instructions, units or entire tests. Typically, several CBA ItemBuilder projects must be used for the application. Each CBA ItemBuilder project file provides one or more entry points called Tasks. For a test section you then need a list of ItemBuilder project files and the corresponding task names to administer them, for instance, in a linear sequence.
CBA ItemBuilder Project Files are zip archives that contain the following components (see also section 8.3.3):
A: The information required at design time for creating assessment components with the CBA ItemBuilder (i.e., for editing content). The files are only required for opening and modifying the assessment components with the CBA ItemBuilder and the files are not required at runtime (i.e., when using the assessment components to collect data).
B: Resource files (i.e., images, videos, and audio files) in web-supported formats that are imported using the CBA ItemBuilder to design pages. The file names of resource files are linked in the CBA ItemBuilder to components (i.e., the resource files are required for item editing and at runtime).
C: Embedded external resources ( i.e., HTML, JavaScript, and CSS files also in web-supported formats) integrated into pages with
ExternalPageFrames/iframesare stored inside the zip archive. An HTML file is defined for eachExternalPageFrames/iframesas entry, but more files might be necessary.D: A
config.jsonthat allows rendering the item content with the CBA ItemBuilder runtime is also stored in the zip archive. Only theconfig.jsonfile and the two folders with the resources (resources) and the embedded resources (external-resources, that can contain sub-directories) are required for using the assessment components generated with the CBA ItemBuilder.E: A file
stimulus.jsonis also part of the CBA ItemBuilder project files that contains JSON-serialized, meta information about the tasks, such as the runtime version (runtimeCompatibilityVersion), the name (itemName) and the preferred size (itemWidthanditemHeight) as well as a list of all defined Tasks (tasks). This file also contains a list of required resource files (resourcesandexternalResources) that allows pre-caching the item before rending.
Taskplayer API: The required Runtime to embed CBA ItemBuilder items into browser-based assessments is provided as a JavaScript file (main.js) and a CSS file (main.css) for each version of the CBA ItemBuilder. Since version 9.0 the interface of the Taskplayer API provided by the JavaScript runtime remained stable, while the internal implementation is changed and updated when new features are implemented in the CBA ItemBuilder. To render an CBA ItemBuilder project of a particular version using the config.json file together with the two folders (resources and external-resources), the same version of the CBA ItemBuilder runtime (i.e., main.js and main.css) is required.
For individual linear sequences, the runtime provides navigation between the tasks directly. If skip rules or adaptive tests are to be implemented, then several runtimes can be combined for the administration of individual tasks or packages of several tasks. This approach also allows implementing a delivery platform that can handle ItemBuilder tasks of different versions.
For programming a CBA ItemBuilder delivery, the following points must be considered and implemented:
Provision of Static Files: To use CBA ItemBuilder items, the resources (directories resources and external-resources) must be made available (e.g. via static hosting). This can be done via arbitrary URLs, which are communicated via the configuration of the runtime.
Configuration: Via URL parameters or with a structure
cba_runtime_configdeclared in the global JavaScript scope (i.e. aswindow.cba_runtime_config) the runtime of the TaskPlayer API can be configured.Caching of Snapshots: Browsers can be closed, and assessments should be able to be continued afterward as unchanged as possible. Tasks can also be exited and revisited as part of between-task navigation. For these requirements, the runtime provides the state of a task as a so-called
snapshot, which the delivery software is expected to store and to provide for restoring the state of tasks. Therefore, for implementing a custom delivery, it is required to enable persistence of the snapshot data because these snapshots have to be made available to the TaskPlayer API for resuming and restoring tasks.Storing of Provided Data: For a data collection with CBA ItemBuilder items using the TaskPlayer API, the following two types of data must be stored: At definable intervals, the TaskPlayer API transmits the collected log data (referred to as
trace logs). These data have become the focus of scientific interest for the in-depth investigation of computer-based assessments and should always be stored. The direct results in (i.e., the so-calledItem Scores) are provided by the TaskPlayer API when the Tasks are switched and must also be stored. Snapshots, trace data, and item scores are each assigned to a person-identifier and a task so that they can be easily post-processed afterward.
A description of an example implementation of an Execution Environment using the TaskPlayer-API is provided (see EE4Basic in section B.5) together with a technical documentation for developers (see Reference in section B.5).
The following subsections describe the Taskplayer API in detail, providing all information required to embed CBA ItemBuilder items into a custom web application and to collect trace, snapshot, and scoring data.
7.7.1 Taskplayer API: Initialization and Configuration
The Taskplayer API uses the HTML5 postMessage mechanism for bidirectional communication. The task player runs in an iframe and the host application (the Execution Environment) communicates with it by sending and receiving JSON messages.
Runtime Files: To render CBA ItemBuilder items, two files are required per CBA ItemBuilder version:
main.<version>.js– the JavaScript runtimemain.<version>.css– the CSS stylesheet
These files are loaded in an HTML page (the frame content) that serves as the iframe source for the task player.
Startup Configuration: The task player accepts configuration either as URL query parameters or via a global window.cba_runtime_config object (which takes precedence):
window.cba_runtime_config = {
eventDomainUri: '*', // Target origin for postMessages
eventTargetWindow: 'parent' // Send taskPlayerReady to parent window
};| Parameter | Values | Description |
|---|---|---|
eventDomainUri |
URL or * |
Target origin for outgoing messages |
eventTargetWindow |
self, parent, opener |
Window that receives the initial taskPlayerReady event |
Initialization Sequence: The task player signals readiness by sending { eventType: 'taskPlayerReady' } to the configured target window. Only after receiving this event should the host application send configuration messages.
7.7.2 Taskplayer API: State Machine and Lifecycle
The task player operates as a state machine with four states:
Initial --> NotLoggedIn --> NoTaskRunning --> TaskRunning
^ |
| (stopTask) |
+----------------+
| From State | API Call | To State | Description |
|---|---|---|---|
| Initial | taskPlayerReady (sent by player) |
NotLoggedIn | Player is ready |
| NotLoggedIn | setUserId |
NoTaskRunning | Set user identifier |
| NoTaskRunning | startTask |
TaskRunning | Begin task execution |
| TaskRunning | stopTask |
NoTaskRunning | End task, triggers scoring |
7.7.3 Taskplayer API: Adding Items
Before starting tasks, items must be registered with the task player using the addItem message. The itemConfig is the parsed content of the config.json file from the CBA ItemBuilder project ZIP archive:
// Add an item to the task player
playerFrame.contentWindow.postMessage(JSON.stringify({
eventType: 'addItem',
itemConfig: configJson, // Parsed config.json
resourcePath: '/items/myItem/resources/',
externalResourcePath: '/items/myItem/external-resources/',
translationPath: '/items/myItem/translations/'
}), '*');| Parameter | Description |
|---|---|
itemConfig |
Parsed JSON from the item’s config.json file |
resourcePath |
URL prefix for the resources/ folder (images, audio, video) |
externalResourcePath |
URL prefix for the external-resources/ folder (HTML/JS) |
translationPath |
URL prefix for the translations/ folder |
libraryPathsMap |
Optional: { MathJax: '<url>' } for MathJax CDN or local path |
7.7.4 Taskplayer API: Scaling Configuration
The display scaling of items can be configured:
playerFrame.contentWindow.postMessage(JSON.stringify({
eventType: 'setScalingConfiguration',
scalingMode: 'scale-up-down', // Proportional scaling
alignmentHorizontal: 'center',
alignmentVertical: 'center'
}), '*');Scaling modes: no-scaling, scale-up, scale-down, scale-up-down (see section 3.2.2 for details).
7.7.5 Taskplayer API: Starting and Stopping Tasks
Start a task: The scope parameter serves as a session identifier for the task execution. Re-using the same scope for a task will restore its previous state (snapshot).
playerFrame.contentWindow.postMessage(JSON.stringify({
eventType: 'startTask',
scope: 'session_001',
item: 'MyItemName',
task: 'task0'
}), '*');Stop a task (triggers scoring computation):
Pause and resume (e.g., for global timeouts):
7.7.6 Taskplayer API: Task Sequencing
For multi-task assessments, the task player can delegate navigation decisions to the host application:
// Register the host as task sequencer
playerFrame.contentWindow.postMessage(JSON.stringify({
eventType: 'setTaskSequencer',
targetWindowType: 'parent',
targetOrigin: '*'
}), '*');When the test-taker triggers a navigation command (e.g., NEXT_TASK), the task player sends a taskSwitchRequest to the host instead of handling it internally:
// Host receives:
{ eventType: 'taskSwitchRequest', request: 'nextTask', scope: '...', item: '...', task: '...' }
// request can be: 'nextTask', 'previousTask', 'cancelTask', 'goToTask'The host application then decides which task to start next (or whether to end the assessment).
7.7.7 Taskplayer API: Collecting Trace Data
Trace data (log events) are collected automatically during task execution. The host must configure a transmission channel before starting tasks:
Option 1: HTTP POST (recommended for server-based applications):
playerFrame.contentWindow.postMessage(JSON.stringify({
eventType: 'setTraceLogTransmissionChannel',
channel: 'http',
transmitUrl: 'https://myserver.com/api/trace',
interval: 5000, // Send every 5 seconds
httpTimeout: 10000
}), '*');Option 2: postMessage (recommended for single-page applications):
playerFrame.contentWindow.postMessage(JSON.stringify({
eventType: 'setTraceLogTransmissionChannel',
channel: 'postMessage',
targetWindowType: 'parent',
targetOrigin: '*',
interval: 5000
}), '*');Option 3: Console (for development/debugging):
playerFrame.contentWindow.postMessage(JSON.stringify({
eventType: 'setTraceLogTransmissionChannel',
channel: 'console',
interval: 0
}), '*');Session identifier: Set a context ID that is included in all trace transmissions:
playerFrame.contentWindow.postMessage(JSON.stringify({
eventType: 'setTraceContextId',
contextId: 'person_42_session_1'
}), '*');Trace data format: The transmitted JSON has this structure:
{
"metaData": {
"sessionId": "person_42_session_1",
"userId": "user123",
"timestamp": "2026-03-21T10:30:00.000Z",
"version": "10.4"
},
"logEntriesList": [
{
"entryId": "unique_id",
"timestamp": "2026-03-21T10:30:01.234Z",
"type": "Button",
"details": {
"indexPath": "0/0/1",
"userDefIdPath": "page1/panel1/button1",
"userDefId": "button1",
"clientX": 150, "clientY": 200
}
}
]
}Common trace entry types include: UserLogin, ItemSwitch, TaskSwitch, Button, Checkbox, RadioButton, Link, SimpleTextField, Snapshot, JavaScriptInjected, and many more (one for each component type).
7.7.8 Taskplayer API: Collecting Scoring Results
Scoring results can be requested after stopping a task:
// Request scoring result
playerFrame.contentWindow.postMessage(JSON.stringify({
eventType: 'getScoringResult',
requestId: 'score_req_1'
}), '*');
// Host receives:
{
eventType: 'getScoringResultReturn',
requestId: 'score_req_1',
result: { /* scoring data */ }
}Scoring result structure: The result object contains name-value pairs:
{
"totalResult": 1,
"hitsCount": 2,
"missesCount": 0,
"hit.Q1_Correct": true,
"hitWeighted.Q1_Correct": 1,
"hitClass.Q1_Correct": "Var1",
"hitText.Q1_Correct": "",
"classFirstActiveHit.Var1": "Q1_Correct",
"classResult.Var1": true,
"nbUserInteractions": 5,
"taskExecutionTime": 12345,
"firstReactionTime": 1500,
"resultVariables": [
{ "name": "Var1", "value": "Q1_Correct", "valueHit": "Q1_Correct", "valueLabel": "" }
]
}Key fields in the scoring result:
| Field Pattern | Description |
|---|---|
hit.<hitName> |
Boolean: is this hit active? |
hitWeighted.<hitName> |
Weight of this hit (if active) |
hitClass.<hitName> |
Class this hit belongs to |
classFirstActiveHit.<className> |
Name of first active hit in class (sequential mode) |
classResult.<className> |
Boolean: class scored as correct? |
totalResult |
Overall result (1 = pass, 0 = fail) |
nbUserInteractions |
Number of user interactions |
taskExecutionTime |
Time in milliseconds |
firstReactionTime |
Time to first interaction in milliseconds |
resultVariables |
Array of class results with names, values, and labels |
Scoring results from previous task executions can be retrieved using getOldScoringResult with additional scope, item, and task parameters.
7.7.9 Taskplayer API: Collecting Snapshots
Snapshots represent the complete state of a running task. They are included in the trace data (entry type Snapshot) and are essential for resuming tasks. When a task is stopped, the snapshot is cached by the task player. If the same task is started again with the same scope, the cached snapshot is used to restore the task state.
For external persistence (e.g., to survive browser restarts), snapshots must be extracted from the trace data and provided back to the task player when resuming.
7.7.10 Taskplayer API: Complete Integration Example
The following example shows the minimal JavaScript code required to embed a single CBA ItemBuilder task into a web page, collect scoring results, and receive trace data:
<!DOCTYPE html>
<html>
<head><title>CBA ItemBuilder Assessment</title></head>
<body>
<iframe id="player" src="frameContent.html"
style="width:1024px; height:768px; border:none;"></iframe>
<script>
var player = document.getElementById('player');
var items = {}; // Store item configs
// Listen for messages from the task player
window.addEventListener('message', function(event) {
var msg;
try { msg = JSON.parse(event.data); } catch(e) { return; }
switch(msg.eventType) {
case 'taskPlayerReady':
// Step 1: Configure trace transmission
send({ eventType: 'setTraceContextId',
contextId: 'session_' + Date.now() });
send({ eventType: 'setTraceLogTransmissionChannel',
channel: 'postMessage',
targetWindowType: 'parent',
targetOrigin: '*', interval: 5000 });
// Step 2: Set user
send({ eventType: 'setUserId', userId: 'testUser' });
// Step 3: Configure scaling
send({ eventType: 'setScalingConfiguration',
scalingMode: 'scale-up-down',
alignmentHorizontal: 'center',
alignmentVertical: 'center' });
// Step 4: Register as task sequencer
send({ eventType: 'setTaskSequencer',
targetWindowType: 'parent',
targetOrigin: '*' });
// Step 5: Load items and start first task
loadItemAndStart('MyItem', 'task0');
break;
case 'taskSwitchRequest':
// Stop current task and get scoring
send({ eventType: 'stopTask' });
send({ eventType: 'getScoringResult',
requestId: 'score_1' });
break;
case 'getScoringResultReturn':
console.log('Scoring:', msg.result);
// Store scoring result, then start next task
// or end the assessment
break;
case 'traceLogTransmission':
// Receive and store trace data
console.log('Trace:', msg.traceLogData);
fetch('/api/trace', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify(msg.traceLogData)
});
break;
}
});
function send(msg) {
player.contentWindow.postMessage(JSON.stringify(msg), '*');
}
async function loadItemAndStart(itemName, taskName) {
// Fetch the item's config.json
var resp = await fetch('/items/' + itemName + '/config.json');
var config = await resp.json();
// Register item with task player
send({
eventType: 'addItem',
itemConfig: config,
resourcePath: '/items/' + itemName + '/resources/',
externalResourcePath: '/items/' + itemName + '/external-resources/',
translationPath: '/items/' + itemName + '/translations/'
});
// Start the task
send({
eventType: 'startTask',
scope: 'session_001',
item: itemName,
task: taskName
});
}
</script>
</body>
</html>This example demonstrates the essential integration pattern. A production implementation would additionally handle error cases, implement a task sequence (administering multiple items), persist snapshots for test resumption, and store trace and scoring data on a server.