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.
- In Storyline, open your course, and open the scene with the “open” button.
- Select the button.
- In the ribbon at the top, switch to the Button Tools menu.
- At the far left, in the Action section, click the When Clicked menu option.
- In the Trigger Wizard, click the Action (e.g., “change state of”).
- In the pull-down menu, under the More section, click Send xAPI Statement.
- In the Trigger Wizard, in the Statement, click + xAPI….
- 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"}}]}}}
- In the xAPI Statement Editor, click the OK button.
- In the Trigger Wizard, click the OK button.
- Open the Trigger Wizard again and change the Action to More > Adjust Variable.
- Change the Variable to
PopupId
, and enter a value, such as popup01
.
- Click the OK button.
- Open the Trigger Wizard again and change the Action to More > Adjust Variable, again.
- 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.
- Click the OK button.
- In the Slide palette (usually docked to the right side of the window), in the Triggers section, click the Manage project variables button —
.
- 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%
).
- 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.
- In the scene with the pop-up, switch to the layer with the pop-up.
- Select the “close” button and create a new trigger.
- In the Trigger Wizard, change the Action to More > Send xAPI Statement.
- In the Statement, click + xAPI….
- 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"}}]}}}
- Click the OK button.
- 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.
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.
- In the scene with the pop-up, switch to the layer with the pop-up.
- Select the video and create a new trigger.
- In the Trigger Wizard, change the Action to More > Send xAPI Statement.
- In the Statement, click + xAPI….
- 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"}}]}}}
- Click the OK button.
- In the Trigger Wizard, change the Action to More > Adjust Variable.
- Change the Variable to
VideoId
, and enter a value, such as video01
.
- Click the OK button.
- Open the Trigger Wizard again and change the Action to More > Adjust Variable, again.
- Change the Variable to
VideoName
, and enter a value, ideally a string that matches the title of the video.
- Click the OK button.
- Open the Trigger Wizard again and change the Action to More > Adjust Variable, again.
- Change the Variable to
VideoLength
, and enter the length as a number, in milliseconds: e.g., 1 minute is 60000
.
- Click the OK button.
- In the Slide palette (usually docked to the right side of the window), in the Triggers section, click the Manage project variables button —
.
- 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%
).
- 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.
- In the scene with the pop-up, switch to the layer with the pop-up.
- Select the video and create a new trigger.
- In the Trigger Wizard, change the Action to More > Send xAPI Statement.
- In the Statement, click + xAPI….
- 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"}}]}}}
- Click the OK button.
- In the Trigger Wizard, change the When to Control Events > Media completes.
- Change the Media to the selected video.
- 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:
Player.AccessibleText
Player,BackgroundAudioVolume
Player.DisplayCaptions
Player.FullScreenMode
Player.ZoomToFit
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.
- In Storyline, open your course. In Story View, select the first slide.
- Create a new trigger.
- In the Trigger Wizard, change the Action to More > Send xAPI Statement.
- In the Statement, click + xAPI….
- 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"}}]}}}
- Click the OK button.
- In the Trigger Wizard, change the When to Control Events > Variable changes.
- Change the Variable to
Player.DisplayCaptions
.
- Click the OK button.
- Click the Manage project variables button —
. - In the Variables dialog box, double-click the Default Value of
ActivityName
, and enter the name of your course.
- Click the OK button.
- Select the trigger and click the Copy the selected trigger button —
.
- Select another slide you wish to apply the trigger to and click the Paste the copied trigger to the selected object button —
.
- 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.