Note: When we refer to 'xAPI courses' here, we are specifically talking about courses that communicate via xAPI and are packaged and launched according to the guidelines outlined here. The package will include a tincan.xml manifest file. This is currently the predominant way that xAPI courses are created in existing authoring tools.
However, with the creation of the cmi5 specification, we have a better way to package and launch content that communicates using xAPI. While cmi5 is still in the early adoption phase, it is now our recommended approach to the concepts of packaging, launch, session capture, and scoring for elearning products wishing to leverage xAPI. Most of the issues outlined below disappear when using cmi5 courses. Be sure to ask your vendor whether they have cmi5 support or when they will.
When customers start to use xAPI courses (see note above), they often run into some differences in behavior with what they've come to expect from SCORM content in Engine. The goal with this article is to outline these differences so that it is clear what is happening.
Dude, where's my player?
One major difference with these types of courses is with the fact that there is no 'player' involved in launching them. With SCORM, you have Engine's player page that is either launching the content inside a frame or in a new window that is linked to it. The player is what tracks and communicates progress data to Engine, and informs us that the content has exited.
With xAPI content, that is not the case. Instead, Engine launches directly to the content itself, passing it the LRS endpoint and a few other pieces of information the content needs in order to post statements back to it.
There are a couple of side effects to the fact that there is no player window:
- By default, we will open xAPI courses in a new window. This will leave our launch page open, with a 'Return to LMS' link in it. Unlike the SCORM player window, this launch page does not (by default) use the RedirectOnExitUrl whenever you close the content window. This is a frequent source of confusion for customers who expect it to honor that like it does for SCORM.
With version 2016.1.16.573 of Engine, we have added a new setting, RedirectLaunchPageOnExit, which can be set to make this launch page redirect to the RedirectOnExitUrl whenever the content window is closed. This setting is "false" by default so that the original behavior wasn't changed unexpectedly for customers.
- Since there is no player window to communicate with Engine for these launches, we have no reliable way to know that the content has exited. Because of this, customers who have a non-API integration with Engine cannot rely on the RollupRegistrationOnExit method override to be called for xAPI courses.
This means that you would need to modify your integration code to override RollupRegistration in order to get progress data for these registrations. Often customers will add logic to bypass the method for non-xAPI registrations. In Engine 2015.1 and above, this is somewhat easier, as you can check the RollupData.IsExit parameter for 'null' to know that this is an xAPI course, as it does not support the idea of exit.
For API integrations, you should note that even if you have set ApiRollupRegistrationDuringSession to 'false', which for SCORM means it will only post progress data on exit, with xAPI content it will post to you every time we get a statement that contains progress information (see below), not just at exit.
Not all statements are created equal
The next question that frequently comes up is: my course is sending statements, but I am not getting any progress reported to me (either through the integration RollupRegistration, or through the ApiRollupRegistrationPostbackUrl).
It's important here to understand how Engine gleans progress information from xAPI courses, as it can help debug any situations where this is happening. There are a couple of conditions that come into play in Engine being able to pull completion from statements and report it through the registration rollup process.
We will trigger rollup anytime we receive a statement that meets certain conditions:
- The statement must be generated by a course launched by Engine. This is required, because the statement must be able to pass back both the actor and the registration id that is generated by Engine and passed on the launch url to the content.
Note: this registration id is NOT the registration id you normally think of with Engine. It is a unique identifier that is created by Engine specifically for xAPI content to use (a UUID). For API customers, you can see this identifier using this endpoint.
- The statement must include a result object, as outlined in the spec, with the appropriate progress data included in it.
- The statement must be for the Activity that was specified in the tincan.xml file for the course. This is relevant, because sometimes courses will send statements for a child activity, and then even though it may have a result object, it will not be used by Engine.
If the statement meets all of those conditions, then we'll pull the completion/success/score/duration data out of the result object and trigger the rollup process.
One thing you'll notice, is that our recording of data is completely tied to the result object in the statement. This means that we do not look at verbs or other aspects of the statement.
Outside of the information coming in the result object mentioned above, as of Engine 2017.1.21.600, we will also report on interaction activities (questions/answers) from statements of that type. These details will be available in the runtime data for the registration.
Hopefully, this information will help as you start to use launched xAPI courses and work on getting the data into your system through the rollup process.
If you have a need to work with the full richness of data that can be recorded with xAPI statements, you'll need to step outside the normal rollup registration process to retrieve and examine the raw statements themselves. We can certainly help guide you with that process -- just contact us at firstname.lastname@example.org!