how to send Tin Can statements with javascript


I've managed to use javascript in Storyline to report score and completion in Scorm 2004. I had no prior knowledge of javascript, but managed it with help from these forums.

Now, I'm fiddling around with Tin Can courses. Storyline reports the basic information fine. But I'm looking to see if I can use the API to send more specific, lesson-related data or statements.

So I'm wondering: Is it possible to send Tin Can statements using the 'execute javascript'-trigger?

If so, does anyone have an example of some javascript that does that?



48 Replies
Norm Cousineau

Hi you have a storyline variable called "activityId"?

For your test, you could try this:
var activity = "";

In my example, clicking buttons changes the value of that variable. That value is sent in statements so I know which buttons the user clicked.

Attached is my published file which works on my LMS (I'd guess it works on yours too. It may be worthwhile to confirm this.)

Erez Goren

Hey Alex,

I'm using my LMS' built-in LRS. I have also discussed this with my LMS' support team and it turns out, using standard functionality:

-Time spent on a unit can only be tracked on SCORM objects

-The above only works -per unit-, meaning to get that function I would need to split my course to seperate slides and upload each one on it's own

Norm Cousineau

Hi Erez. It is possible to modify the sample to send "duration" with a statement. In my LRS I can drill down to see more information. (I can click on a statement and get all the details.) But it seems like that's not possible with your LRS. If it were possible, it would take a bit of effort to write the JavaScript to figure out the duration to send it in a statement. (In other words it's not something that's calculated automatically in this case where we're sending our own custom statements from the course.)

Norm Cousineau

Hi Prakash, I haven't tried, but here's a sample provided by Rustici. Use the getStatements function.

callback: function (err, result) {
// 'err' will be null on success
if (err !== null) {
// handle error
// handle success, 'result' is a TinCan.StatementsResult object;}}

Sure Norm!

Thanks for your reply. I already got the statements from LRs using this coding’s......

var tincan = new TinCan({
recordStores: [{
endpoint: '',
username: 'xDnlGEoAa8XclqDG_5Q',
password: 'VTUkmTpiDJnoQ9OBXYE',
var container = document.getElementById('response');
'params' : {
'limit' : 20
}, // <-- don't forget this comma, I bloody do all the time.
'callback': function (err, result) {
container.innerHTML = (err !== null ? 'ERROR' : JSON.stringify(result.statements));

Anyway you’re pervious and this discussions are very helpful to me thank you so much.

Scott Wiley

Hi Prakesh,

So in your success returning statements, can you see a way to set a Storyline variable that would be equal to the results you get back?

In a proof of concept project, I want to display on screen in the course what results are returned and "container.innerHTML" or "" is not working for me.

I tried this, with no success:

var container = document.getElementById('response');
var player = GetPlayer();

        params: {
            'limit' : 20
        callback: function (err, result) {
            container.innerHTML = (err !== null ? 'ERROR' : JSON.stringify(result.statements));
            player.SetVar("statementContent", container.innerHTML);

KnowledgeWorkx .

Erez, did you get it working finally? I got Norm's sample code working on TalentLMS, although it didn't work at first for me. This is how I figured it out:

1. To see how far, if any, of the javascript code executed in the trigger, I temporarily interspersed Norm's code with extra "alert" lines for debugging, e.g.:

alert("1. Start of Norm's code!");
var tincan = new TinCan({url: window.location.href});
alert("2. TinCan initialized!");
var activity = "" + GetPlayer().GetVar("activityId");
alert("3. The activity text is: " + activity);

I published it, then "adding <script src="tincan-min.js"></script> into the head of story.html and add tincan-min.js into the file package" as Alex said, uploaded it to TalentLMS and then when I did the course, I only saw alert 1, but NOT alert 2! 

2. So then I checked Norm's example .story closer & made my trigger exactly like his (slide trigger when variable changes), and made sure my .story was referring to the same variable as my javascript (e.g. "activityId" above).  But, sadly, I still didn't get alert 2!

3. So then I checked the .zip file I uploaded to TalentLMS, and behold, Alex's "tincan-min.js" changes WERE NOT IN THE zip file! At first, I had published it, then clicked "OPEN", made Alex's "tincan-min.js" changes, then clicked "ZIP", then uploaded it to TalentLMS, and failed miserably. But it worked if I published it, then clicked "ZIP", THEN made Alex's "tincan-min.js" changes inside the zip, then upload it, then wonderous success!

p.s. NOTE, do NOT change the name of the zip file because TalentLMS will NOT recognize it as a TinCan package. Any filename changes must be done beforehand in Storyline (Publish/Title) OR afterwards in TalentLMS (Files/Rename).

Ros McNamee

Can we get a .story file to be able to reference? All info on here seems very abstract and specific to their material. I have been scowering the internet looking for straight forward step by step instructions on how to get the LRS to record what the user does inside a Storyline slide, beyond the default. I see the .zip file Norm gave does exactly that with 3 buttons, but I've no clue how he did it.

Any help would be appreciated, and please if you can start from step 1, not step 100  and include a sample if you can. 

KnowledgeWorkx .

Thanks Ros for your question. Generating custom TinCan statements is an important part of using TinCan's powers, even though "this thread is a bit dated and outside [Articulate's] realm of support". I've attached a sample .story file that I made when first trying this myself, which will send the Student's Input from the Storyline course to the LMS's TinCan report of statements. The text on the slide should help you step through how I built it. If it's not clear, just ask, because last year I could have used the same thing as what you're asking, Ros!

Ashley Terwilliger

Hi Anshul, 

Welcome to the E-Learning Heroes community! We're glad you're here. 😀

Have you taken a look at the information here on implementing Tin Can API with Articulate content? That's where you'll want to start and then I'd suggest asking your LRS if they have specific settings that are needed as well. 

If you need further help, feel free to let us know here! 

Designboy Chris

Hey, this last story is class, I currently use

to send my LRS to. I would love to capture the data box entry there too, is this possible and what part of Kelly Weins code would I need to alter to work on my articualte files?

//var activity = ""
//alert("Testing JavaScript for TinCan statements! (code from Norm)");
var tincan = new TinCan({url: window.location.href});
var vTextEntry= "" + GetPlayer().GetVar("TextEntry2");
tincan.sendStatement({verb: {id: ""}, object: {"id": vTextEntry,"objectType": "Activity"}});