How Do I Add Custom xAPI to Storyline?

How Do I Add Custom xAPI to Storyline?

While Articulate Storyline supports a handful of xAPI actions out-of-the-box, you may want more. In response, Articulate added an option to create a trigger that sends a custom xAPI statement. If you need help working with triggers, then the Articulate Community has this tutorial.
Notes
We've written the JSON in this Knowledge Base article to match the out-of-the-box xAPI that Storyline already sends, and to conform with xAPI Profile Guidelines.

Interactivity xAPI Statements

This first example is implicit and extensible because it tracks an action at the smallest scale: when a student opened and closed a popup by clicking a button. From this, you can extrapolate similar custom xAPI for other page-level interactions, such as adjusting a slider or dial, or selecting a hotspot.

Prerequisites: For this example, you'll need a slide with an “open” button, and a slide layer with the popup and a “close” button. You should have also already added triggers to each button respectively, to show and hide the layer.
  1. In Storyline, open your course, and open the scene with the “open” button.
  2. Select the button.
  3. In the ribbon at the top, switch to the Button Tools menu.
  4. At the far left, in the Action section, click the When Clicked menu option.
  5. In the Trigger Wizard, click the Action (e.g., “change state of”).
  6. In the pull-down menu, under the More section, click Send xAPI Statement.
  7. In the Trigger Wizard, in the Statement, click + xAPI….
  8. In the xAPI Statement Editor, replace the JSON code with this:
{    "verb": {
        "id": "http://activitystrea.ms/open",
        "display": {"en-US": "opened"}},
    "object": {
        "objectType": "Activity",
        "id": "%Project.ActivityId%/%Slide.Id%/%PopupId%",
        "definition": {
            "name": {"en-US": "%PopupName%"},
            "type": "http://adlnet.gov/expapi/activities/interaction"}},
    "context": {
        "contextActivities": {
            "parent": [{
                "objectType": "Activity",
                "id": "%Project.ActivityId%/%Slide.Id%",
                "definition": {
                    "name": {"en-US": "%Project.SlideTitle%"},
                    "type": "http://adlnet.gov/expapi/activities/module"}}],
            "grouping": [{
                "objectType": "Activity",
                "id": "%Project.ActivityId%",
                "definition": {
                    "name": {"en-US": "%ActivityName%"},
                    "type": "http://adlnet.gov/expapi/activities/course"}}]}}}
  1. In the xAPI Statement Editor, click the OK button.
  2. In the Trigger Wizard, click the OK button.
  3. Open the Trigger Wizard again and change the Action to More > Adjust Variable.
  4. Change the Variable to PopupId, and enter a value, such as popup01.
  5. Click the OK button.
  6. Open the Trigger Wizard again and change the Action to More > Adjust Variable, again.
  7. Change the Variable to PopupName, and enter a value, ideally a string that matches the name shown on the button or the title of the popup.
  8. Click the OK button.
  9. In the Slide palette (usually docked to the right side of the window), in the Triggers section, click the Manage project variables button — .
  10. In the Variables dialog box, double-click the Default Value of ActivityName, and enter the name of your course (one of the only values for which Storyline doesn't have a system variable, like %Project.ActivityId%).
  11. Click the OK button.
When packaged and run, the courseware will send an xAPI statement when the student clicks the “open” button, dynamically replace the variables for the popup's ID and name, and replace the ActivityName too.
  1. In the scene with the pop-up, switch to the layer with the pop-up.
  2. Select the “close” button and create a new trigger.
  3. In the Trigger Wizard, change the Action to More > Send xAPI Statement.
  4. In the Statement, click + xAPI….
  5. In the xAPI Statement Editor, replace the JSON code with this:
{    "verb": {
        "id": "http://activitystrea.ms/close",
        "display": {"en-US": "closed"}},
    "object": {
        "objectType": "Activity",
        "id": "%Project.ActivityId%/%Slide.Id%/%PopupId%",
        "definition": {
            "name": {"en-US": "%PopupName%"},
            "type": "http://adlnet.gov/expapi/activities/interaction"}},
    "context": {
        "contextActivities": {
            "parent": [{
                "objectType": "Activity",
                "id": "%Project.ActivityId%/%Slide.Id%",
                "definition": {
                    "name": {"en-US": "%Project.SlideTitle%"},
                    "type": "http://adlnet.gov/expapi/activities/module"}}],
            "grouping": [{
                "objectType": "Activity",
                "id": "%Project.ActivityId%",
                "definition": {
                    "name": {"en-US": "%ActivityName%"},
                    "type": "http://adlnet.gov/expapi/activities/course"}}]}}}
  1. Click the OK button.
  2. In the Trigger Wizard, click the OK button.
If you already entered the pop-up “open” triggers and variables, then this trigger will inherit the values from that earlier action.

Media xAPI Statements

Sadly, the video player that Articulate offers does not send xAPI. Nor does the video player have any controls to which we can attach a trigger. However, Storyline has a couple of other methods to track media activity. Read on!

Prerequisites: For this example, you'll need a slide with video, either linked or embedded. You must know the length of the video, in milliseconds.

Video Played

If the student clicks anywhere on a video, even with the media player controls hidden, then the media begins playing. So, although we can't attach triggers to the media player controls, we can still track that generic click.
  1. In the scene with the pop-up, switch to the layer with the pop-up.
  2. Select the video and create a new trigger.
  3. In the Trigger Wizard, change the Action to More > Send xAPI Statement.
  4. In the Statement, click + xAPI….
  5. In the xAPI Statement Editor, replace the JSON code with this:
{    "verb": {
        "id": "https://w3id.org/xapi/video/verbs/played",
        "display": {"en-US": "played"}},
    "object": {
        "objectType": "Activity",
        "id": "%Project.ActivityId%/%Slide.Id%/%VideoId%",
        "definition": {
            "name": {"en-US": "%VideoName%"},
            "type": "https://w3id.org/xapi/video/activity-type/video",
            "extensions": {"https://w3id.org/xapi/video/extensions/length": "%VideoLength%"}}},
    "context": {
        "contextActivities": {
            "parent": [{
                "objectType": "Activity",
                "id": "%Project.ActivityId%/%Slide.Id%",
                "definition": {
                    "name": {"en-US": "%Project.SlideTitle%"},
                    "type": "http://adlnet.gov/expapi/activities/module"}}],
            "grouping": [{
                "objectType": "Activity",
                "id": "%Project.ActivityId%",
                "definition": {
                    "name": {"en-US": "%ActivityName%"},
                    "type": "http://adlnet.gov/expapi/activities/course"}}]}}}
  1. Click the OK button.
  2. In the Trigger Wizard, change the Action to More > Adjust Variable.
  3. Change the Variable to VideoId, and enter a value, such as video01.
  4. Click the OK button.
  5. Open the Trigger Wizard again and change the Action to More > Adjust Variable, again.
  6. Change the Variable to VideoName, and enter a value, ideally a string that matches the title of the video.
  7. Click the OK button.
  8. Open the Trigger Wizard again and change the Action to More > Adjust Variable, again.
  9. Change the Variable to VideoLength, and enter the length as a number, in milliseconds: e.g., 1 minute is 60000.
  10. Click the OK button.
  11. In the Slide palette (usually docked to the right side of the window), in the Triggers section, click the Manage project variables button — .
  12. In the Variables dialog box, double-click the Default Value of ActivityName, and enter the name of your course (one of the only values for which Storyline doesn't have a system variable, like %Project.ActivityId%).
  13. Click the OK button.
If you already entered triggers and variables, then this trigger will inherit the default values from that earlier action.

Video Completed

Storyline does have a media event that we could use to track if the video reached its end, Media completes.
  1. In the scene with the pop-up, switch to the layer with the pop-up.
  2. Select the video and create a new trigger.
  3. In the Trigger Wizard, change the Action to More > Send xAPI Statement.
  4. In the Statement, click + xAPI….
  5. In the xAPI Statement Editor, replace the JSON code with this:
{    "verb": {
        "id": "http://adlnet.gov/expapi/verbs/completed",
        "display": {"en-US": "completed"}},
    "object": {
        "objectType": "Activity",
        "id": "%Project.ActivityId%/%Slide.Id%/%VideoId%",
        "definition": {
            "name": {"en-US": "%VideoName%"},
            "type": "https://w3id.org/xapi/video/activity-type/video",
            "extensions": {"https://w3id.org/xapi/video/extensions/length": "%VideoLength%"}}},
    "context": {
        "contextActivities": {
            "parent": [{
                "objectType": "Activity",
                "id": "%Project.ActivityId%/%Slide.Id%",
                "definition": {
                    "name": {"en-US": "%Project.SlideTitle%"},
                    "type": "http://adlnet.gov/expapi/activities/module"}}],
            "grouping": [{
                "objectType": "Activity",
                "id": "%Project.ActivityId%",
                "definition": {
                    "name": {"en-US": "%ActivityName%"},
                    "type": "http://adlnet.gov/expapi/activities/course"}}]}}}
  1. Click the OK button.
  2. In the Trigger Wizard, change the When to Control Events > Media completes.
  3. Change the Media to the selected video.
  4. Click the OK button.
If you've entered this trigger on the same slide as the “played” action and the slide has no other videos, then this trigger should inherit the variables from the other.

Accessibility xAPI Statements

A frequent question about xAPI is, “Can I xAPI track students' use of accessibility features?”. Yes! Storyline included. Obviously, you can manually add controls with triggers for custom xAPI, like a “D” link to a long description popup, for example. However, Storyline also has a couple of out-of-the-box functions too.

The controls on the courseware player for Storyline packages has five built-in variables you can use as triggers:
  1. Player.AccessibleText
  2. Player,BackgroundAudioVolume
  3. Player.DisplayCaptions
  4. Player.FullScreenMode
  5. Player.ZoomToFit
The system variable Player.DisplayCaptions also matches the xAPI Profile template Enable Closed Captioning. So, we'll see how to use that.

Closed Captions Enabled/Disabled

The Storyline player has a Captions control and a separate menu of more “Accessibility controls” , including Zoom to fit, Accessible text, Keyboard shortcuts, and Background audio. We're showing you how to track when the student clicks the CC button.
  1. In Storyline, open your course. In Story View, select the first slide.
  2. Create a new trigger.
  3. In the Trigger Wizard, change the Action to More > Send xAPI Statement.
  4. In the Statement, click + xAPI….
  5. In the xAPI Statement Editor, replace the JSON code with this:
{    "verb": {
        "id": "http://adlnet.gov/expapi/verbs/interacted",
        "display": {"en-US": "interacted"}},
    "object": {
        "objectType": "Activity",
        "id": "%Project.ActivityId%",
        "definition": {
            "name": {"en-US": "Enable/Disable Closed Captioning"},
            "type": "https://w3id.org/xapi/video/templates#closed-captioning"}},
    "context": {
        "contextActivities": {
            "parent": [{
                "objectType": "Activity",
                "id": "%Project.ActivityId%",
"definition": { "name": {"en-US": "%ActivityName%"},
"type": "http://adlnet.gov/expapi/activities/course"}}],
"grouping": [{ "objectType": "Activity", "id": "%Project.ActivityId%", "definition": { "name": {"en-US": "%ActivityName%"}, "type": "http://adlnet.gov/expapi/activities/course"}}]}}}
  1. Click the OK button.
  2. In the Trigger Wizard, change the When to Control Events > Variable changes.
  3. Change the Variable to Player.DisplayCaptions.
  4. Click the OK button.
  5. Click the Manage project variables button — .
  6. In the Variables dialog box, double-click the Default Value of ActivityName, and enter the name of your course.
  7. Click the OK button.
  8. Select the trigger and click the Copy the selected trigger button — .
  9. Select another slide you wish to apply the trigger to and click the Paste the copied trigger to the selected object button — .
  10. Repeat as needed for all affected slides.
This trigger only detects changes to the CC button in the Storyline courseware player. It doesn't show if the button is on or off. The xAPI statement will say, “Enable/Disable Closed Captioning”.

This parent and grouping in this JSON are generic for the entire course. If you want, you can customize the parent context to reflect each scene and slide, so you can track exactly where the student clicked the CC button.



Notes
Articulate®, Storyline®, and Rise® are all registered trademarks of Articulate Global, LLC.




    • Related Articles

    • What xAPI does Articulate Track?

      We're often asked questions like: “What xAPI properties does my authoring tool send to the LRS?” “What metrics can I track with my authoring tool?" Recently, we've gotten a few more questions about Articulate, specifically. Articulate has two ...
    • What are xAPI Extensions and How Do I Use Them in My xAPI Statements?

      Best Practices for xAPI Extensions Activity, Context, and Result Extensions in xAPI Statements Do you need to know when and how to best use Activity, Context or Result Extensions in your xAPI Statements? This is a common challenge and a frequently ...
    • Why Does My xAPI Say “und”?

      Because you didn't set the language of your xAPI package when you published your courseware in your authoring tool. What is a Language Map? When an LRS gets a text string, like an object.definition.name, or object.definition.description, the xAPI ...
    • Will LRS Reporting Work with a SCORM Package?

      No. Although an authoring tool may offer the option to enable “Report to an external LRS” for packages other than xAPI and cmi5, those other SCORM or AICC packages do not send xAPI statements to an LRS. The courseware player in each package matches ...
    • Will Students See Errors in an xAPI Course with No LRS?

      If you develop an xAPI course package and don't yet have an LRS, or the LRS is down, then the student should not see any error messages. It will depend on the authoring tool you use. To be sure, you should test it. We've gotten more questions about ...