Skip to content

AI-built SCORM course plays but records nothing: fix the tracking code

Updated 26 October 2026

Quick fix

The course plays, but the LMS shows “not attempted”, stays “incomplete”, or has no score. When an AI tool wrote the SCORM code, it is almost always one of these:

  • It never connects: the manifest and the code use different SCORM versions, or the code stops looking too soon. Fix.
  • The LMS refuses the values: SCORM 1.2 and 2004 names mixed up, or values like “complete” or “80%”. The right names and values.
  • It never finishes, or finishes too early: closing the tab ends nothing, or the score is sent after the end. Fix.
  • Progress is kept in the browser: learners start over on another computer. Fix.

To see which, drop the zip into Alder (free, nothing is uploaded), play the course in its test player and press “I’m done”. Each of these shows as a finding, with the call that caused it in the log.

The course never connects to the LMS

The LMS shows “not attempted”, and Alder says “The course never connected to the LMS” after the test. The course didn't find the API, the connection object the LMS puts on a page around it, or never asked for it.

  1. Make the manifest and the code agree on the version

    A SCORM 1.2 course looks for an object called API; a 2004 course looks for API_1484_11. The LMS offers the one the manifest names. AI tools often write a 2004 manifest and 1.2 code, or the other way round. Alder catches this before you launch: “The manifest says SCORM 2004, but the content is built for SCORM 1.2” (MANIFEST-012). Change whichever is wrong so both say the same.

  2. Look in every window above the course, then the opener

    Code that checks only window.API, or only window.parent.API, misses LMSs that put the API higher up or open the course in a new window. Walk up through each parent, then try window.opener, as the scorm.js on the packaging page does. Wrap each look in try: a window on another web address throws an error instead of answering.

  3. Fix JavaScript errors that stop the start

    If the script fails before it reaches the start call, nothing connects. Alder lists JavaScript errors the course threw during the test.

The LMS refuses the values

Every SetValue call returns "true" or "false". On "false" the value is simply not recorded, and AI-written code rarely checks. These are the names and values each version accepts:

The same things in SCORM 1.2 and SCORM 2004
SCORM 1.2SCORM 2004
Find the LMSAPIAPI_1484_11
Start, save, finishLMSInitialize, LMSCommit, LMSFinishInitialize, Commit, Terminate
Statuscmi.core.lesson_status: completed, incomplete, passed or failedcmi.completion_status: completed or incomplete, and cmi.success_status: passed or failed
A score of 80%cmi.core.score.raw: 80 (0 to 100)cmi.score.scaled: 0.8, and cmi.score.raw: 80
1 minute 30 secondscmi.core.session_time: 00:01:30cmi.session_time: PT1M30S
Leaving before the endcmi.core.exit: suspendcmi.exit: suspend

In Alder's test LMS, a SCORM 1.2 course setting “complete”, “80%”, “8/10” or a time of “90” is refused with error 405, and a 2004 name such as cmi.completion_status with error 401. In SCORM 2004, a scaled score of 80 is refused with 407. Each refused call is a row in the log with its error code, and Alder sums them up as “The LMS refused some of the course's data”. What each code means: SCORM error codes.

It never finishes, or finishes too early

A course has to end its session (LMSFinish in 1.2, Terminate in 2004), and that has to be the last call. AI-written code often finishes only from a “Finish” button, but most learners just close the tab. Without the call, many LMSs keep only what was saved along the way, and some throw the attempt away.

Alder's Must fix card: the LMS may keep only part of this attempt, or throw it away. The course never told the LMS it was finished. How to fix it: call LMSFinish when the learner exits, including when they close the window (listen for pagehide).
The SCORM 1.2 probe, started and set to completed, then closed without finishing.

The opposite mistake is sending the score or status after finishing, for example from a results screen shown after the course ended its session. The LMS ignores it:

Alder's Worth checking card: the LMS ignores what the course sends after it has finished. How to fix it: send the status, score and exit value before LMSFinish, and call LMSFinish last.
The same probe, setting passed after LMSFinish.
  • Finish when the window closes too: listen for pagehide and finish there, once.
  • Save (LMSCommit or Commit) after each important change, so a crash or a closed laptop loses nothing.
  • Send everything first; finish last; send nothing after.
  • Several HTML pages? If each page starts its own session, the second start is refused, and leaving a page can end the session. Keep the connection on one page that stays open (a single-page course, or pages shown in a frame inside it). See “Error initializing communications with LMS”.

Progress kept in the browser

AI tools like localStorage for remembering the learner's place. It works on the computer you test on, so it looks fine. But it doesn't follow the learner to another computer, and on a shared one it mixes learners up. Alder flags it as “The course wrote to browser storage”. Keep the place in the LMS instead, in cmi.suspend_data:

Resume with the LMS (uses scorm.js)
// When the course opens, after scorm.start(): pick up where the learner left off.
var saved = scorm.get('cmi.suspend_data');
var state = saved ? JSON.parse(saved) : { page: 0, answers: {} };

// Whenever the learner moves on: keep the place in the LMS, not in localStorage.
scorm.set('cmi.suspend_data', JSON.stringify(state));
scorm.save();

The LMS only gives the saved data back if the course left with exit set to “suspend”, which scorm.js does when the learner hasn't finished. SCORM 1.2 guarantees only 4,096 characters, so keep the state small: the suspend_data limit.

Check the zip before you upload it (free)

  1. Drop the zip into Alder

    Open Alder and drop the zip. A version mismatch (MANIFEST-012), a missing launch file or a manifest in an extra folder shows at once.

  2. Play it to the end, then press “I’m done”

    Click “Launch the course” and go through it as a learner, including the quiz. “I’m done” shows what an LMS would record (status, score, time) and every problem above that happened.

  3. Test leaving halfway

    Launch again, leave partway, then use “Test as a returning learner”. If the course starts from the beginning, the place wasn't saved in the LMS.

Why AI-written SCORM code goes wrong

AI tools learned SCORM from twenty years of examples in two versions, many wrappers and many LMSs, so they mix names and versions freely. And the mistakes are silent: opened on its own, the course finds no LMS and just plays, and a refused value only returns “false”. Nothing fails until a real LMS records the wrong thing. The calls have to come in this order:

The order of a course's SCORM callsFive steps, each with its SCORM 1.2 and SCORM 2004 name: find the LMS connection (API or API_1484_11); start once (LMSInitialize or Initialize); report status, score and progress (LMSSetValue or SetValue); save (LMSCommit or Commit); and finish last (LMSFinish or Terminate). The LMS drops anything sent after finishing.1. Find the LMS connectionAPI / API_1484_112. Start, onceLMSInitialize / Initialize3. Report status, score, progressLMSSetValue / SetValue4. SaveLMSCommit / Commit5. Finish, lastLMSFinish / TerminateAnything sent after this is dropped
Every SCORM course makes these calls, in this order.

Still not working?