How to Use JavaScript in Storyline – Safe, Practical Examples

Storyline's triggers can do a lot, until one day you need today's date on a certificate, a cleaner way to check a typed answer or a score displayed as a tidy percentage, and the triggers panel just shrugs. That's when people start pasting code from forums and hoping, and hope is not a testing strategy. How do you use JavaScript in Storyline safely, without breaking the course or the next update?
You use JavaScript in Storyline through the Execute JavaScript trigger, and the safe pattern is simple: get the player with GetPlayer(), read Storyline variables with GetVar, do a small, focused calculation, and write the result back with SetVar. Let Storyline handle everything on screen, such as showing layers and changing states, based on those variables. Keep scripts short, wrap risky parts in error handling, and test in the published output, because preview won't always behave like the real course. Avoid scripts that reach into Storyline's internal page structure, because those break when the software updates.
How Does JavaScript in Storyline Actually Work?
When you publish a Storyline course, it becomes a web page that runs in the learner's browser. The Execute JavaScript trigger lets you run your own code at a moment you choose, such as when a slide starts or a learner clicks a button, and your code runs in that same browser page.
The connection between your code and the course is the player object, which Storyline provides through a function called GetPlayer(). From there, two methods do most of the work:
- player.GetVar("VariableName") reads the current value of a Storyline variable.
- player.SetVar("VariableName", value) changes it.
Variable names must match exactly, including capital letters. "numScore" and "NumScore" are two different things as far as the code is concerned. Create the variable in Storyline first, with the right type (text, number or true/false), before your script tries to use it.
The Safe Pattern: Variables In, Variables Out
Here's the habit that keeps courses maintainable: JavaScript does the calculating, and Storyline does the displaying. Your script reads variables, calculates something and sets a variable, and then normal Storyline triggers respond to that variable by showing a layer, changing a state or jumping to a slide.
Why does this matter? Because the next developer can see the logic in the triggers panel, and the script stays small enough to read in ten seconds. When Articulate updates the player, your code is unaffected, because it never touched anything except the documented variable methods.
Where Should the JavaScript Trigger Go?
Place it as close as possible to where the result is needed. A script that prepares values for a slide usually runs when the timeline starts on that slide, while a script that checks an answer runs when the learner clicks Submit. A script that responds to a variable can run when that variable changes.
Order matters too. Storyline runs triggers for the same event from top to bottom, and anything listed after a "jump to slide" trigger never runs at all. If your script sets numPercent and a later trigger checks numPercent in a condition, keep the script above it. Even safer, have the dependent trigger fire when numPercent changes, so it reacts to the script's result. Just remember that a change trigger only fires when the value actually changes, so test the case where it stays the same. Otherwise you can spend twenty minutes convinced your math is wrong when the real problem is trigger order.
Avoid putting important scripts on the slide master unless every slide truly needs them. Master scripts run more often than you expect, and they're easy to forget about when you're debugging a single slide.
Five Practical Examples You Can Adapt
Each example below assumes you've already created the variables it names. Add the code to an Execute JavaScript trigger and set the trigger's timing to fit the slide.
1. Put Today's Date on a Certificate
Create a text variable called txtToday and reference it on the certificate slide as %txtToday%, then run this when the timeline starts on that slide:
var player = GetPlayer();
var today = new Date();
var options = { year: "numeric", month: "long", day: "numeric" };
player.SetVar("txtToday", today.toLocaleDateString(undefined, options));
The date format follows the learner's browser settings, so people in different countries see the format they expect.
Notice the first line. Every example starts by getting the player, and it's good practice to add a short comment above it in real projects, such as a line starting with two slashes that says "Sets txtToday for the certificate slide." Future you will be grateful.
2. Show a Score as a Clean Percentage
Say you track correct answers in numCorrect and total questions in numTotal across custom interactions. This sets numPercent to a whole number, and it won't divide by zero if numTotal is empty:
var player = GetPlayer();
var correct = player.GetVar("numCorrect");
var total = player.GetVar("numTotal");
var pct = total > 0 ? Math.round((correct / total) * 100) : 0;
player.SetVar("numPercent", pct);
3. Check a Typed Answer Without Being Picky
Learners type extra spaces and mix capital letters, and that shouldn't make a correct answer wrong. This script trims the text, converts it to uppercase and compares it, then sets a true/false variable:
var player = GetPlayer();
var answer = player.GetVar("txtAnswer") || "";
var cleaned = answer.trim().toUpperCase();
player.SetVar("isAnswerCorrect", cleaned === "LOCKOUT");
One catch: a text entry field updates its variable only when it loses focus, so make sure the learner has clicked away, or clicked Submit, before this runs.
4. Pick a Random Scenario
Want learners to receive one of three scenarios at random? Set a number variable to 1, 2 or 3, then use normal triggers to jump to the matching slide:
var player = GetPlayer();
var pick = Math.floor(Math.random() * 3) + 1;
player.SetVar("numScenario", pick);
5. Remember Notes in the Browser
For a reflection activity, you might want a learner's notes to survive a page refresh on the same computer, and the browser's local storage can hold them. Wrap it in try and catch, because some browsers and LMS configurations block storage:
var player = GetPlayer();
try {
localStorage.setItem("safetyCourse_notes", player.GetVar("txtNotes"));
} catch (e) {
console.log("Notes not saved: " + e.message);
}
Use the same pattern with getItem to load the notes back, but keep this to non-sensitive content. Local storage stays on that device, isn't tracked by the LMS and could be visible to the next person on a shared computer, so anything you need for completion or reporting belongs in the LMS, not in the browser.
How Do You Test and Debug Storyline JavaScript?
Test in published output. Preview may not run your JavaScript the way the published course does, so publish to the web or to your LMS test area and open it in a browser. Some browsers also restrict scripts when you open course files straight from your hard drive, so a test LMS or a simple local web server gives more reliable results.

Then use the browser's developer tools by pressing F12 in most desktop browsers and opening the Console tab. Errors in your script appear there in red, with a line number. Add console.log() lines to print values as the script runs, which is the fastest way to confirm whether GetVar is returning what you expect.
If nothing happens at all, check the basics first: a misspelled variable name, a missing semicolon or quote, or a trigger that never fires because its condition is false. In my experience, those three explain most "my script doesn't work" messages. Remove your console.log lines before the final publish so the console stays clean.
For language questions, MDN's JavaScript guide is the reference I trust, because it's clear, accurate and full of small examples you can adapt.
Rules That Keep JavaScript in Storyline Safe
These rules come from cleaning up other developers' code more times than I'd like to admit:
- Don't use JavaScript for things triggers can do. Showing layers, changing states and jumping slides belong in triggers.
- Don't reach into Storyline's page structure. Scripts that grab internal elements by class name or ID break when the player updates.
- Keep each script short and focused on one job. If it scrolls, split it or rethink it.
- Add a comment line at the top saying what the script does and which variables it uses.
- Don't load outside libraries from the internet. Many corporate networks and LMSs block them, and they add security risk.
- Don't store personal data in the browser. Use the LMS for anything that needs to be tracked.
- Keep a snippet library. Save tested scripts in a shared file so the team reuses proven code instead of pasting from forums.
- Test on every browser your learners use, including on mobile if they'll take the course there.
When Should You Not Use JavaScript at All?
Avoid it when the built-in features already work. JavaScript adds a layer that many Storyline developers can't read or maintain, so if the person updating the course next year doesn't know JavaScript, every script is a small risk. Use it where it genuinely saves time or adds something triggers can't, and document it well.
Also think twice about JavaScript for media. You can control audio and video with code, but it's fiddly and fragile across browsers. Most audio problems in courses aren't code problems anyway. They start at the microphone, which is why good eLearning narration habits fix more audio issues than any script ever will.
Small Scripts, Big Wins with JavaScript in Storyline
JavaScript in Storyline is a precision tool, not a rebuild kit. Read variables, calculate, write variables back, and let Storyline's triggers do the rest. That pattern handles dates, percentages, forgiving text checks, random scenarios and simple browser storage, and it survives software updates.
Pick one example from this article and drop it into a throwaway test file. Publish it, open the console, watch the variables change and get comfortable with the loop. Once you trust the process, you'll know exactly when a few lines of code are the right answer and when a trigger would have done the job just fine.