Importing Courses into Engine
E-learning courses are usually distributed in a self-contained unit called a "package", typically in the form of a ZIP file. Although the structure of a package varies between the different learning standards, you usually don't have to know about these differences when working with Engine.
To launch a course in Engine, you first have to make Engine aware of your course by importing it. For most customers, importing a course into Engine is as simple as uploading the ZIP file package and letting Engine handle the rest.
However, Engine does support a variety of other ways to import your courses, such as providing the path to a course already extracted somewhere, or the URL to download the zip file. You can read about those import methods below, but for now, let's stick to the most common import behaviors.
Importing by ZIP
An important distinction to understand is that Engine does not host your course content files. When Engine imports a course, it will just unzip the course, parse and record its details according to the appropriate learning standard, and drop the course files onto your content server. Unless you want to use Engine's remote hosted player, you should ensure that your content server is on the same domain as Engine, or else Engine's player will be inhibited by browser same-origin policies.
Required Settings
There are a few settings that you'll need to configure for this type of import process to work correctly:
FilePathToUploadedZippedPackage
- This setting should be the directory that Engine can use as a place to temporarily store the ZIP files while they are being imported. They will be deleted after the import process is completed.FilePathToContentRoot
- The directory to which Engine should extract the contents of your courses. Within this directory, a folder for each course will be created. The name of the course folder will be based on your course id, and a subfolder under that for the version (e.g., /mycourseid/0).Note: This directory should be hosted by a web server so that all of your course content is accessible to your learners in the browser.
WebPathToContentRoot
- Engine uses this value to calculate the web path to a course's content once it has been imported. This should be the URL where the directory you specified inFilePathToContentRoot
is being hosted. This value is often a relative URL for the current domain (e.g./courses/content/
), but can also be a fully-qualified URL (e.g.http://example.org/courses/content/
) if needed.
Posting the ZIP File Directly
Once you've set those values, you can import a course by sending a POST to the /courses/importJobs/upload
resource, taking special note of the courseId
query string parameter. This parameter should provide a unique identifier for the course being imported.
The body of the request will have the contents of your zip file, and the Content-Type of the request should be multipart/form-data
.
Have Engine Download the ZIP File
If you don't want to POST the contents of your course directly to Engine, you can also have the import process fetch the ZIP file itself. To do this, you need to host the course on a web server that Engine can access or on the server's local file system. Once you've done that, you can POST a JSON object (as Content-Type application/json
) to /courses/importJobs
endpoint with a url pointing to the location of your zipped course file.
Checking Import Status
It's important to note that when you call the importJobs
endpoint through one of the methods above, the course is not immediately ready for use. Since the processing of a course package may take a while, Engine will queue the import job to process it asynchronously and will return a job ID to you in the response.
You should verify that the import job completed successfully before trying to launch it. There are two main ways to do that:
- Using the job ID that was returned to you, check the status by querying the
/courses/importJobs/{importJobId}
resource in the API. You may have your UI wait while it periodically checks to see whether the job is finished before continuing. - Alternatively, you could have Engine update your application directly when the import is finished. If you set the value of
ApiImportResultsPostBackUrl
to the URL of an endpoint in your application, then Engine will POST a JSON object describing the results of the course import whenever an import has been completed.
Updating Courses
If at any point you need to update something about your course, you can always upload a new version of the package. To do this, just import your course as normal while specifying the ID of the existing course that you want to update with the course
query parameter. You must also specify a second parameter named mayCreateNewVersion
with a value of true
. That will tell the import process to use the uploaded package as the new version of the specified course.
New registrations against a course will use the latest course version. The behavior for existing registrations, however, is configurable. To configure when existing registrations will switch to using the new version of the course, you will need a setting named WhenToRestartRegistration
.
By default, we only move registrations to a new version ifthe registration has already been marked as complete. Otherwise, it stays on its original course version.
If that behavior doesn't work for your application, you can review the other possible values for WhenToRestartRegistration
below:
Setting Value | Condition |
---|---|
NEVER | Never restart an existing registration |
WHEN_EXISTING_REG_IS_COMPLETE_AND_NEWER_PACKAGE_VERSION_EXISTS | When a newer version of the associated course package exists and course status is 'Complete' |
WHEN_NEWER_PACKAGE_VERSION_EXISTS | When a newer version of the associated course package exists |
WHEN_EXISTING_REG_IS_COMPLETE | When the registration has been completed, regardless of pass/fail status |
WHEN_EXISTING_REG_IS_SATISFIED | When the overall course status is 'Satisfied' |
WHEN_EXISTING_REG_IS_SATISFIED_AND_NEWER_PACKAGE_VERSION_EXISTS | When the overall course is satisfied and a newer version of the associated course package exists |
WHEN_EXISTING_REG_IS_INCOMPLETE_AND_NEWER_PACKAGE_VERSION_EXISTS | When the overall course is incomplete and a newer version of the associated course package exists. |
WHEN_EXISTING_REG_IS_FAILED | When the overall course is failed. |
WHEN_EXISTING_REG_IS_FAILED_AND_NEWER_PACKAGE_VERSION_EXISTS | When the overall course is failed and a newer version of of the associated course package exists |
One word of caution: whenever Engine moves a registration to a newer version of the course, a new instance of that registration will be created. To a learner, this will effectively reset their progress in the course. Versioning works this way because it's possible that the structure of the new version may not be compatible with the saved data for the old version.
Advanced Import
Importing by Manifest
If your application is already handling the ZIP extraction and the course content is already hosted on a web server, then you can simply point Engine to the manifest of your course and import from that.
To do this, you will POST a JSON object to /courses
with the referenceRequest
property set to an object containing two values:
- the
url
property should point to a SCORM/xAPI/cmi5 manifest or one of the AICC course structure files - the
webPathToCourse
should provide the URL to the root directory of the course's content. This can be an absolute path (e.g.,/courses/myCourseOneFolder
) as long as it lives on the same domain as Engine's player.
Example:
{
"referenceRequest": {
"url": "http://example.org/courses/mycourse/imsmanifest.xml",
"webPathToCourse": "http://example.org/courses/mycourse"
}
}
Since Engine is not handling the actual content files for the course (only the manifest), you must ensure that the content is already available at the path specified.
Unlike the importJobs
endpoints, importing by manifest will run synchronously . This means that you won't have to wait for the import job to complete -- the HTTP request will not return until your manifest has been imported.
Ad Hoc Import
You can sometimes have e-learning content that lives on a web server somewhere, but you do not have an actual zip package with a manifest inside it. This is much more likely with standards like AICC or xAPI where the content can communicate directly back to Engine outside the context of a 'player'.
Engine has a way to 'import' a course such as this so that you can launch and track it along with your normally imported course zip packages.
To do this, you will have to POST a JSON object to /courses
and include the adHocReferenceRequest
property.
Here is an example of what this object could look like and a brief description of what value each of these properties should have.
{
"launchUrl": "http://example.com/courses/tenant-21048/RuntimeBasicCalls_SCORM12/shared/launchpage.html",
"webPathToCourse": "http://example.com/courses/tenant-21048/RuntimeBasicCalls_SCORM12/",
"learningStandard": "scorm12",
"title": "Golf Example - SCORM 1.2"
}
launchUrl
- The URL of the launch page of the course.webPathToCourse
- The root folder of the course's content. This is folder that a course manifest would go in, if one existed.learningStandard
- The learning standard of the course being imported. Acceptable values areaicc
,scorm11
,scorm12
,scorm2004
,scorm20042ndedition
,scorm20043rdedition
,scorm20044thedition
,tincan
, andcmi5
(values are case insensitive, and Engine will ignore any spaces in the name).title
- The title of the course. Will be used as the body of the<title>
of the player page in the browser when the course is launched, and possibly displayed in the player UI.
Using the course that you've described in the JSON body, Engine will generate a placeholder manifest in memory and import your course using that. Like importing with a manifest, an ad-hoc import will run synchronously.
Validating a Course Zip or Manifest
Before importing a course for real, some customers like to validate that the to-be-imported course is, in fact, valid and would be imported successfully.
Engine provides a parameter named dryRun
that you can pass (with a value of true
) to any of our synchronous import methods (i.e., POST to /courses
or /courses/upload
). When you set this to true
, Engine will not extract your course files to FilePathToContentRoot
or save any course information to the database. It will only check that the manifest file is valid for its learning standard and that the course would be imported without issue.
Media Content Courses
You can import, play and track launches of video/audio files, and pdf documents similarly to how you would for normal standards-based course packages. Engine automatically collects and stores completion and duration data for .mp4, .mp3 and .pdf files types. You can retrieve that data using the same registration results API or postback that you would use for any other registration.
To import a media course, use the same endpoints described in the above sections with a few minor considerations to differentiate media from zipped course packages.
The resource content types used in the import syntax are one of three types:
- video/mp4
- audio/mp3
- application/pdf
Posting the Media File Directly
To post a media file directly to Engine, POST to /courses/importJobs/upload
. The body of the request contains the media file. You must also include a request header, uploadedContentType
, which should be one of the three supported resource content types mentioned earlier.
Optionally, you can add a second item to the request body called contentMetadata
, a string of JSON that represents a serialized mediaFileMetadata
object.
{"title": "Workplace Violence","description": "A course that teaches one how to identify that different forms of workplace violence."}
Have Engine Download the Media File
In contrast, Engine can fetch the media file during the import process. To do this, you need to host the media file on a web server that Engine can access or on the server's local file system. Once you've done that, you can POST a JSON object (as Content-Type application/json) to the /courses/importJobs
endpoint.
In addition to a url
pointing to the location of your media file, the JSON body should indicate the media resource type you expect Engine to download along with any optional mediaFileMetadata
information.
{
"url": "http://localhost:80/Courses/SampleVideo.mp4",
"contentType": "video/mp4",
"mediaFileMetadata": {
"title": "Shoe Tying 101",
"description": "Video introducing how to tie tennis shoes."
}
}
Point Engine to the Media File
If your media course content is already hosted on a web server, then you can simply point Engine to the file and have the player load it directly from there when launched.
To do this, POST a JSON object to /courses
with the mediaFileReferenceRequest
property set to an object containing at least two values:
- The
url
property should point to the .mp4, mp3, or .pdf file. - The
contentType
should define the resource type of the file from the url. - Optionally, you may specify an additional
mediaFileMeatadata
object to describe the media course.
{
"mediaFileReferenceRequest": {
"url": "http://localhost:80/Engine2019Courses/new_courses/math_lecture.mp3",
"contentType": "audio/mp3",
"mediaFileMetadata": {
"title": "Linear Algebra Part 2",
"description": "Professor Mark's day-2 lecture on advanced linear algebra.",
"contentLanguage": "en-US",
"moveOn": "Completed"
}
}
}
Note: For pdf courses, the server that hosts the file must provide the proper CORS headers to allow Engine's player to load the file. Otherwise there will be an error at launch time from the pdf viewer.
URL Courses
When using the /courses
endpoint, you can specify any URL and have Engine create a course that launches it. This is a flexible option if you want to track launches of content that is not available as a learning standard zipped package or a specific media file we support.
Since this could be an external url to anything, Engine can't track much beyond knowing whether or not the learner launched the course. As soon as the course is launched, Engine automatically marks the registration as Completed
.
The JSON body takes a URL property as before, but contentType
would simply be url
.
{
"mediaFileReferenceRequest": {
"url": "http://mysite.com/learn",
"contentType": "url"
}
}
Media Content Settings
There are a number of settings that control how the media content looks and behaves. You can view the complete list here in the MediaContent Settings section
.
For example, you may require learners to view 50% of a course to attain completion. Or, you may want to enforce a rule that each learner spend at least 30 seconds on each page of a PDF.
MediaContentCompletionThreshold
- The percentage of media that must be consumed before a media course can be considered 'Complete'.PDFContentPageDurationThreshold
- Number of seconds the user must view a document page before the page will be counted towards progress/completion calculation.