FlowScript

Compatibility:IdSurvey 7IdSurvey 8

You can manage the logic of the questionnaire flow using a programming language named FlowScript.

FlowScript is part of IdCode. They share the same functionality and part of the syntax, but FlowScript highly improves the possibilities of application.

You can add FlowScript into any page of the questionnaire. The script will be carried out during the saving process of the page, when the respondent clicks on the “Continue” button.

FlowScript will perform any instruction available in IdCode, allowing conditions of any level of complexity. It is also possibile to use the else and while instructions.

FlowScript is composed by different elements, such as:

Commands

Commands are instructions that are carried out when FlowScript is executed, such as a “skip” to a specific page (goto), “out of target” (ot) or the assignment of a value to a contact field.

Conditions

A condition determines when a command has to be carried out. For example, if the condition is true, carry out this command.

Functions to use within conditions

IdSurvey offers many function that can be used both in FlowScript and IdCode. The functions that you can use within the conditions allow you to carry out controls on the questions of the questionnaire, on the contact fields or on the status of the quotas. For example, checking how many answer options where selected in a multiple choice question or checking if a specific quota is full, ecc.

Other special functions

These particular functions can be employed both within conditions and within commands. Special functions are generally only necessary for FlowScript that are highly complex.

In-dept sintax

Commands are instructions that will be carried out when FlowScript is executed. You can add one or more commands, with or without condition. Each command has to end with the “;” sign (semicolon).

The possible commands are:

  • Function GoTo (skip)
  • Function GoToRnd (random skip)
  • Function Ot (out of target)
  • Assign a value to a contact field 
  • Assign responses
  • SetVariable (assign contact fields and advanced responses).

GoTo

Jump to the specified page or question.

Example of a simple skip:

goto(P3);

skips to page P3.

Example of a skip with sequence:

goto(P3, P5, P10);

skips to page P3, then page P5, then page P10.

Note

  • A simple skip will ensure the integrity of the questionnaire: this means that when skipping to a next page, any response given to the questions that were skipped will be deleted. Instead, if the skip condition lands on a previous page, the data will not be deleted. In this case, the interview will proceed displaying the questions one by one with the responses already filled out. In both cases the interview will always be populated only with the responses to the questions that were actually asked, following the rules of the display conditions and skip that were set (if a question is filtered or skipped it means that it will not be displayed during the interview, so we expect the responses related to be blank). However, you can prevent the responses to be cleared out by using a skip with sequence without specifying the second page of the skip, adding the single quotes without any code in it, for example GoTo (Q15, '').

GoToRnd

It displays specific pages or questions randomly, always ending up with the page or question specified as last parameter.

For example:

gotornd(P5, P6, P10);

It will display pages P5 and P6 randomly, then it will end with page P10.

Ot

It sends the contact with the ongoing interview out of target.

Example out of target with condition:

if(Q1==1 && Q2==3) ot();

If on question Q1 answer with code 1 was selected and on question Q2 answer with code 3 was selected, you go out of target.

Assign value to contact field

It allows you to assign a value to any contact field.

Example:

{CarBrand} = Jaguar;

Assigns “Jaguar” to the contact field CarBrand.

Example with condition:

if (Q1==3 && Q2==1) {Subscription} = Netflix;

If on question Q1 answer with code 3 was selected and on question Q2 answer with code 1 was selected, it assigns “Netflix” to the contact field Subscription.

Assign response

It allows you to assign an answer to any question of the questionnaire.

Example response selection:

Q15 = 3;

It selects response with code 3 on question Q15.

Example multiple choice selection:

Q15 = '3,4,8';

It selects the responses with codes 3, 4 and 8 on question Q15.

Example populating an open-ended answer of a question:

[Q12] = 'I am very satisfied';

It populates the open-ended answer on question Q12.

Assign valueIt assigns the value to a contact field.{MarcaAuto} = Jaguar;

Assigns “Jaguar” to the contact field CarBrand.
Assign responseIt assign the response code to a question.Q15 = 3;

It selects response with code 3 on question Q15. 

Q15 = '3,4,8';

It selects the responses with codes 3, 4 and 8 on question Q15.

[Q12] = 'I am very satisfied';

It populates the open-ended answer on question Q12.
GoTo
(single)
It skips to a specific question or page.

In order to maintain the integrity of the interview, any following question that were previously answered will be cleared out.

goto(P1);

Skips to page P1.
GoTo
(multiple)
It skips to the pages or questions specified.goto(P1, P2);

Skips to page P1 and then to page P2.
GoToRndIt randomly skips to the pages (or questions) specified, always ending up with the page (or question) specified as last parameter.gotornd(P5, P6, P10);

It will display pages P5 and P6 randomly, then it will end with page P10.
Ot
(out of target)
It sends the contact with ongoing interview out of target.ot();
SetVariableIt allows you to set the value of a variable dynamically creating its name.setVariable('{son_name_'+{ison}+'}', Sam);

This example obtains the value of the variable “ison” (for example 3) and uses it to create the name of the variable “son_name_3” where it will wirte the value “Sam”.
RecStartIt starts the silent audio recording in CAPI interviews.recStart();

It starts the silent audio recording (compatible only with CAPI app interviews).
RecStopIt stops the silent audio recording in CAPI interviews.recStop();

It stops the silent audio recording (compatible only with CAPI app interviews).
sendMailSend an email.sendMail('email@sender.com', {Email}, 'Mail subject', 'Email text');

Send an email from email@sender.com to the address in the email field with the specified subject and text.

{email_result}=sendMail('email@sender.com', {Email}, 'Mail subject', 'Email text');

Send the email and saves the outcome in the field email_result of the contact.
sendSMSSend an sms.sendsms('Company', {mobile}, 'Congratulations! You completed the survey');

Send an SMS with sender as “Company” to the phone number found in the Mobile field of the contact.

{sms_result}=sendsms('Company', {mobile}, 'Congratulations! You completed the survey');

Send the SMS and saves the outcome in the field sms_result of the contact.

Conditions will allow you to specify the case in which one or more commands need to be executed. A condition, in its simple form, it is composed by the instruction if and by a comparison expression. It is then followed by the command to execute if the condition is true.

if(Q1==1) ot();

If on question Q1 response with code 1 was selected, you go off target.

You can use different comparison symbols and logic operators to combine multiple conditions.

if(Q1>5 && Q2!=1) goto(P5);

If on question Q1 a response with code greater than 5 and on question Q2 response with code 1 was not selected, you are sent to page P5.

You can use expression with multiple factors to carry out algebraic calculation or to combine text of open-ended answers, contact fields and strings.

if([Q1]+[Q2]<100) goto(P5);

If the sum of the number entered on the open-ended answer on questions Q1 and Q2 is lower than 100, you are sent to page P1.

Notes

  • Expressions with multiple factors can be used before and after the comparison sign.
  • Syntax of FlowScript conditions is the same as IdCode.

Let’s focus on all the topics necessary to create condition of any level of complexity:

  • Comparison symbols
  • Logic operators
  • if…then (to specify the commands to execute on a true condition)
  • if…then…else (to add commands to execute on a false condition)
  • while (it executes command until the condition is true)
  • List of functions to use on conditions

Comparison symbols

Comparison symbols to use within expressions of the conditions are:

  • == equal
  • != different
  • < lower
  • > greater
  • <= lower or equal
  • >= greater or equal

Logic operators

Conditions can be combined among them by using parenthesis and the usual logic operators:

  • && and
  • || or
  • ! negation

 

Example:

( Q1==1 || Q1==2) && ( Q2==1||Q2==2 )

If on question Q1 option with code 1 or with code 2 was selected, and on question Q2 option with code 1 or code 2 was selected.

( !Q1==1 ) || ( (Q2== 1 || Q2==2) && (Q3==1||Q3==2) )

If the condition “Q1 equal 1” is not true, or if on question Q2 option with code 1 or code 2 was selected, and on Q3 option with code 1 or code 2 was selected.

Note

  • The && operator prevails over the || operator. This means that when parenthesis are not used, AND conditions prevail over OR conditions. The negation operator ! prevails over all the other operators.

If…then

The if…then instruction allows you to set the condition in which one or more commands have to be carried out.

if(condition) command;

If the condition is true, execute the command.

Example:

if(Q8==3 && [Q2]<18) ot();

If on question Q8 option with code 3 was selected and on the open-ended answer to question Q2 a value lower than 18 was entered, you are sent out of target.

Example of condition with multiple commands:

if(Q2==3 && Q2!=1) { {Car_Owned}=none; ot(); }

If on question Q2 option with code 3 was selected and on question Q2 option 1 was not selected, the contact field “Car_Owned” will be populated with “none”, then you are sent out of target.

Note

  • After each condition you can add a group of commands enclosing the conditions into curly brackets. FlowScript will process a maximum of 1000 instructions for each group.

If…then…else

The instruction if…then…else extends the possibilities of the if…then instruction by allowing you to add commands to execute when the condition is false.

The syntax is the following:

if(condition) {command on true condition} else {command on false condition}

For example:

if(Q1==1) goto(P2); else goto(P5);

If on question Q1 answer option with code 1 was selected, you are sent to page P2, otherwise (if the condition is false) go to page P5.

While

While allows you to repeat one or more commands until the condition is true. With the while instruction you can create loops within the FlowScript. The use of this instruction is usually limited to particularly complex necessities. It is not to be confused with the section loops of the questionnaire.

The syntax is the following:

while(condition) command;

For example:

{j}=0; 
while ({j} <= {i})
	{
		{total}= {total}+[Q1][{j}];
		{j}++;
	}

It assigns value 0 to the j variable.

If the value of the variable j is lower than the value of the variable i, it populates the field “total” by adding the previous value of the field “total” to the amount entered on the open-ended question Q1 of j, therefore it increases field j of 1.

Note

  • In this example we called “variables” those that we usually identify as “contact fields”. Technically, there is no distinction between variables and contact fields. In IdSurvey the contact fields can be used as variables, in the same way as you can do in any programming language.
CountCodeIt allows you to count the number of options selected.if(CountCode (Q1) >= 3)

It checks if on question Q3 three or more options were selected.
ResponsesCodeOfIt gives back the codes of the answers selected in a question.if(Q2==responsesCodeOf(Q1)

It checks if the answer selected at question Q2 has the same code of that selected at question Q1.
CountResponsesWithCodeIt allows you to count the number of questions to which a specific response code was answered.if(CountResponsesWithCode(Q1,Q2,Q3,Q4,Q5,Q6,99) >= 3)

It checks if code 99 was answered to a minimum of three questions among Q1, Q2, Q3, Q4, Q5 and Q6.
CountResponsesWithTextIt allows you to count the number of questions to which a specific text or number was answered.if(CountResponsesWithText (Q1,Q2,Q3,Q4,Q5,Q6,'sea') >= 3)

It checks if the word “sea” was entered on at least 3 of the text answers on questions Q1, Q2, Q3, Q4, Q5 and Q6.
CheckQuotaIt allows you to verify if a certain quota is open or full.if(CheckQuota ('Parents') == 1)

It checks if the quota “Parents” is full.
CompareDateIt compare two dates.
It gives -1 if the first date precedes the second one, 0 is they are the same and 1 if the first date is subsequent to the second one.
if(compareDate({date_of_birth}, ‘2010-10-01') == -1)

It checks if the date in the “date_of_birth” field precedes the date specified.
ModuleIt gives back the string CATI, CAWI or CAPI according to the module with which the interview is currently distributed.if(module()==cawi)

It checks if the interview is currently distributed via CAWI.
ContainsTextIt allows you to verify the presence of the specific text within an open-ended answer.if(ContainsText ([Q1],'sea')==1)

It checks if the text answer to question Q1 contains the word “sea”.
StartWithTextIt compares the beginning of a string with a specified string.if(StartWithText({Mobile},'+39')==1)

It checks if the field Mobile starts with “+39”.
EndWithTextIt compares the end of a string with a specified string.if(EndWithText({Identification},'123')==1)

It checks if the field Identification ends with “123”.

The following functions were developed in order to manage special exception and they can be used both within condition and commands. The use of these function is usually limited to specific complex requirements.

GetVariableIt allows to obtain the value of a variable (on the contact or on a question) dynamically creating the name of the variable itself.getVariable('{date_of_birth_son_'+{ison}+'}')

It obtains the value of the “ison” variable (for example 3) and uses it to generate the name of the variable “date_of_birth_son_3” getting the value related.
JoinIt allows to force the combination of strings preventing that these are interpreted as numbers. For example 10+02+12 goes 24, while join(10,02,12) gives 100212.join(10,02,12)

It creates the string 100212.

join(text,02,[Q1])

It creates the string text02openResponseQ1.
RandomIt creates a random number between the minimum number and the maximum number indicated. You can specify a name to save the number generated in order to use it afterwards.random(1, 10)
It creates a random number between 1 and 10.

random(1, 10, 'my random number')

It creates a random number between 1 and 10 and saves it with the name specified. Using the same syntax (in the FlowScript of any other page of the questionnaire) the number saved and generated the first time will be called again. 
ReplaceIt replaces the specified text within a string.

(Available starting from IdSurvey 8.1)

Replace([Q1], 'car', 'bus')

It gives back the string of the text answer of question Q1 replacing the word “car” with “bus”.

Replace({phone}, '+39', '')

It gives back the field phone without the prefix +39.
GetItemByRankingIt gets back the label or the code of the item according to its position.

(Available starting from IdSurvey 8.1)

GetItemByRanking(Q1, 1, label)

It gives back the label of the element in first position in the drag&drop question (or – for the matrix – it gives back the text of the row where the answer with code 1 is selected).

GetItemByRanking(Q15, 3, code)

It gives back the code of the element placed in third position in the drag&drop question (or – for the matrix – it gives back the code of the row where the answer with code 3 is selected).

GetItemByRanking(Q1, 1, auto)

or
GetItemByRanking(Q1, 1)

It gives back the label of the element in first position in the drag&drop question. If the label is not available you get the code.
getResponseIt returns the answer selected (as string) and allows you to specify the data to be recovered and the formatting of the multiple answer separator.

(Available starting from IdSurvey 8.1)

getResponse(Q1)

or
getResponse(Q1, auto)

It gives back the open end answer (if available) or the label of the answer selected in question Q1. In case of multiple answers, you get all the options separated by the pipe character “ | ”.

getResponse(Q1, auto, ', ')

As the previous example but in case of multiple answers, you get all options separated by a comma and a space.

getResponse(Q1, opentext)

It gives back the text answer of question Q1.

getResponse(Q1, label)

It gives back the label of the answer selected in question Q1.

getResponse(Q1, code)

It gives back the code of the answer selected in question Q1. In case of multiple answers, you get all the options separated by the pipe character “ | ”.

getResponse(Q1, code, ', ')

It gives back the code of the answer selected in question Q1. In case of multiple answers, you get all the options separated by by a comma and a space.

getResponse(Q1, commentbox)

It gives back the text inserted in the comment box.

Shorthand if…then…else

In FlowScript you can use the instruction if…then…else even in the form known as “shorthand”. This forma is necessary to use the conditions within other commands or to enter the dynamic text in the body of the questionnaire. Technically, the if “shorthand” form allows you to add a condition within functions that only accept expressions. Despite the different syntax, the logic and functioning do not differ from the normal functioning of the if…then…else.

condition ? expression_condition_true : expression_condition_false

For example:

(Q1==1)?'private':'company'

If on question Q1 option with code 1 was selected, it gives back the string “private”, otherwise it gives “company”.

(Q1==1)?{social_security_number}:{vat_number}

If on question Q1 option with code 1 was selected, it gives back the value of the contact field named “social_security_number”, otherwise it gives “vat_number”.

([Q1]>1)?'how old are your sons':'how old is your son'

If on the open-ended question Q1 was entered a number greater than 1 (number of sons), the text of the question with the plural form will be displayed, otherwise the singular form will be displayed.

In the following example we will show how to create combined “shorthand” if else conditions.

( [Q1]>=4 ) ? 'positive' : ( [Q1]<=2 ) ? 'negative' : ( [Q1]==3 ) ? 'neutral' : ' '

If on the open-ended question Q1 a value greater or equal to 4 was entered, the system gives back the string “positive”, otherwise it checks if a value lower or equal to 2 was entered and in this case it gives back the string “negative”; otherwise it checks if value 3 was entered: in this case it will give back the string “neutral”, otherwise it will give back an empty string.

FlowScript gives priority to the programming speed and the simplicity of the expressions, at the expense of the language orthodoxy. This causes some peculiarities that may confuse an expert user of other programming languages.

String with or without single quotes, what are the differences?

The complete and correct syntax of the strings requires the use of single quotes. If the string only includes one word (that means without blanks), you can omit the single quotes.

Therefore, the syntax [D1]==Marco is equal to [D1]=='Marco'.

The condition [D1]=='very satisfied' can not be written without single quotes, since they are necessary in order to determine the beginning and the end of a string.

Comparisons asymmetry

The elements that are compared within conditions (the elements before and after the comparison operator) are NOT the same. The one that come after the comparison operato is always interpreted as a string, while the one preceding the operator, if a free string (without single quotes), is interpreted as a question code.

For example, the condition D1==1 “verify if on question with code D1 was given an answer with code 1”. If I reverse the order of the elements I will get the condition 1==D1 which means “verify if on question with code 1 was given an answer with code D1” which is completely different.

Therefore, please always keep in mind that comparisons are NOT, in general, invertible.