Your Community is getting an upgrade!
Read about our partnership with Higher Logic and how we will build the next generation of the Instructure Community.
Found this content helpful? Log in or sign up to leave a like!
Hello!
In my Storyline project, we are hosting an artificial intelligence based tutor on an AWS server - to keep some privacy, the start of the URL is https://s3.us-east-2.amazonaws.com and the end is /index.html?user=[%UserID%]
Our goal is to have the following javascript search for the Canvas User ID, store it in the URL, and then keep track of that user's conversations with the AI tutor:
// Get the SCORM API
function getAPI(win) {
var API = null;
while (win && !API && win.parent && win.parent !== win) {
win = win.parent;
API = win.GetPlayer ? win.GetPlayer() : null;
}
return API;
}
// Retrieve Canvas User ID
var API = getAPI(window);
var userID = "unknown"; // Default value
if (API && API.GetStudentID) {
userID = API.GetStudentID();
// Debugging: Show the User ID if it's retrieved
alert("User ID Retrieved: " + userID);
} else {
// Debugging: Show an error message if User ID is not retrieved
alert("Error: User ID not retrieved. SCORM API might not be available.");
}
// Set the User ID in Storyline Variable
var player = GetPlayer();
player.SetVar("UserID", userID);
// Confirm that the variable has been set (optional)
alert("User ID set in Storyline: " + userID);
When the user clicks the red button, it runs this script and also opens the link to our AI tutor. (See screenshot 1). When we export the storyline as a SCORM package and import it into SCORM cloud, the javascript successfully searches for the UserID and tries to populate it in both the URL and the (temporary for testing) "User ID:" field in Storyline, but because it can't find it, it displays error messages. (see screenshot 2).
However, when we upload this same file to Canvas, the url just keeps it's placeholder and does not display any error messages.
The inspector in Chrome shows screenshot 3, but we confirmed our cross-origin frame permissions are wide-open and should not be causing any problems.
So we're wondering if something on Canvas's end is blocking our ability to gather the user ID. I'm happy to detail the situation more, but is anyone able to help? I'm just looking for a solution that finds the user ID in Canvas and puts it into the AWS url. We have a tight turnaround on this and either hope it's a solvable issue or the issue isn't on our end.
Thank you in advance!
Solved! Go to Solution.
For those stumbling on this post like I did when trying to figure out a way to reliably do this on the web version and the mobile app, I figured it out. I learned before that students can make API calls only to things they have access to without needing a token (i.e, their own user details) as everything in Canvas is loaded via API. I can't speak to doing it in scorm but this is the js solution.
const initProcedure = () => {
// API docs indicate you can use 'self' instead of a harcoded ID
fetch("https://yourorg.instructure.com/api/v1/users/self/profile", {
method: 'GET',
headers: {
'Accept': 'application/json'
}
})
.then(response => {
console.log(response)
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
})
.then(data => {
if(data != null) {
const uid = data.id;
// This is the user's ID, do something useful with it.
console.log(uid);
}
})
.catch(error => {
console.error(error);
});
};
I don't use SCORM, so I cannot test this. I'll just speak about things that cause me concern. They may be unfounded since I cannot test.
The first thing that struck my attention is your getWindow() function.
You're trying to find the top window. SCORM or other tools are probably loaded in an iframe and the parent window is the window embedding the iframe. It exists, but it is never the same as the window itself. That is, both win.parent exists (is truthy) and win.parent !== win because you cannot break out of the sandbox.
That means that it would have to find win.GetPlayer to get out of the loop, but that isn't enough. I don't know what the GetPlayer() function does, but if it returns a false value such as 0 or null, then your loop keeps going and it will never exit because you'll never get win.parent === win.
If the GetPlayer() was in the initial window, it would never trigger because you reset win before checking.
The next thing that strikes me as weird is that you call GetPlayer() when it may not exist. The whole idea of GetAPI() is to return the GetPlayer object, which you assign to API. That may not be on the current window, but when you invoke it in the third line of code from the bottom, you don't use API, you just use GetPlayer(). There is no guarantee that GetPlayer() exists there and may not because you always force the check to bypass the initial window and look at a parent.
It seems that the bottom three lines of code should be inside the check to make sure that API exists. Actually, I would let player = getAPI(); and not mess with the API variable at all. Then you could check to see if player exists before invoking player.GetStudentId() to get the userId.
As is, if GetPlayer is in the current window, then API will always be null and so the userId will be "unknown".
For a quick solution, the Canvas environment variable lets you get the current user ID:
var userID = ENV.current_user_id;
This doesn't appear to work in the Canvas mobile app. When I try to get ENV in the mobile app, it only seems to return the course ID for some reason. I am going to need to find a way to more reliably get this variable. I will post a seperate question since I realize this is an old post.
For those stumbling on this post like I did when trying to figure out a way to reliably do this on the web version and the mobile app, I figured it out. I learned before that students can make API calls only to things they have access to without needing a token (i.e, their own user details) as everything in Canvas is loaded via API. I can't speak to doing it in scorm but this is the js solution.
const initProcedure = () => {
// API docs indicate you can use 'self' instead of a harcoded ID
fetch("https://yourorg.instructure.com/api/v1/users/self/profile", {
method: 'GET',
headers: {
'Accept': 'application/json'
}
})
.then(response => {
console.log(response)
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
})
.then(data => {
if(data != null) {
const uid = data.id;
// This is the user's ID, do something useful with it.
console.log(uid);
}
})
.catch(error => {
console.error(error);
});
};
To interact with Panda Bot, our automated chatbot, you need to sign up or log in:
Sign InTo interact with Panda Bot, our automated chatbot, you need to sign up or log in:
Sign In