Tutorials · 6 min read

Build a self guided training course with api.video

Build a self guided training course with api.video

When building a video training course, you may wish to guide users through the content by unlocking videos only after certain content has been viewed. In this post, we'll walk through how to build such a flow with api.video and our session analytics.

Doug Sillars

June 28, 2021

Online video training is huge. There are many companies that offer video training courses where the course follows one video after another. The only way to continue in the course is to finish a video, and when the video is completed, the next video is unlocked. This ensures that the video course is taken in the order designed by the instructor, and that the students are not 'skipping' ahead through the coursework.

Other use cases for this might be a corporate training, where it is required that every employee watches each video in a series to be compliant with the policies of an organization (as a veteran of AT&T, I have taken months of this sort of training)

In this post, we'll walk through how you can build a video training app with api.video.

Connecting a session to a user

The first step in any training course will be to login your user. In the case of training a video, we'll skip a secure login form (it is just a demo!) and simply ask you to enter your name:

screenshot of training a video

When you submit this form, we'll search through the videos connected to the course (in this case, they are hardcoded in the app as an array:

var videolist = ['vi47Q8KHXLYyaOoX2Yoznxqh','vi6QvU9dhYCzW3BpPvPsZUa8','vi1DrBc0VkPfedcfTc21U1TP'];
var videoDurations= [91,321,333];

Note, we also hardcode the duration of the 3 videos (but in a more dynamic app, you can get the video duration from the video status endpoint.

Now for each of these videos, I have created dynamic metadata entry:

	"metadata": [
			"key": "classUserName",
			"value": "__classUserName__"

when the value of a metadata entry has two underscores on either side of the value, any value can be applied to the metadata entry. In this case, we'll apply the username as the value. We can search for any video sessions that have the classUserName "Doug" for each of the videos in the training session. (in the code below, I am using the NodeJS client:

			currentPage = '1';
      pageSize = '25';
      var metadata = {'classUserName': userName};
      var params = { videoId, metadata, currentPage, pageSize};
      const result = client.rawStatistics.listVideoSessions(params);

This will result in the first 25 sessions where the variable userName (Doug) is saved as the classUsername metadata. (Of course, if you believe that your users might have more than 25 sessions per video, you can expand that number up to 100 - but for a training course, 25 viewing sessions per video per user is probably more than adequate).

The response from this will be every session that the user has had for the video. For each of these sessions, we want to know if the video was watched all the way through. We've written up this analysis of session events. As soon as we discover a session that has watched the video, we stop looking through the sessions.

How many videos to unlock?

This approach will then be completed for each video in the series, until we reach a video that has not been watched. This is done through the recursive function iterateVideos:

function iterateVideos(videolist, videoDurations, userName, videoCounter){
  return new Promise(function(resolve, reject){
      //soo take list of videos, and iterate until we know which video can be watched.
      console.log("testing video "+videoCounter);
      var videowatched  = videoWatched(videolist[videoCounter], videoDurations[videoCounter], userName);
        console.log("video "+videoCounter+ " "+ passfail);
          //video was watched, so lets check the next one
          if (videoCounter < videolist.length){
            var nextVideo = iterateVideos(videolist, videoDurations, userName, videoCounter);
            //the last video was watched so, stop and show all the videos...
            resolve(videoCounter -1);
          //video was NOT watched start wit this video
          console.log("resolve the counter of the first video not watched", videoCounter);
      }).catch((error) =>{


The videoWatched function checks each session to see if the video has been completed.

If the video has been completed, it returns true. Then we check the next video to see if it has been watched. (If we reach the end of the video list - we show all of the videos.).

If the video has not been watched - we know where to stop displaying playable videos, and we can display the page.

What the user sees

For this simple example with three videos, there are just three potential views:

  • If no videos have been watched - the first video will have no sessions, and the session analysis will stop immediately. The page will show the first video as playable, and the subsequent videos as locked.

  • If the first video has been completed, but not the second: the page will show the first two videos as playable, but the third video will still be locked.

  • If videos 1-2 are completed (or if all 3 videos are completed), all three videos appear as watchable.

Looking at the HTML

<iframe type="text/html" src="https://embed.api.video/vod/vi6QvU9dhYCzW3BpPvPsZUa8?metadata[classUserName]=Doug" width="960" height="320" frameborder="0" scrollling="no"></iframe>

See how each video adds the metadata[classUserName]=Doug this will ensure that any video session that is started on this page will be assigned to the user Doug. Once a video is watched, the user can refresh the page, and all the session data will be recalculated, and the next video will be unlocked.

Build your own video training app

With api.video, you can easily upload your videos for playback. Using our analytics and dynamic metadata, we can build a training application that unlocks each video as content is viewed. Build your own based on our code on Github. If you have question, feel free to reach our community or test it now in our free Sandbox environment.

Try out more than 80 features for free

Access all the features for as long as you need.
No commitment or credit card required

Video API, simplified

Fully customizable API to manage everything video. From encoding to delivery, in minutes.

Built for Speed

The fastest video encoding platform. Serve your users globally with 140+ points of presence. 

Let end-users upload videos

Finally, an API that allows your end-users to upload videos and start live streams in a few clicks.


Volume discounts and usage-based pricing to ensure you don’t exceed your budget.