Storyline - Change Interaction ID

I've created a very simple survey in storyline using multiple choice and "essay" questions.  I've published this a SCORM package and if works through our LMS (and SCORM cloud) pushing out the answers the users are supplying.

However, the actual question text doesn't come through making it difficult to report on the data.  By default Storyline seems to set the interaction id to a combination of the slide number and the question type, Slide_0_0_Essay_1,  what I'd really like is to be able to edit the interaction ids to contain the question text so that our LMS can provide some useful reports to the end user.

Thanks in advance

Chris

31 Replies
Richard Hyde

Hi both,

I've managed to add the question text to the interaction ID by editing the SCORM2004Functions.js file in the published Storyline course.  This file sits in the 'lms' folder and there is a function that constructs the interaction ID and sends the interaction to the LMS.

I've attached my version of the file.  I think this is a generic file, so could be replaced in any published course.  I've dropped the code I changed below to explain what I did.

On line 802:

// strDescription is the question text passed from the course so construct a valid interaction string (remove all spaces and replace with underscore)

strDescription = CreateValidIdentifier(strDescription);
 // Replace all ' and " with blank (these have to be removed from any questions)
 strDescription = strDescription.replace(/'/g, '');
 strDescription = strDescription.replace(/"/g, '');
 // Append strDescription, i.e. the question text to end of the interaction ID and send it to the LMS
 blnResult = SCORM2004_CallSetValue("cmi.interactions." + intInteractionIndex + ".id", strID + "_" + strDescription);

This works on SCORM Cloud so I hope you have success.

Richard.

James Birks

Pam, it's been a while since i worked in these files - but i believe the bulk of the change takes place in this block of code (lines 708-732)

/*-----------------------------------------------------------------------------------*/

//alert("SCORM RECORD INTERACTION - ID : " + intInteractionIndex + " : strID : " + strID);

strDescription = CreateValidIdentifier(strDescription);

// Replace all ' and " with blank

strDescription = strDescription.replace(/'/g, '');

strDescription = strDescription.replace(/"/g, '');

//alert("SCORM RECORD INTERACTION - ID : " + intInteractionIndex + " : strDescription : " + strDescription);

/*-----------------------------------------------------------------------------------*/

//need to leave support for blnCorrect=t/f for legacy implementations of RSECA

if (blnCorrect == true || blnCorrect == INTERACTION_RESULT_CORRECT){

strResult = SCORM_RESULT_CORRECT;

}

else if (blnCorrect == "" || blnCorrect == "false" || blnCorrect == INTERACTION_RESULT_WRONG){ //compare against the string "false" because ("" == false) evaluates to true

strResult = SCORM_RESULT_WRONG;

}

else if (blnCorrect == INTERACTION_RESULT_UNANTICIPATED){

strResult = SCORM_RESULT_UNANTICIPATED;

}

else if (blnCorrect == INTERACTION_RESULT_NEUTRAL){

strResult = SCORM_RESULT_NEUTRAL;

}

WriteToDebug("strResult=" + strResult);

//blnResult = SCORM_CallLMSSetValue("cmi.interactions." + intInteractionIndex + ".id", strID);

blnResult = SCORM_CallLMSSetValue("cmi.interactions." + intInteractionIndex + ".id", strDescription);

blnResult = SCORM_CallLMSSetValue("cmi.interactions." + intInteractionIndex + ".type", scormInteractionType) && blnResult;

All i am doing is reformating the question string a little and using it as the id rather than the actual question number. You will probably have to change any questions to a likert value also.

Hope this helps you.

Sam Hammond

Elizabeth, what version of SCORM are you publishing out to? And are you looking to have the question text be the ID instead, or your own custom-set text? 

I was able to set a custom Interaction ID in a SCORM 2004 v4 publish (tested and verified in SCORM Cloud) using the customization below. 

BE ADVISED: You'll need to include and modify a text variable called "pageID" on every interaction slide you have in your course in order for this to work. You could add a fancy if/else in the code to handle cases where that variable isn't set, but that requires a bit of JavaScript know-how. SCORM data model best practices also recommend that the interaction ID 1) be unique for every interaction and 2) contain no spaces in the text field (not sure about whether special characters are kosher either).

Modify the lms.js file (located in the lms directory of your output folder) as follows:

Insert at line 28 after //Save State Delay code block and before if(lmsAPI && lmsAPI.IsLmsPresent) statement:

function GetPlayer(){
return document.getElementById("player");
}

Then insert the following directly under the case "BW_StoreQuestionResult": line on line 54(ish):

var player = GetPlayer();
var modifiedId = player.GetVar("pageID");
arrArgs[1] = modifiedId;

Your case "BW_StoreQuestionResult": block should now look like this:

case "BW_StoreQuestionResult":
      var player = GetPlayer(); 
      var modifiedId = player.GetVar("pageID");
      arrArgs[1] = modifiedId;
      RecordInteraction(arrArgs);
      break;

This should hopefully set the interaction ID equal to whatever you set the pageID variable to be in Storyline. 

Again, highly finicky and only tested thus far in SCORMCloud on a 2004v4 publish. YMMV. 

Sushil Vispute

I have edited question no with question text & User Response using SCORM2004Functions.js file which is  located inside the 'lms' folder. There is a SCORM2004_RecordInteraction function which is used for construction of interaction ID, Description & Response and sends these data to the LMS. I have tested and it's works on LMS.

Below have line by line code level changes

//Find SCORM2004_RecordInteraction function in SCORM2004Functions.js file

strID = CreateValidIdentifier(strID);

strID = strID.split('_')[0].replace("Scene", "Question:");

//Each “Scene” required only one question in sequence

strDescription = CreateValidIdentifier(strDescription);

strID = strID + "_" + strDescription;

blnResult = SCORM2004_CallSetValue("cmi.interactions." + intInteractionIndex + ".id", strID);

blnResult = SCORM2004_CallSetValue("cmi.interactions." + intInteractionIndex + ".type", SCORM2004InteractionType) && blnResult;

blnResult = SCORM2004_CallSetValue("cmi.interactions." + intInteractionIndex + ".learner_response", strResponse) && blnResult;

// If you don’t want to show Objective ID, Time, Correct Responses, Weighting, Result and Latency on LMS interaction report comment these statements.

//Please don’t comment “Type”, otherwise interaction report will be not generate.

/* if (strResult != undefined && strResult != null && strResult != ""){

blnResult = SCORM2004_CallSetValue("cmi.interactions." + intInteractionIndex + ".result", strResult) && blnResult;

} */

/* if (strCorrectResponse != undefined && strCorrectResponse != null && strCorrectResponse != ""){

          blnResult = SCORM2004_CallSetValue("cmi.interactions." + intInteractionIndex + ".correct_responses.0.pattern", strCorrectResponse) && blnResult;

} */

/* if (strDescription != undefined && strDescription != null && strDescription != ""){

          blnResult = SCORM2004_CallSetValue("cmi.interactions." + intInteractionIndex + ".description", strDescription) && blnResult;

} */

/* if (intWeighting != undefined && intWeighting != null && intWeighting != ""){

          blnResult = SCORM2004_CallSetValue("cmi.interactions." + intInteractionIndex + ".weighting", intWeighting) && blnResult;

} */

/* if (intLatency != undefined && intLatency != null && intLatency != ""){

          blnResult = SCORM2004_CallSetValue("cmi.interactions." + intInteractionIndex + ".latency", ConvertMilliSecondsIntoSCORM2004Time(intLatency)) && blnResult;

} */

/* if (strLearningObjectiveID != undefined && strLearningObjectiveID != null && strLearningObjectiveID != ""){

          blnResult = SCORM2004_CallSetValue("cmi.interactions." + intInteractionIndex + ".objectives.0.id", strLearningObjectiveID) && blnResult;

} */

/* blnResult = SCORM2004_CallSetValue("cmi.interactions." + intInteractionIndex + ".timestamp", ConvertDateToIso8601TimeStamp(dtmTime)) && blnResult; */

 

Thanks!!!

Lee-Ann Williams

Oh my goodness!!!! Why isn't there just a way to input an question-level identifier within SL2 instead of having to edit the output? Obviously SL2 has a default way to doing this, by using the scene and slide number as the identifier. For a large organization with a lot of assessments, this level of effort is extreme.

Sam Hammond

Agreed, Lee-Ann. However, if your organization is going to need this edit permanently, I'd advise you to edit the lms.js file located in your Storyline installation directory instead of doing it every time you publish. This is an unsupported "hack" but it definitely gets the job done for our organization's purposes. Let me know if I can be of assistance. 

Sam Hammond

Spot-on Phillip about the special character issues...we tend to just junk that part of the interaction data and focus solely on the "hacked" interaction ID we injected, as well as the student response (right now we just look at correct/incorrect, but we'd love to get more reliable response text too.)

We correlate the interaction ID with another spreadsheet that contains the IDs AND the question text, and build our Item Analysis out that way. You can use a program like Microsoft Power BI to do set this up once and keep it up to date. 

This gives us the added benefit of being able to see performance across multiple language versions of the same test, which is a plus. 

Sam Hammond

Hi Angela, 

I see you deleted your post, so I hope you arrived at a solution. You may not have been able to get your first question to register because it wasn't included in your results slide as a "scored" question. Some LMS platforms don't store interaction data for interactions that you don't mark as significant towards the score/outcome of the test. Hope this helps!

Angela Kim

Thanks for checking in on me! When I checked the results slide, everything was there. Another thing I noticed that the page ID did not match up either. So, what I did change was to set up the page ID when the timeline starts on the page instead of on the submit button and that seemed to work. Not sure why it didn't work on the Submit button...but since it's working, I deleted the post. I can see on the report that the custom IDs match the question and all questions are appearing on the report. Thank you so much. Do you know if Storyline 3 has a feature to customize question IDs without having to manually do so on the back end?

[cid:image001.png@01D2CFB0.88EEA2A0]

[cid:image004.jpg@01D2CFB0.FF419ED0]

Craig Bellingham

Hi Sam,

This is an amazingly useful hack and I'm surprised as of yet Articulate haven't built this kind of functionality directly into Storyline - it's actually a bit disappointing to be honest.

I tested the code on SCORM Cloud, at first without success, but then came across one of your other posts discussing the non-use of lms.js in HTML5 output. When I then tested it as a Flash only course it worked great.

Alas, as I'm working on some courses which are expected to run on devices without Flash, have you come across a way of doing the same but with an HTML5 only course?

Regards,

Craig.

Sam Hammond

Craig, 

Wouldn't you know it but that's exactly what I've been working on this week :) 

Instead of going after the lms.js endpoint, you'll need to modify code in the SCORM functions JavaScript file (in my case, it's SCORM2004Functions.js).

Within function SCORM2004_RecordInteraction(), I inserted the following code after the local variables are declared:

if(typeof GetPlayer == "function"){
  var player = GetPlayer();
  var idCheck = player.GetVar("pageID");
  strID = idCheck.replace(/[ \t\r\n\v\f]/g, "_");
}

Where pageID is the custom interaction ID you set within Storyline.

The code detects whether it can pull the variables from the player then "scrubs" the PageID to conform to the SCORM standard. 

Let me know if this ends up working for you. 

I've also been working on ways to get special characters into the interaction model, as we localize our assessments and want item-level data on those versions as well. It's been a bit painful but I'm making progress. Let me know if that's of interest to you!

EDITED TO ADD: You can apply similar contingency code to the previous lms.js hack I mentioned up-thread to help it "fail gracefully" too:

case "BW_StoreQuestionResult":
if(typeof GetPlayer == "function"){
    var player = GetPlayer();
}
var idCheck = player.GetVar("pageID");
if (typeof idCheck === "undefined" || idCheck === null) {
    RecordInteraction(arrArgs);
} else {
    var modifiedId = player.GetVar("pageID");
   arrArgs[1] = modifiedId;
   RecordInteraction(arrArgs);
}
break;