
Personalized SCORM: a guide with examples from Oleh Selezen
Imagine opening a training course and it greets you by name, knows your position, addresses you in the appropriate gender, and even customizes the examples for your department. This is not magic. It’s not fiction. It’s just a well-tuned personalization system.
This is a completely different level of learning – when the content doesn’t just exist, but speaks directly to you. When, instead of a one-size-fits-all approach, you get the feeling that the course was created just for you. This is not only pleasant, but also has a significant impact on engagement, motivation, and results.
But how do you make SCORM work more humanely? Or even more adapt the content to the user’s position and automatically generate a personalized certificate at the end of the training?
Oleh Selezen, Head of Distance Learning at VIYAR, became interested in this issue. And together with the LMS Collaborator team, they found a solution and developed an approach that allows you to “pull” additional data from SCORM and adapt the course content right in the process.
This article contains a real-life case study, step-by-step instructions, code samples, and simple explanations to help you do the same in your courses.
How did it all start?
The story began not with a great idea, but with a simple but very apt request.
About a year ago, Oleh Selezen turned to the LMS Collaborator team with a request: “Is there any way to extract more than just a name and email from a SCORM course?” After all, this is clearly not enough for true personalization.
The idea caught our eye and we decided to experiment. We created a test learning portal and started playing with the boundaries of SCORM. That’s how the cmi.core.student_info custom variable appeared. Technically, it’s not in SCORM 1.2 or SCORM 2004, but it allows you to pass additional data: gender, position, department, etc.-anything that can affect the adaptation of the content.
Meanwhile, Oleh wrote his own JavaScript code that pulls this data from the LMS, stores it in variables, and uses it inside the course.
This is how we got it:
- addressing the user in the right way;
- displaying different blocks depending on the position;
- customizing the training logic for the role in the company.
From a simple request, a full-fledged approach grew, which is now being used on real projects. Oleh himself will tell you how everything works step by step below.
Oleh Selezen – Head of the Distance Learning Department at VIYAR
How to get and use data from LMS
To avoid wasting time guessing, I have collected a complete list of variables that LMS Collaborator passes through cmi.core.student_info. I also prepared a JavaScript code that will help you read this data in the course.
On the LMS Collaborator side, the transfer of advanced user information is already configured. In particular, their position, department, email, gender, even a link to a photo. All this information comes through the cmi.core.student_info variable.
For this data to work in your course, you need to create variables with the correct names and types in Articulate Storyline. Then you can manage course content according to each user’s profile.
Variables you need to create in Articulate Storyline:
What it looks like in practice: a ready-made example of a SCORM course with personalization
For clarity, I have prepared an example of a course with embedded code. It shows exactly how content personalization is implemented based on data from the LMS. Everything I mentioned above:
– addressing the user by name;
– adaptation of text depending on gender;
– automatic display of the position and department name on the screen;
– uploading a user’s photo from their LMS profile;
– generating a personalized certificate with automatic filling in of personal data.
You can easily adapt this example to your courses. Just change the texts, colors, or design styles.
Download the sample file to test everything in your own course or use it as a basis for your projects: download the file
Practical part: how to set up personalization
Now to the technical implementation.
The first step is to prepare a JavaScript code sample that reads the extended data from LMS Collaborator and passes it to the variables of your course created in Articulate Storyline.
The code works equally well in both SCORM 1.2 and SCORM 2004, so you don’t have to do any additional work. You just need to insert it into the project once, and the course will be ready for publication in either format.
An example of a ready-made script
function findLMSAPI(win) {
if (win.hasOwnProperty(“API”)) return win.API;
else if (win.parent == win) return null;
else return findLMSAPI(win.parent);
}
function getSCORMValue(element) {
try {
var lmsAPI = findLMSAPI(this);
if (lmsAPI) {
let value = null;
if (typeof lmsAPI.LMSGetValue === “function”) {
value = lmsAPI.LMSGetValue(element);
}
if (value === “” || value === null) {
}
return value;
} else {
return null;
}
} catch (error) {
return null;
}
}
function setArticulateVar(variable, value) {
var p = GetPlayer();
if (p && typeof p.SetVar === “function”) {
p.SetVar(variable, value);
let checkValue = p.GetVar(variable);
}
}
function checkAndSetArticulateVars(studentData) {
var p = GetPlayer();
if (p && typeof p.SetVar === “function”) {
const mappings = {
user_id: String(studentData.id),
user_uid: String(studentData.uid),
user_is_chief: studentData.is_chief,
user_position_rank: studentData.position_rank,
user_email: studentData.email,
user_fullname: studentData.fullname,
user_gender: studentData.gender,
user_city: studentData.city,
user_position: studentData.position,
user_department: studentData.department,
user_firstname: studentData.firstname,
user_secondname: studentData.secondname,
user_patronymic: studentData.patronymic,
user_international_name: studentData.international_name,
user_photo_thumb: studentData.photo_thumb,
user_big_photo_thumb: studentData.big_photo_thumb
};
for (const articulateVar in mappings) {
const value = mappings[articulateVar] !== null && mappings[articulateVar] !== undefined ? mappings[articulateVar] : “”;
setArticulateVar(articulateVar, value);
}
} else {
setTimeout(checkAndSetArticulateVars, 500, studentData);
}
}
function Script1() {
try {
var lmsAPI = findLMSAPI(this);
if (lmsAPI) {
var student_info = getSCORMValue(“cmi.core.student_info”);
if (student_info) {
try {
var studentData = student_info;
checkAndSetArticulateVars(studentData);
} catch (parseError) {
}
}
}
} catch (error) {
}
}
setTimeout(function() {
Script1();
}, 1000);
The script is ready, but for it to work smoothly and read data for each user, you need to insert it in the right place.
So the second step is to add the code to the Slide Master (this is the best solution).
This way, the code will automatically run, regardless of which slide the user starts the course. You don’t need any additional triggers or checks – the data is read from the LMS immediately.
Personalized address and adaptation of the text by gender
To make the course “communicate” with the user, you can implement two key elements of personalization: addressing by name and automatically adapting the text depending on gender. Here’s how to do it:
1. Create the necessary variables in the Storyline:
- user_firstname – type Text, (contains the username)
- user_gender – type Text, (value: male or female)
These variables are automatically filled with data from the LMS through the connected code.
2. Use variables in your slide text:
To address a user by name, simply insert user_firstname in the desired place in the text.
To change words based on gender, for example, “ready” to “ready”, use Conditions in triggers or States on objects.
How it works in practice:
Create two separate text objects: one with the word “ready” and one with the word “finished”. Then set a display condition for each of them:
- If user_gender is male, display “ready”
- If user_gender is female, display “ready”
As a result, the course addresses the user by name, as a real-life interlocutor would, and changes the wording depending on gender. This creates the effect of a “live” dialog and personalizes the learning experience – as if the course was created for that person.
Adaptation of the course scenario for each user
After receiving the values of the variables from the LMS, you can flexibly manage the course scenario. Customize it for a specific user so that everyone sees only what is relevant to their role, department, or tasks.
For example:
- the user_position variable allows you to show certain slides only for certain positions (for example, separately for managers and salespeople);
- user_department displays different content depending on the department (for example, the logistics department will receive one version, the sales department will receive a completely different one).
With these variables, you can personalize course content in real time:
– hide or show individual objects and content blocks,
– launch different scenario branches depending on the role,
– create a unique experience for each employee.
All this works without any extra settings. It is enough to read the variables once, and then the course adapts to each person like a personal assistant.
Displaying a user’s photo
Another way to make the course as personalized as possible is to show the user’s photo right in the interface. This adds a sense of live contact with the person on the other side of the screen.
This requires two variables:
- user_photo_thumb – photo thumbnail (128×128)
- user_big_photo_thumb – larger version (180×180)
But it’s not that simple. In Storyline, you can’t directly link a URL to an image, so JavaScript will help.
There are two ways to implement this:
Option 1: WebObject
The easiest way is to insert a ready-made HTML file with the <img src=”…”> tag into the slide, which will automatically pull up the desired photo.
This is a very simple and reliable way because you don’t need to write any triggers or JavaScript code manually. Just insert a WebObject and everything works automatically as soon as the user_photo_thumb or user_big_photo_thumb variables are set to a value.
But, like any solution, WebObject has its own peculiarities:
- A WebObject takes up the entire slide, so you should set its exact size so that it doesn’t overlap other elements (for example, 180×180).
- Until the course is uploaded to the LMS, you may see a black square instead of a photo. This can make it a little difficult to visually position objects when designing a course.
By default, the photo shape is square, but you can make it round. To do this, set the photo_is_round boolean variable:
- false – square photo;
- true – round photo (border-radius: 50% style is applied).
If your LMS doesn’t allow you to upload photos or if you’re testing the course locally, use a placeholder file (placeholder.jpg). With it, the user will see a pre-prepared neutral icon instead of an empty space.
💡Download the file user_photo (.html)
Option 2: Replace the photo inside the shape
This method is a bit more complicated than the previous one, but it gives you complete design freedom and helps you create a unique style for your photo.
You can use any standard Storyline shape: circle, square, hexagon, etc. The shape of the shape will work as a “frame” or “mask” and it determines how the photo will look on the screen.
It is important to take a few preparatory steps:
- Create the shape you want on the slide.
- Add a placeholder image inside the shape.
- Copy the id of the element that contains the placeholder. This is the id the script will use to change the photo.
- Add this id to the JavaScript.
- Use JavaScript to dynamically replace the image inside this shape with user_photo_thumb or user_big_photo_thumb.
This is what it looks like in the interface:
Ready-made code that can be inserted into your course. Just replace the id with your own:
JavaScript
(function replaceUserPhoto() {
var player = GetPlayer();
var photoURL = player.GetVar(“user_big_photo_thumb”);
if (!photoURL) {
console.warn(“user_big_photo_thumb is empty or not specified.”);
return;
}
// Enter the required data-model-id here manually
var modelId = “”;
function trySwap() {
var container = document.querySelector(`[data-model-id=”${modelId}”]`);
if (!container) return false;
var img = container.querySelector(“image”);
if (!img) return false;
var currentHref = img.getAttributeNS(“http://www.w3.org/1999/xlink”, “href”);
if (currentHref === photoURL) return true; // is already replaced
img.setAttributeNS(“http://www.w3.org/1999/xlink”, “href”, photoURL);
img.setAttribute(“href”, photoURL);
return true;
}
// Waiting for the object to appear in the DOM
var attempts = 0;
var maxAttempts = 100;
var poll = setInterval(function () {
if (trySwap() || ++attempts >= maxAttempts) {
clearInterval(poll);
}
}, 30);
})();
Generating a personalized certificate
The final touch of personalization is the issuance of a personalized certificate with the user’s personal data, your company’s brand design, and dynamic variables. All this can be done through WebObject.
What can be customized?
- Insert the name, surname, position, and other variables directly on the certificate.
- Change the certificate background, add any image with your own style, logos, and signatures.
- Display dynamic data from Storyline using the same variables (user_firstname, user_position, etc.).
- Provide the ability to download a PDF file of the generated certificate in one click.
How to add a custom background to a certificate?
- Prepare the certificate image in PNG or JPEG format.
- Encode the image in Base64 format – this is a special code that can be inserted directly into HTML. To do this, use the following service: https://www.base64-image.de/
- Copy the generated code starting with data:image/png;base64,…
- Paste this code into an HTML file as a background image of the certificate. Then add it to your slide as a WebObject.
- Create a trigger to call printing:
Code
var iframe = document.querySelector(‘iframe’);
if (iframe && iframe.contentWindow && iframe.contentWindow.generatePdf) {
iframe.contentWindow.generatePdf();
}
💡You can download an example of such an HTML template here: Download an example HTML template
The %course_title% variable automatically substitutes the course title into the certificate during generation. The date of generation is also added automatically – you do not need to fill it in manually.
Thank you for reading this far! I hope you find useful case studies and ideas that you can adapt to your Storyline courses. We’ve gone from basic variables to personalized photos and certificates – and all of this is in the ready-made example. Let your courses be not just educational, but personalized, effective, and engaging!
Conclusion
Personalization in learning is not just a trend, but a powerful tool for increasing engagement and efficiency. When a course “speaks” to the user in their language, addresses them by name, and adapts the content to their individual needs, it creates a completely different learning experience.
This approach yields tangible results:
- increases course completion rates,
- improves learning,
- creates an emotional connection with the content,
- forms a positive attitude towards corporate training.
Oleh Selezen proved in practice that it is possible to do this even within SCORM courses. With the right tools and a little tweaking of the standard, you can create courses that will be perceived not as a template, but as content created specifically for each employee. And this is the main strength of modern e-learning.
