FlexiSurveyUser guide

Logic & Formula Reference

The complete reference for conditional logic rules, the formula language behind computed variables, and M&E indicator formulas.

For: Survey designers, M&E officers, data managersPlan: All plans (indicator formulas need a MEAL-enabled plan)

FlexiSurvey has three places where you write logic instead of clicking it together: conditional logic rules that show, hide, and require questions while a survey is being taken; the formula language behind computed variables and panel variable transforms; and indicator formulas that reduce a whole response set to an M&E indicator value. This page is the complete reference for all three. Everything here describes the engine as it runs today; the same evaluation semantics apply on the web taker, the respondent portal, the embedded widget, the mobile apps, and server-side validation.

Conditional logic rules

A rule has four parts: a trigger, a condition group, one or more actions, and a priority. When a rule's trigger applies and its conditions match the answers given so far, its actions run. Disabled rules are ignored entirely.

Triggers

Trigger When the rule is considered
On answer Every time an answer changes (the default; always evaluated)
On page load Every evaluation pass (same behaviour as "on answer")
On survey start Only while no answers have been given yet
On survey end Only once every question has an answer

Condition operators

Each condition compares one question's answer against a fixed value. Twelve operators are available:

Operator Matches when Notes
equals the answer equals the value compared as text, so 5 equals "5"
not equals the answer differs from the value
contains the answer contains the value as a substring on multi-choice answers, matches if any selected option contains it
not contains the answer does not contain the value
greater than the answer is numerically greater
less than the answer is numerically smaller
greater than or equal numeric ≥
less than or equal numeric ≤
is empty the question is unanswered, blank, or has no selections
is not empty the question has any answer
in the answer equals one of a list of values
not in the answer equals none of the listed values

An unknown or malformed operator never matches (the engine fails closed rather than guessing).

Combining conditions

Conditions sit inside a group with one of four combinators, and groups nest to any depth:

A group with no conditions always matches, which lets you author an unconditional rule.

Actions

Action Effect
Show question Makes the target question visible
Hide question Hides the target question
Skip to question Jumps the taker forward to the target question
End survey Finishes the survey at that point
Set required Makes the target question required for this respondent

Precedence and interactions

Rules evaluate in priority order, highest first. Once a higher-priority rule has decided a question's visibility, a lower-priority show or hide on the same question is ignored. Two behaviours are worth knowing because they prevent whole classes of field problems:

The formula language

Computed variables (named values derived from a response's answers) and panel variable transforms share one expression language. It is evaluated by a purpose-built parser with no access to anything outside the expression: no code execution, no network, no other responses.

Referencing answers

Inside a formula, a question's answer is available as the token q_<questionId> (the builder inserts these tokens for you, so you rarely type them by hand). Computed variables can also reference other variables by their name. When a question lives inside a repeat group, its token holds the list of that question's answers across all instances, which is exactly what the aggregate functions expect: sum(q_income) totals income across all household members.

Operators

In order of binding strength, tightest first:

Operators Meaning
^ exponentiation
* / % multiply, divide, modulo
+ - add, subtract (unary minus is supported)
< > <= >= comparison
== != equality
&& logical AND
|| logical OR

Parentheses group as usual. Strings are written in quotes; function names are case-insensitive.

Functions

Math

Function Returns
abs(x) absolute value
ceil(x) / floor(x) round up / down
round(x) or round(x, decimals) rounded value
min(a, b, …) / max(a, b, …) smallest / largest argument
sqrt(x) square root
pow(base, exp) power
log(x) / log10(x) / exp(x) natural log, base-10 log, e^x

Aggregates (accept lists, e.g. a repeated question's token, or several arguments)

Function Returns
sum(…) total
avg(…) mean of the numeric entries; blank entries are skipped; empty input returns nothing rather than 0
count(…) how many entries are non-empty
median(…) median of the numeric entries
stdev(…) population standard deviation; needs at least two numeric entries

Text

Function Returns
len(s) length
upper(s) / lower(s) / trim(s) case changes, whitespace strip
concat(a, b, …) joined text
substr(s, start) or substr(s, start, length) a slice

Conditional

Function Returns
if(condition, whenTrue, whenFalse) one of two values
coalesce(a, b, …) the first non-empty argument
isBlank(v) whether the value is missing or whitespace
isNumber(v) whether the value is a real number (a blank is not a number)

Date

Function Returns
now() / today() current timestamp / current date
year(d) / month(d) / day(d) calendar parts
daysBetween(d1, d2) whole days between two dates

Missing-data semantics

The language treats blanks honestly, because a blank silently becoming a zero is how field data goes wrong:

Indicator formulas (MEAL)

Indicator formulas are a separate, aggregate language: where a computed variable produces one value per response, an indicator formula reduces the whole response set to one number, with the survey answers exposed through the variables you map in the indicator binding (written with a $ prefix, e.g. $water_access).

Aggregate functions iterate the response set; their arguments are per-response expressions:

Function Returns
count() / count(predicate) responses, or responses matching the predicate
pct(predicate) percentage of responses matching
pctOf(predicate, predicate) percentage with an explicit denominator
sum(expr) / avg(expr) / median(expr) / stddev(expr) numeric aggregates over a per-response expression
distinct(expr) count of distinct values
min(v) / max(v) smallest / largest value of a bound variable

Inside a predicate or value expression you can use abs, round, floor, ceil, sqrt, pow, min, max, if, coalesce, between, and in, plus the same operators as the formula language.

Three guarantees the indicator engine makes:

Indicator formulas are validated when you save a binding, including a check that every $variable you reference is actually mapped, and the binding editor's live test runs your formula against real responses before anything is saved.

Where to go next