Skip to content

Rule Operators

Rules control the flow of a questionnaire. After a user answers a question, the rules engine evaluates conditions to determine which question to show next.

There are four rule component types available in the Strapi rules dynamic zone:

A single condition with if/then/else branching.

Field Type Description
if condition The comparison to evaluate
then string Question ID to navigate to if the condition is true
else string Question ID to navigate to if the condition is false

Example: If the user’s country is Germany, go to the German-specific question; otherwise, go to the generic question.

{
"if": {
"op": "equals",
"variable": { "type": "static", "value": "DE" }
},
"then": "germanSpecificQuestion",
"else": "genericQuestion"
}

Grouped conditions combined with AND/OR logic.

Field Type Description
condition enum AND or OR
comparisons array Array of individual comparisons
then string Question ID if the group evaluates to true
else string Question ID if the group evaluates to false

Example: If the user is over 18 AND lives in Germany, go to the standard flow.

{
"condition": "AND",
"comparisons": [
{ "op": "greaterThan", "key": "age", "variable": { "type": "static", "value": 18 } },
{ "op": "equals", "key": "country", "variable": { "type": "static", "value": "DE" } }
],
"then": "standardFlow",
"else": "blockerScreen"
}

Date-based comparison using dateDiff.

Field Type Description
op string Always dateDiff
variable.type enum Unit: year, month, or day
variable.value number The threshold value to compare against
variable.dir enum Direction: gt (greater than) or lt (less than)
variable.key string Question ID containing the date answer
variable.comparisonKey string Optional: another question ID to compare against (instead of today’s date)
then string Question ID if true
else string Question ID if false

Example: If the user’s date of birth is more than 65 years ago, route to a senior-specific flow.

{
"op": "dateDiff",
"variable": {
"type": "year",
"value": 65,
"dir": "gt",
"key": "dateOfBirth"
},
"then": "seniorFlow",
"else": "standardFlow"
}

Example with comparisonKey: If the gap between two dates is less than 30 days.

{
"op": "dateDiff",
"variable": {
"type": "day",
"value": 30,
"dir": "lt",
"key": "travelStartDate",
"comparisonKey": "travelEndDate"
},
"then": "shortTripFlow",
"else": "longTripFlow"
}

Unconditional routing — always navigates to the target question.

Field Type Description
then string Question ID to always navigate to

Example: After the intro screen, always go to the first question.

{
"then": "dateOfBirth"
}

These operators are used inside rule-comparison and rule-group-comparison conditions.

Operator Description Example
equals Deep equality check (=== semantics for primitives, deep compare for objects/arrays) Answer is exactly "DE"
notEquals Deep inequality check Answer is not "DE"
same Loose equality (== semantics) Answer loosely matches 42
notSame Loose inequality (!= semantics) Answer does not loosely match 42
greaterThan Answer is greater than the value Answer > 18
lessThan Answer is less than the value Answer < 65
Operator Description Example
isIn Answer is contained in the provided array Answer is one of ["DE", "AT", "CH"]
isNotIn Answer is not in the provided array Answer is not in ["US", "UK"]
contains Answer (string or array) contains the value Answer contains "health"
notContains Answer does not contain the value Answer does not contain "excluded"
Operator Description Example
isDefined Answer is not null and not undefined User has answered the question
isNotDefined Answer is null or undefined User has not answered the question
Operator Description
equalsOrContainsCountryCode Answer equals or contains the specified country code
notEqualOrContainsCountryCode Answer neither equals nor contains the specified country code
doCountryCodesMatch The country codes in the answer match the specified codes
doCountryCodesNotMatch The country codes in the answer do not match
doAllCountryCodesMatch All country codes in the answer match (for multi-country questions)
doAllCountryCodesNotMatch Not all country codes match
Operator Description
doesAddressMatch Address answer matches the comparison address
doesAddressNotMatch Address answer does not match
Operator Description
always Always evaluates to true. Use for unconditional routing.

Each comparison operator uses a variable to define what the answer is compared against.

Compare the answer against a fixed, hardcoded value.

{
"op": "equals",
"variable": {
"type": "static",
"value": "DE"
}
}
Field Type Description
type string "static"
value any The fixed value to compare against (string, number, boolean, array, or object)

Compare the answer against another question’s answer.

{
"op": "equals",
"variable": {
"type": "dynamic",
"key": "partnerCountry"
}
}
Field Type Description
type string "dynamic"
key string The question ID whose answer to use as the comparison value

Use case: “If the user’s country of residence matches their country of origin, skip the visa question.”


For cases where CMS operators are insufficient, rules can include custom JavaScript functions defined in app code. These are not configurable from Strapi.

Signature:

(answer: any, answers: Record<string, any>, questionId: string) => boolean
Parameter Description
answer The current question’s answer
answers All answers collected so far (keyed by question ID)
questionId The current question’s ID

Custom functions are defined in the questionnaire’s TypeScript file and referenced by the rules engine at runtime.


Rules are evaluated in the order they appear in Strapi. The first matching rule determines the next question. If no rule matches, the questionnaire follows the default question order (as defined in the questionList).