JavaScript & Qualtrics: Getting Started
As mentioned in a previous post, Qualtrics is a fantastic platform that allows for really cool JavaScript manipulation of questions and view. In this post I highlight some low level things you can do to get started using JavaScript in a Qualtrics Survey. In my best practice post I highlight some more advanced things you can do, as well as best practices for front end developers looking to develop on Qualtrics.
While possibilities with JavaScript in Qualtrics are basically limitless, my time and typing is not. In this post I highlight just a few things that someone with little to no coding experience could add to a survey, with an explanation of why it works and how to implement it.
To get started, let’s familiarize ourselves with three key areas of the survey editor:
Question Text HTML Editor
When editing a question you have several options for modifying the question text. The normal option is actually an enriched view that hides HTML. You also have a rich context editor. The option that will be most useful to you in this post is the HTML view, which is pointed to above. It shows the raw HTML for the question, which will allow us full control.
Question JavaScript Editor
While Qualtrics does allow for HTML and CSS in the HTML view of the question, the survey editor will strip out any JavaScript. Instead, you include JavaScript in the editor provided by Qualtrics.
Custom CSS Portal
As mentioned previously, Custom CSS can be included at the question level, but it becomes unpredictable because that CSS will only be applied on the page that contains that question. Global CSS is better suited for the Custom CSS Portal accessed in the Look & Feel > Advanced screen, shown above.
Also important here is the Header and Footer, which also accept raw HTML, including JavaScript and CSS.
Example JavaScript Implementations
As mentioned above, there are lots of ways to modify a survey using JavaScript. I’ll highlight a few here and add more over time.
Adding a Date Picker
This is actually pretty easy given a great plugin built by dbushell on GitHub called Pikaday. You can easily load it in by adding the following references to your header:
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/pikaday/1.6.1/css/pikaday.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/pikaday/1.6.1/pikaday.min.js"></script>
What we’ve done here is loaded in a page of CSS and a page of JavaScript that are used to format and create a date picker. The first reference is a link
tag which contains the CSS. The script
tag contains the JavaScript.
All this does is make this JavaScript available, however, so we still need to configure it to work in our survey. The easiest way to implement this would be to go to a question of your survey, change the type to Text Entry
, and then open up the JavaScript Editor. Go ahead and replace the first addOnload function with the following:
Qualtrics.SurveyEngine.addOnload(function() {
var inputId = 'QR~' + this.questionId;
var picker = new Pikaday(
{
field: document.getElementById(inputId),
firstDay: 1,
minDate: new Date(),
maxDate: new Date(2020, 12, 31),
yearRange: [2000,2020]
});});
At this point you’re done! This will allow you to select any date from now until the end of 2020. Not good enough? Let’s figure out how to configure this for your exact needs.
We’ll start out by going through this line by line so we understand what is happening. The first line is a Qualtrics native function. The addOnload
function accepts a callback, which basically means you can give it code to execute once it’s finished doing whatever it’s supposed to do. So we feed it function() {}
and expect it to run whatever is within the {}
s.
The first line of that function is declaring a variable that we will use later. We need to find the Text Entry box on the screen, and those always have the format of QR~<QUESTION_ID>
. So we build that by merging QR~
with another Qualtrics native function that gets the id of the current question, this.questionId
.
Finally, we create a new instance of the Pikaday and name it picker
. That constructor accepts an object, which is the information contained in the {}
s. These are basic key-value pairs. The first is the field
which accepts the DOM location of the text input, which we found earlier and already named inputId
. The next key is firstDay
, which accepts a 0
or 1
, depending on whether the week should start on Monday or Sunday. The rest are pretty self explanatory and can be modified quite easily.
In JavaScript new Date()
will always return the exact moment that it was invoked, so the minDate
above will be set to today’s date. If you want people to be able to select a range in the past you can add a date range as you see in the maxDate
key.
There are a range of ways to modify this calendar picker all available on the GitHub site for the Pikaday plugin. If you’re a more advanced JavaScript programmer I recommend taking a look at adding more features you may need.
Bonus! Calculate age based off a date
I throw this in here because it’s an often requested feature and it plays nicely with the existing JavaScript we’ve already added. The Pikaday API accepts an onSelect
key which can run a function. We can add that as the last element of the key-value pairs like this:
var picker = new Pikaday({
field: document.getElementById(inputId),
firstDay: 1,
minDate: new Date(1900, 01, 01),
maxDate: new Date(),
yearRange: [1900,2017],
onSelect: function(date) {
calculateAndSaveUserAge(date);
}
});
This is basically saying that when someone selects a date, run a function called calculateAndSaveUserAge
and give it the date
as an argument. Now we can make that function outside of the picker
declaration like so:
function calculateAndSaveUserAge(date) {
var todayInSeconds = new Date().getTime();
var birthdayInSeconds = date.getTime();
if (birthdayInSeconds < todayInSeconds) {
var ageInSeconds = todayInSeconds - birthdayInSeconds;
var ageInYears = Math.round(ageInSeconds / 1000 / 60 / 60 / 24 / 365);
Qualtrics.SurveyEngine.setEmbeddedData("Age", ageInYears);
} else {
alert("You cannot be born in the future!");
}
}
This function takes today’s date and runs the getTime
method on it. This is a built in function that JavaScript offers to get the number of milliseconds since January 1, 1970. We then run the same method on the date object that was passed into the function and subtract the two, giving us the person’s age in milliseconds. Finally, we convert that to years and store it as embedded data using the Qualtrics JavaScript API’s setEmbeddedData
function. We just need to be sure to declare Age
as an Embedded Data field in the Survey Flow and then we’re set to go!
Adding a Timer that Spans Pages
One request I hear a lot is the desire to add a timer to a survey that can time someone across page breaks. A common use case for this type of thing is an exam that should end after a certain amount of time.
Luckily for us, this is a pretty easy task! From a high level, we simply need to set a start time, then periodically check the current time against the start time to know the elapsed time. If we want a countdown timer, then we can simply subtract the elapsed time from the total allowed time.
Qualtrics makes this easy for us given its ability to store embedded data. We’ll use the same getTime
method above when we start the survey and store that as StartTime
in the embedded data. At the question that we want to declare as the start time, add this to the JavaScript. One way of doing this might be attaching this to the Next Button on the page leading to the quiz section.
Qualtrics.SurveyEngine.setEmbeddedData('StartTime', new Date().getTime());
Of course, to use this we need to instantiate the StartTime
embedded data field in the Survey Flow. Go ahead and add that now.
Now that we have that, we can add a function that gets the elapsed time and displays it to the user. First we’ll need a place to drop that elapsed time though, so let’s put this in the header:
<div id="ClockContainer">
<div id="Clock"></div>
</div>
Now, for the function:
This can seem overwhelming at first, but I think once you look at it the comments should help it make sense. Start at line 63
and follow the functions from there.
Finally, we probably want to add some CSS to the timer to make it look fancy. In my case, the CSS is pretty simple, but in yours you may want to go all out. Here is my simple CSS that can get you started:
#ClockContainer {
position: absolute;
right: 0;
top: 0;
}#Clock {
padding: .5em 1em;
border: 1px solid #4CAF50;
display: inline-block;
float:right;
margin: .5em;
font-size: 20px;
color:#4CAF50;
font-family: 'Orbitron', 'Courier New', 'Courier', sans-serif;
font-weight: 200;
min-width: 150px;
text-align: center;
}
This can be added to the Custom CSS menu in the Look & Feel > Advanced tab. The Orbitron font is provided by Google Fonts and can be referenced at the top of the Header if you’d like.
And there you have it! A working clock that spans multiple pages. See if you can modify it to change colors as it approaches zero, or to close out the survey session on complete! Have fun!
Scroll to Top or Bottom of a Survey on Click
This one is relatively simple and can be accomplished in two ways. In general, there are two ways to scroll a page. You can use the HTML anchor
tags, or use JavaScript. To scroll to the top, let’s use HTML.
HTML has some built in functionality that works across every browser and most email clients. One of those is the ability to set anchors, classes, and IDs on a page. On a Qualtrics Survey, the elements of the page are all named according to purpose, as seen in the following graphic:
We can use this structure to our advantage when we want to direct people around a survey, since any ID can be referenced using HTML’s anchor
tag like the following:
This is text but if you click <a href="#ProgressBar">here</a> something will happen!
The above HTML will make the ‘here’ look like a hyperlink, but when clicked, it will simply scroll to the top of the page. The reason is that the HTML interprets it as a referential point on the page and scrolls to the top of that point.
Scrolling to the bottom can obviously be done the same way, but using a different id, say the #Buttons
id. However, often this request comes in terms of wanting to scroll to the bottom after answering a question, whereas scrolling to the top is usually okay as separate text field or button.
Question answers accept HTML, but it gets clunky because if someone clicks the button but not the text, the HTML anchor won’t trigger. Instead, let’s use JavaScript to handle this.
In the JavaScript editor for the question we want to attach the scroll to bottom, we can paste in the following JavaScript:
Qualtrics.SurveyEngine.addOnload(function()
{
function findPos(obj) {
var curtop = 0;
if (obj.offsetParent) {
do {
curtop += obj.offsetTop;
} while (obj = obj.offsetParent);
return [curtop];
}
}
this.questionclick = function(event,element) {
if (element.type == 'radio') {
window.scroll(0,findPos(document.getElementById("Buttons")));
}
}});
This is pretty simple, so let’s go through it. We’ll start at the this.questionclick
. That is a Qualtrics method that allows us to listen for someone clicking the question. We then check if they selected a radio button. We don’t want to scroll unless they answer. If they simply click the question text we want it to do nothing. Finally, we scroll them using the built in window.scroll
method. It accepts two arguments, the x and y position to scroll to. The first is 0
because we don’t care about the x position, and the next will be returned by the findPos
function we wrote above this. This accepts an object on the page, then finds its position and returns it. As you can see, we feed that function the object using the built in document.getElementById
method, feeding it the ID to which we want to scroll.
This will work on any Multiple Choice question, and could obviously be modified to work on any other question type.
Custom JavaScript Validation
One complaint I hear a lot with Qualtrics is that when you need to add upwards of 20 lines of validation to a question it would be easier with code. That’s true! But how would you do it?
Most people like the look & feel of the standard Qualtrics validation messages, so let’s stick with those. My approach would be:
- Hide the default next button and create our own
- Create a set of functions as a toolset
- Handle page load for that specific page
At the question level, the following JavaScript will hide the next button and create a custom one. The idea here is stop the default action when clicking Next and instead run through our own validation checks.
You’ll notice that a lot of the functions referenced here don’t exist yet! We’re going to put those in the header, like so:
Now the last step is to add in your custom validation. You’ll see that I’ve added in 3 if
statements in the isValidQuestionResponse
function. It is within this function that you would add any failure conditions. Within each condition you should set isValid
to false
, as well as adding an object containing a text
and selectorId
key to the warnings
array. The text will be what displays to the end user, and the selectorId will be the css selector of the input. The showWarnings
function will add a sibling to that input that contains the warning text.
Wow, you made it to the end!
You might want to check out these best practices for writing Qualtrics JavaScript.
Or, jump right into fixing the latest modern theme to be more intuitive!