Conditions
Conditions are the conditional logic primitive that powers segments and message overrides. They describe how runtime context, feature flags, and experiments determine whether a piece of authored content applies.
Condition kinds#
There are three kinds of conditions:
- Attribute conditions check a value from runtime context against an expected value with an operator.
- Feature conditions check whether a feature flag is enabled via an application-provided resolver.
- Experiment conditions check whether an experiment variation matches via an application-provided resolver.
Attribute conditions are native to Messagevisor. Feature and experiment conditions activate only when your application registers a resolveFlag or resolveVariation function on the SDK instance, typically through a module that integrates with a feature management tool like Featurevisor.
Attribute condition#
conditions: - attribute: plan operator: equals value: proattributeis the key of an authored attribute, or a dot-notation path into a nested object attribute (account.country).operatoris one of the operators listed under Operators reference.valueis the expected value. Its type depends on the attribute and operator; some operators (exists,notExists) take no value.
Feature condition#
conditions: - feature: new-checkout operator: isEnabledfeatureis the feature flag key.operatorisisEnabledorisDisabled.
If no resolveFlag is registered on the SDK instance, the condition evaluates to false.
Experiment condition#
conditions: - experiment: checkout-copy operator: hasVariation value: boldexperimentis the experiment key.operatorishasVariation.valueis the variation name that should match.
If no resolveVariation is registered on the SDK instance, the condition evaluates to false.
Condition shapes#
conditions can be authored in several equivalent shapes depending on how much structure you need.
Single condition#
A single condition object:
conditions: attribute: plan operator: equals value: proArray of conditions#
An array of conditions is treated as an and by default. All children must match.
conditions: - attribute: age operator: greaterThanOrEquals value: 18 - attribute: plan operator: equals value: proLogical groups#
Use and, or, and not for explicit grouping.
AND#
conditions: and: - attribute: plan operator: equals value: pro - attribute: platform operator: in value: - web - iosOR#
conditions: or: - attribute: plan operator: equals value: enterprise - and: - attribute: plan operator: equals value: pro - attribute: signupDate operator: before value: "2026-01-01T00:00:00Z"NOT#
not matches when its child group does not fully match (i.e. it negates an and):
conditions: not: - attribute: country operator: equals value: usYou can nest and, or, and not to any depth.
Wildcard#
Use the literal string "*" to always match. This is useful for "everyone" segments or unconditional overrides:
description: Everyoneconditions: "*"Operators reference#
All supported operators at a glance:
| Operator | Type of attribute | Description |
|---|---|---|
equals | any | Exact match |
notEquals | any | Does not match |
exists | Attribute is present and not null | |
notExists | Attribute is missing or null | |
greaterThan | integer, double | Strictly greater |
greaterThanOrEquals | integer, double | Greater than or equal |
lessThan | integer, double | Strictly less |
lessThanOrEquals | integer, double | Less than or equal |
contains | string | Value contains the substring |
notContains | string | Value does not contain the substring |
startsWith | string | Value starts with the string |
endsWith | string | Value ends with the string |
before | string, date | Date is before the given one |
after | string, date | Date is after the given one |
includes | array | Array attribute contains the value |
notIncludes | array | Array attribute does not contain it |
in | string | Attribute value is in the array |
notIn | string | Attribute value is not in the array |
isEnabled | Feature flag is enabled | |
isDisabled | Feature flag is not enabled | |
hasVariation | Experiment variation matches |
Examples for each operator below.
equals#
conditions: - attribute: country operator: equals value: NLnotEquals#
conditions: - attribute: country operator: notEquals value: NLexists#
conditions: - attribute: country operator: existsnotExists#
conditions: - attribute: country operator: notExistsgreaterThan#
conditions: - attribute: age operator: greaterThan value: 21greaterThanOrEquals#
conditions: - attribute: age operator: greaterThanOrEquals value: 18lessThan#
conditions: - attribute: age operator: lessThan value: 65lessThanOrEquals#
conditions: - attribute: age operator: lessThanOrEquals value: 64contains#
conditions: - attribute: name operator: contains value: JohnnotContains#
conditions: - attribute: name operator: notContains value: SmithstartsWith#
conditions: - attribute: name operator: startsWith value: JohnendsWith#
conditions: - attribute: email operator: endsWith value: "@example.com"before#
Both sides are interpreted as dates. Use ISO 8601 strings for authored values.
conditions: - attribute: signupDate operator: before value: "2024-01-01T00:00:00Z"after#
conditions: - attribute: signupDate operator: after value: "2024-01-01T00:00:00Z"includes#
includes applies when the attribute itself is an array:
conditions: - attribute: permissions operator: includes value: writenotIncludes#
conditions: - attribute: permissions operator: notIncludes value: writein#
in applies when the value is an array and the attribute is a single value:
conditions: - attribute: country operator: in value: - be - nl - lunotIn#
conditions: - attribute: country operator: notIn value: - fr - gb - deisEnabled#
Requires a resolveFlag function registered on the SDK instance. Evaluates to false when no resolver is available.
conditions: - feature: new-checkout operator: isEnabledisDisabled#
Requires a resolveFlag function registered on the SDK instance. Evaluates to false when no resolver is available.
conditions: - feature: new-checkout operator: isDisabledhasVariation#
Requires a resolveVariation function registered on the SDK instance. Evaluates to false when no resolver is available.
conditions: - experiment: checkout-copy operator: hasVariation value: boldWhere conditions are used#
In segments#
A segment names a reusable conditional building block by wrapping conditions with a description and an optional archived/promotable flag:
description: Pro plan usersconditions: - attribute: plan operator: equals value: proInline on a message override#
A message override can use conditions directly when the logic is small and specific to that message:
overrides: - key: platform-web conditions: - attribute: platform operator: equals value: web translations: en: Sign in from browserOverrides can also reference segments via segments: instead of conditions:. Segments are themselves built from conditions, so the underlying authoring vocabulary is the same.
Attribute access#
The attribute field names an authored attribute. When the attribute is of type object, you can read a nested field with dot notation:
conditions: - attribute: account.country operator: equals value: NLEach dot-separated segment is a property lookup. If any intermediate property is missing, the value is treated as missing, which makes exists evaluate to false, notExists evaluate to true, and any other operator evaluate to false.
Examples#
A single condition that targets web users:
conditions: - attribute: platform operator: equals value: webThe same logic used inside a segment:
description: Target web usersconditions: - attribute: platform operator: equals value: webAnd inline on a message override:
description: Sign in button labeltranslations: en: Sign inoverrides: - key: platform-web conditions: - attribute: platform operator: equals value: web translations: en: Sign in from browserEdge cases and behavior notes#
An array of conditions is implicitly AND#
conditions as an array means all of them must match. Use or explicitly when any of them should be sufficient.
not negates an AND of its children#
{ not: [a, b] } matches when a and b do not both match. It is not a per-child negation. Use nested not if you need that.
Missing attribute paths short-circuit#
If an attribute path is missing on the runtime context, every comparison operator returns false. The only operators that treat "missing" as a valid signal are exists and notExists.
Feature and experiment conditions need application wiring#
Without resolveFlag or resolveVariation registered on the SDK instance, isEnabled, isDisabled, and hasVariation always evaluate to false. This is intentional, since Messagevisor does not assume which feature flag system you use.
Linting catches authoring mistakes#
When attributes are defined, linting validates that referenced attribute keys and value types match. This catches typos and type mismatches before runtime.
Target context can simplify conditions at build time#
When a target declares partially known context, the builder can determine whether a condition is always true, always false, or still variable. Impossible branches are removed from the built datafile. See Targets for the details.

