Skip to content

SCORM 1.2 and xAPI

Both packages are the standalone HTML player plus a launch wrapper and an imsmanifest.xml, zipped. They are for the training market and for every LMS that speaks SCORM 1.2 or xAPI.

The_Ferry_at_Dusk-scorm12.zip
├── index.html the standalone player + the SCO wrapper (head script)
└── imsmanifest.xml single-organization, single-SCO manifest

The xAPI variant is the same two files with an additional emitter script in index.html. Both files sit at the zip root, as SCORM requires.

On launch the wrapper finds the API object by walking parent windows, calls LMSInitialize, and sets cmi.core.lesson_status to incomplete. It subscribes to the player with whenComplete (so a scenario short enough to finish during boot is still reported), and on completion sets:

ElementValue
cmi.core.score.raw0–100, per the scoring rule below
cmi.core.score.min / max0 / 100
cmi.core.lesson_statuspassed / failed when a score variable is used; completed / incomplete otherwise

then LMSCommit and LMSFinish. The manifest carries <adlcp:masteryscore>80</adlcp:masteryscore>.

Written into the manifest as a comment, verbatim, so an LMS administrator can read it without opening the code:

  1. If a numeric score variable is available — a project variable literally named score — the run scores its final value normalised onto 0–100 from the variable’s declared range (its Min / Max custom fields, defaulting to 0 and 100), clamped. Status is passed at or above the mastery score (80), failed below.
  2. Otherwise: reaching an ending scores 100; an abandoned run scores the proportion of the project’s playable nodes it visited. Status is completed when an ending was reached, incomplete otherwise.

So to grade a scenario, declare a variable named score (with Min and Max custom fields if the range is not 0–100) and set it from the nodes:

Variable["score"] = Variable["score"] + 25

The example manifest uses rule 2 because the example has no score variable.

The xAPI package keeps the SCORM wrapper and adds an emitter that sends statements to the LRS named in the launch URL’s query string — endpoint and auth (required; with neither present the emitter stays silent so the same package still works as a plain SCORM upload), and actor as a JSON agent (an anonymous account agent is used when absent):

VerbWhenResult
initializedOn launch—
respondedEach choice, as it is taken (the player fires onChoice before traversal runs, so order is preserved)response: the choice text; the choice’s node as a sub-activity of the scenario
completedWhen the run endsscore raw 0–100 and scaled 0–1, success at or above the mastery score, completion when an ending was reached

The activity ID is the manifest identifier (CM_<Title>). Every statement sent is also kept on window.chatmapperXapi.sent for inspection.

Unzip and open index.html: with no API object present the wrapper stays inert and the scenario plays normally — an LMS that is missing or refuses to initialise is never a reason to break the course. For a real conformance check use SCORM Cloud or your LMS’s sandbox — the package is a plain single-SCO 1.2 course with nothing exotic in it.

  • One SCO per package: one scenario, one score. Split a course into several scenarios if you need several scores.
  • The player is text-only; a training package with audio should use the LearnBrite or engine route instead, or a wrapper you build around the player’s API.
  • SCORM 2004 is not produced; every 2004-capable LMS also imports 1.2.