Survey Custom Scripting Language (CSL) snippets

Medallia Agile Research offers a powerful scripting language called the Custom Scripting Language (CSL) to enhance your surveys and reports

You can use it to place variables in your surveys and reports by selecting them from a dropdown.

This scripting language provides the ability to use complex logic to make calculations, show or hide certain blocks of texts or images, and much more.

See below for ready-to-use CSL code snippets for different situations. Each snippet can be used immediately or you can tailor it further to your own specific situation.

Pronouns

You can use CSL for he, him, his, she, her, hers, etc.

This is useful, for example, for 360° surveys where employees need to review their colleagues. This way you can refer to that colleague with the correct pronoun.

In this example, the pronoun is defined by a question but it can also be defined by the gender uploaded with the contacts. The code for that is provided as well.

You put this code directly in the question or answer option where you need the pronoun.

"He" or "She" depending on the selection in a question with label "questiongender". The first answer option is "man" hence we use "orderNumber 1" to check this.

{{#if (eq respondent.questions.questiongender.orderNumber 1)}}He{{else}}She{{/if}}

"His" or "Her" depending on the selection in a question with label "questiongender".

{{#if (eq respondent.questions.questiongender.orderNumber 1)}}his{{else}}her{{/if}}

When based on the contact gender, this is the code to use for he/she:

{{#if contact.gender.isMale}}He{{else}}She{{/if}}

The following is the code to use for his/her:

{{#if contact.gender.isMale}}his{{else}}her{{/if}}

Quizzes

You can use CSL to create a quiz. Register the end score and show a different text based on that score.

You can also provide the overview of provided answers with some additional info

  1. First create the questions and assign labels to each question.

    In the Live example we added three quiz questions:

    1. How often do you eat fruit? (label: "fruitconsumption")
    2. How often do you exercise? (label:"exercise")
    3. Do you smoke? (label: "smoking")
  2. Decide which answers yield which score.
  3. Create outcome questions to register that score. Hide these questions for the respondents.In our example the outcome questions are set up as follows:
    1. For fruit, the answer "daily" will result in a green score. Both "multiple times per week" and "once per week" result in an orange score. And "less than once per week"  results in a red score.
    2. For exercise, both the answers  "daily" and "multiple times per week" will result in a green score. "Once per week" results in an orange score. And "less than once per week" results in a red score.
    3. And for the smoking question, "yes" is a red score and "no" is a green score.

Scoring

Now it's time to register a score for each possible answer option.

For each score registration question, go to the Prefill tab and select Fixed Text. Then add your CSL code in that text box to register whether a respondent had a green, orange, or red score for each subject. This score can subsequently be used in the reports.

The following is example code for fruit consumption.

{{#if (eq respondent.questions.fruitconsumption.orderNumber 1)}}1

{{! if the respondent selects the first answer option then we tick the first answer option in this result question, which stands for "green"}}

{{else if (or (eq respondent.questions.fruitconsumption.orderNumber 2)(eq respondent.questions.fruitconsumption.orderNumber 3))}}2

{{! if the respondent selects the 2nd or 3rd answer option then we tick the second answer option in this result question, which is the "orange" result}}

{{else}}3

{{! all other cases get "red" as result}}

{{/if}}

The following is example code for exercise.

{{#if 

{{! if the respondents selects the first or second answer option then he gets "green" as a result}}

(or (eq respondent.questions.exercise.orderNumber 1)(eq respondent.questions.exercise.orderNumber 2))}}1

{{!if he selects the 3rd option he gets "orange" as a result}}

{{else if (eq respondent.questions.exercise.orderNumber 3)}}2

{{! all other cases are "red"}}

{{else}}3{{/if}}

The following is example code for smoking.

{{#if (eq respondent.questions.smoking.orderNumber 1)}}1{{else}}2{{/if}}

Outcome texts

And then, of course, there are the different outcome texts that respondents get depending on their score.

In this case, put the code in a Text/media question.

{{else if (or (eq respondent.questions.fruitconsumption.orderNumber 2)(eq respondent.questions.fruitconsumption.orderNumber 3))}}
    You eat fruit every week, which is already good.
    Can you try to step it up a notch and see if you can incorporate fruit into your daily meals? 
    
    {{else}}
    You do not eat enough fruit.
    Try and eat at least one piece of fruit every day. Add it to a yogurt bowl or make a (green) smoothie. You'll be amazed at the results.{{/if}}

The following is example code for exercise.

{{#if (or (eq respondent.questions.exercise.orderNumber 1)(eq respondent.questions.exercise.orderNumber 2))}}

You exercise (almost) daily, which is great!

Keep up the good work.

{{else if (eq respondent.questions.exercise.orderNumber 3)}}

You exercise weekly, which is good.

But surely you can sneak in an extra session or 2? Even going for a walk for half an hour (or more) is better than slouching in the couch.

{{else}}
You don't exercise at all.

Your body (and soul) deserve better than that.

Start small: take a stroll through the neighborhood, or go cycling for half an hour. Do you like to dance? Turn your living room into a disco and dance, dance, dance! You'll be surprised at how good you feel afterwards.

Then build up gradually until you get to at least 3 exercise sessions per week.{{/if}}

The following is example code for smoking.

{{#if (eq respondent.questions.smoking.orderNumber 1)}}
You smoke.

Quit! It's a nasty habit, and no good ever came from it.

{{else}}

You don't smoke

Best decision of your life! It's a nasty habit, and no good ever came from it.{{/if}}

Concept testing

Based on the answer pattern of your respondents, you can show different images, text, prices, and so on to them. This is useful when you want to test different concepts, and these differ based on certain answers or socio-demographic criteria.

When using images, upload them into the media library and copy the HTML code.

In the examples below, we base ourselves on two questions ,age and gender, but you can go as broad as you like.

The following example is based only on the age of the respondent.

We are showing two different images — image 1 is shown to people younger than 45 and image 2 is shown to people aged 45 and older.

{{#if 
{{! this bit says if the age is the first, second or third option, then show image 1}}
(or (eq respondent.questions.agequestion.orderNumber 1)(eq respondent.questions.agequestion.orderNumber 2)(eq respondent.questions.agequestion.orderNumber 3))}}[html code of image 1]

{{! if not, show image 2}}

{{else}}[html code of image 2]{{/if}}

But you can combine age and gender.

The following snippet shows 4 different images: one to women younger than 45, one to men younger than 45, one to women 45 and older, and a fourth one to men 45 and older:

{{#if

{{! we check 2 things: 1: is the gender the first answer option AND is the age one of the first 3 answer options}}

(and (eq respondent.questions.genderquestion.orderNumber 1)(le respondent.questions.agequestion.orderNumber 3))}}[html code of image 1]

{{else if 

{{! again check if the age is one of the first 3 answer options, but now we need the 2nd answer option for gender, i.e. the women}}

(and (eq respondent.questions.genderquestion.orderNumber 1)(gt respondent.questions.agequestion.orderNumber 3))}}[html code of image 2]


{{else if

{{! now we look for the older respondents so the age must be the 4th answer option or higher. Gender is back to "men"}}

(and (eq respondent.questions.genderquestion.orderNumber 2)(le respondent.questions.agequestion.orderNumber 3))}}[html code of image 3]

{{else}}

{{! all other cases, meaning the women of 45 and older}}

[html code of image 4]{{/if}}

It also works with regular text:

{{#if (and (eq respondent.questions.genderquestion.orderNumber 1)(le respondent.questions.agequestion.orderNumber 3))}}young man{{else if (and (eq respondent.questions.genderquestion.orderNumber 2)(le respondent.questions.agequestion.orderNumber 3))}} young woman{{else if (and (eq respondent.questions.genderquestion.orderNumber 1)(gt respondent.questions.agequestion.orderNumber 3))}}slightly less young man{{else}}slightly less young woman{{/if}}

Prefill age category based on age

It is important to think about how you want to analyze and present your data ahead of time. A good example is age.

Say you have birth dates or ages in a contact field. If you know that you want to present your survey results with a breakdown based on certain age categories, then you can set that up ahead of time by creating a hidden radio buttons question with the age categories you want. That way, you can make charts, filters, and break out results based on those age categories.

To do this, complete the following steps:

  1. Add a new radio button question.
  2. Enter as answer choices the age categories you would like to have.
  3. Select the Prefill tab and select Fixed text.
  4. Add the following CSL, adjusted to match your categories. It assumes that the source is a contact field called Age:
{{#if (lt contact.customFields.Age 20)}}
1
{{else if (lt contact.customFields.Age 30)}}
2
{{else if (lt contact.customFields.Age 40)}}
3
{{else if (lt contact.customFields.Age 50)}}
4
{{else if (lt contact.customFields.Age 60)}}
5
{{else}}
6
{{/if}}

The numbers 1,2,3,4,5,6 stand for the answer option order number:1 = less than 202 = 20 to 293 = 30 to 394 = 40 to 495 = 50 to 596 = 60 plus

The 'lt' stands for less than. It says if the contact field 'Age' is less than 20 then select answer choice 1, else …

If you use other ranges, adjust the answer choices and the code to match. The source could also be question instead of a contact field, like a slider or textbox with integer validation.

If you have a data-of-birth, then you can calculate the age and place it in a temporary variable with the following code:

{{set "age" (dateDiff respondent.questions.DOB currentDate "year")}} or {{set "age" (dateDiff contact.dateOfBirth currentDate "year")}}

{{#if (lt (get "age") 20)}}
1
{{else if (lt (get "age") 30)}}
2
{{else if (lt (get "age") 40)}}
3
{{else if (lt (get "age") 50)}}
4
{{else if (lt (get "age") 60)}}
5
{{else}}
6
{{/if}}

Prefill region based on selected province or state

You may want to do an analysis based on a larger geographical region as well as on the province or state that a respondent lives in.

While this used to mean that you needed to ask both questions or add the info manually to the raw data, use CSL to capture the larger region in a hidden question based on the city, state, or province that a respondent selected in a previous question.

More specifically, you will use the score of the base question to prefill a subsequent question. This score represents the order of the answer options in the follow-up question.

Additionally you can use this hidden question to set your quota.

  1. Create the province question. Assign a label to it. In this particular case, the label "provinceQuestion" was used.
  2. Assign a score "1", "2" or "3" to each province. Each score represents a region, e.g. 1 = Vlaanderen, 2 = Brussel and 3 = Wallonië.
  3. Create the region question.
  4. Make sure that the order of the regions is consistent with the allotted score (i.e., if the Flemish provinces received a score of 1, put Vlaanderen as the first answer option).
  5. Select the Prefill ab and select Fixed text.
  6. Add the score variable:
    {{respondent.questions.provinceQuestion.score}}

This way, the region question will be prefilled based on the score of each answer option in the province question.

A province with score 1 will result in the prefilling of the first answer option in the region question, a province with score 2 will prefill the 2nd answer option, etc.

Prefill Nielsen region based on selected province

Nielsen regions are used often in market research. Respondents don't know what Nielsen regions are or which one they live, so asking this question would be quite useless. But you can capture this information in a hidden question based on their response to the province question.

  1. Create the province question. Assign a label to it. For this example, the label "provinceNielsen" was used.
  2. Assign a score between 1 and 5 to each province. Each score represents a Nielsen region.
  3. Create the Nielsen region question.
  4. Make sure that the order of the regions is consistent with the allotted score.
  5. Select the Prefill tab and select Fixed text.
  6. Add the score variable:
    {{respondent.questions.provinceNielsen.score}}

This way, the correct Nielsen region will be selected based on the score of each answer option in the province question.

A province with score 1 will result in the prefilling of the first answer option in the region question, a province with score 2 will prefill the 2nd answer option, etc.

Average of all questions on a page

This snippet returns the average rating for all questions on a page  given by the current respondent. That means that you can add questions and sub-questions to the page without updating the CSL code.

First we create two variables: one to hold the number of questions and sub-questions found on the page and another to hold the sum of all the ratings given by the respondent to those questions. Then we loop through all the questions of the survey and if the questions are on the page we want, we add them to our variables. After the loop, we divide the sum of the ratings by the number of questions to get the average rating.

{{set "questionCount" 0}}
{{set "ratingSum" 0}}

{{#each respondent.questions}}
  {{#if (eq question.pageNumber 1)}}
    {{set "questionCount" (add (get "questionCount") 1)}}
    {{set "ratingSum" (add (get "ratingSum") scaleValue)}}
  {{/if}}
{{/each}}

{{divide (get "ratingSum") (get "questionCount")}}
Tip:
  • Make sure that all questions on that page have the same scale.
  • Answers are only registered after a respondent clicks Next. This means that the CSL code has to be at least on the next page or CSL won't have the answers from that page yet.
  • To save and see the average later in reports, you need to prefill a hidden slider question. Set the min and max of the slider to match the min and max of the scale of the questions on the source page.

Respondent summary

This snippet returns a list of all questions in your survey along with the answers given by the current respondent.

This snippet can be used on the thank-you page, thank-you email, or in email notifications.

{{#each respondent.questions}}
{{questionNumber}} {{question.text}}: {{value}}
{{/each}}

Calculating Body Mass Index (BMI)

You can use CSL to calculate various scores like BMI. Don't forget to save the value in hidden questions or else you will not be able to see it in the reporting.

To calculate BMI, take a person's weight in kilograms and divide it by their length in meters squared. Here is the formula:

BMI formula.

To make things more manageable, use temporary variables. Remember that temporary variables only work on the same page.

First , create a page in your survey where you ask for your respondent's height and weight. On the next page, you show them their result. Thew result page would look something like this:

Weight : {{respondent.questions.weight}} kg
Height:   {{respondent.questions.height}} m
{{set "BMI" (round (divide respondent.questions.weight (pow respondent.questions.height 2)) 2)}}

Your BMI is:
{{get "BMI"}}

{{#if (lt (get "BMI") 18,5)}}
You are underweight.
{{else if (lt (get "BMI") 25)}}
You have a healthy weight.
{{else if (lt (get "BMI") 30)}}
You are overweight
{{else}}
You are obese.
{{/ if}}

If you want to use pounds and inches instead of the metric system, use this CSL calculation:

{{set "BMI" (round multiple((divide respondent.questions.weight (pow respondent.questions.height 2)) 703) 2)}}
Tip: CSL calculations always start with the operator. When trying to put together a calculation with a lot of nestled parts, try calculating the inner parts first and then keep adding to it. So in one tab, you have the question editor where you work and in another tab, you have the survey open to that page. That way, you can keep making small changes and then refreshing the survey tab to see the result. You can also work with more temporary variables to hold parts of the calculation and then use the variables in your final calculation.

Postfill a question to use in display logic and branching

Sometimes, you want to use a calculation or other CSL in page display logic or branching. Since this cannot be done directly, you can use your calculation to postfill a question. Then you can use the question in your display logic or branching. There is an added advantage that the question will also be available in the reporting for filters. Say you want to show a page if a respondent selected more than 1 answer in a checkboxes question, maybe to show them a rank-order question.

To get start, created a hidden radio button question 'More than 1 option chosen?' with two answer choices ('yes' and 'no') at the bottom of the page with the checkboxes question. Make sure your checkboxes question has a data label since you will need it to refer to the CSL. Then, in the radio buttons question, go to the Prefill tab and select Fixed text or CSL and enter the following CSL:

{{#if (gt (count respondent.questions.myLabel.answerChoices) 1)}}yes{{else}}no{{/if}}

What this says is, if the count of answer choices selected in the question with data label 'myLabel', is greater than (gt) one, select 'yes' otherwise select 'no'.

You can also replace the 'yes' and 'no' in the code with '1' and '2', which stands for the first and second answer choice. You will need to that if your survey is multilingual.

Select Yes for the Postfill value after page is submitted? dropdown.

Now you can use the radio buttons question in your display logic, branching, and reporting.

Write all answers given for a multi select question

The 'each' takes us through each answer given by the current respondent and we add to a temporary variable. At the end, we use the 'get' to write out the contents of the variable.

{{#each respondent.questions.myDataLabel.answerChoices}}
{{set "answers" (get "answers") " | " caption.unformatted)}}
{{/each}}
{{set "answers" (substring (get 'answers') 3)}}
{{get "answers"}}

The following is a more complex example that only returns answer choices that the respondent answered that contain the word 'happy'.

{{#each respondent.questions.myDataLabel.answerChoices}}
{{#if (contains caption "happy")}}
{{set "answers" (get "answers") " | " caption.unformatted)}}
{{/if}}
{{/each}}
{{set "answers" (substring (get 'answers') 3)}}
{{get "answers"}}

Custom validation upload question type

The snippet below allows you to add a CSL based validation to your upload question type for when you for example want to limit the respondent to upload a file of a certain file type. In this case, we don't want the respondent to upload a PDF file.

The CSL snippet below will check the path of uploaded file from right to left. We will check four characters in this path. If this contains the characters pdf, then we will show a custom message. You can also use this to postfill a hidden question with true or false. You can then use branching to redirect the respondent to an additional page that tells the respondent they need to upload the correct file type. Using custom CSS, you can hide the next button on that page so the respondent has no other option than go back to upload the correct file type.

The example script checks the last 4 characters from the uploaded file path from your upload question type with label labelUploadQuestion:

{{#if (eq (right respondent.questions.labelUploadQuestion 4) ".pdf")}} BAD FILE TYPE, Please click Back and upload the correct file type{{else}} all good! {{/if}}

The example below can be used to postfill a hidden question on the same page as the upload question:

{{#if (eq (right respondent.questions.labelUploadQuestion 4) ".pdf")}}false{{else}}true{{/if}}

The CSS snippet below will hide the next button on your inserted page. In this example, this would be page 2:

.page-2 .nextButton {
visibility: hidden !important;
}