Eventvisor

Concepts

Conditions

Conditions have various use cases in Eventvisor projects, ranging from filtering events from being tracked to conditionally routing them to different destinations.

Datafile representation

Eventvisor can store conditions as JSON strings in compact datafiles. This is only a representation change. The string contains the same JSON condition object described on this page. The grammar is part of datafile schema version 1, and SDKs parse it before evaluation. Malformed strings fail closed, so they never accidentally match. Parsed conditions are cached for the active datafile.

Set stringify: false in project configuration or on an individual Target when human-readable datafiles are more important than size.

Condition syntax is designed for consistent evaluation across SDK languages. Regular expressions use a portable subset. Supported flags are g, i, m, and s, with each flag used at most once. Lookaround, named groups, noncapturing groups, backreferences, inline mode groups, atomic groups, and possessive quantifiers are rejected during linting. SDKs also reject them defensively if an unvalidated datafile is loaded.

The before and after operators require a real ISO 8601 date and time with a timezone, such as 2026-01-01T00:00:00Z. Invalid calendar dates are rejected. Semantic version operators require a complete SemVer value such as 1.2.3. Prefixes, partial versions, wildcards, and invalid leading zeroes are rejected. Invalid operands fail closed and do not match.

A condition must use exactly one source selector. Source and transform paths reject empty segments and unsafe object keys such as __proto__, prototype, and constructor.

Anatomy of a condition

A condition is based on the following properties:

  • A source for original value (see sources page), which can be expressed via several different properties like:
    • source
    • attribute
    • payload
    • lookup
  • An operator for the comparison between the source and the value
  • A value to compare against

Operators

These operators are supported as conditions:

OperatorType of attributeDescription
existsSource is defined
notExistsSource is undefined
equalsanyEquals to
notEqualsanyNot equals to
greaterThaninteger, doubleGreater than
greaterThanOrEqualsinteger, doubleGreater than or equal to
lessThaninteger, doubleLess than
lessThanOrEqualsinteger, doubleLess than or equal to
containsstringContains string
notContainsstringDoes not contain string
startsWithstringStarts with string
endsWithstringEnds with string
inprimitiveIn array of primitive values
notInprimitiveNot in array of primitives
beforestring, dateDate comparison
afterstring, dateDate comparison
matchesstringMatches regex pattern
notMatchesstringDoes not match regex pattern
semverEqualsstringSemver equals to
semverNotEqualsstringSemver not equals to
semverGreaterThanstringSemver greater than
semverGreaterThanOrEqualsstringSemver greater than or equals
semverLessThanstringSemver less than
semverLessThanOrEqualsstringSemver less than or equals
includesarrayArray includes primitive
notIncludesarrayArray excludes primitive

Several examples below showing how attribute source can be used with each of them. You can of course use other sources as well.

equals

# ...
conditions:
- attribute: country
operator: equals
value: us

notEquals

# ...
conditions:
- attribute: country
operator: notEquals
value: us

greaterThan

# ...
conditions:
- attribute: age
operator: greaterThan
value: 21

greaterThanOrEquals

# ...
conditions:
- attribute: age
operator: greaterThanOrEquals
value: 18

lessThan

# ...
conditions:
- attribute: age
operator: lessThan
value: 65

lessThanOrEquals

# ...
conditions:
- attribute: age
operator: lessThanOrEquals
value: 64

contains

# ...
conditions:
- attribute: name
operator: contains
value: John

notContains

# ...
conditions:
- attribute: name
operator: notContains
value: Smith

startsWith

# ...
conditions:
- attribute: name
operator: startsWith
value: John

endsWith

# ...
conditions:
- attribute: name
operator: endsWith
value: Smith

in

# ...
conditions:
- attribute: country
operator: in
value:
- be
- nl
- lu

notIn

# ...
conditions:
- attribute: country
operator: notIn
value:
- fr
- gb
- de

before

# ...
conditions:
- attribute: date
operator: before
value: 2023-12-25T00:00:00Z

after

# ...
conditions:
- attribute: date
operator: after
value: 2023-12-25T00:00:00Z

semverEquals

# ...
conditions:
- attribute: version
operator: semverEquals
value: 1.0.0

semverNotEquals

# ...
conditions:
- attribute: version
operator: semverNotEquals
value: 1.0.0

semverGreaterThan

# ...
conditions:
- attribute: version
operator: semverGreaterThan
value: 1.0.0

semverGreaterThanOrEquals

# ...
conditions:
- attribute: version
operator: semverGreaterThanOrEquals
value: 1.0.0

semverLessThan

# ...
conditions:
- attribute: version
operator: semverLessThan
value: 1.0.0

semverLessThanOrEquals

# ...
conditions:
- attribute: version
operator: semverLessThanOrEquals
value: 1.0.0

exists

# ...
conditions:
- attribute: country
operator: exists

notExists

# ...
conditions:
- attribute: country
operator: notExists

includes

# ...
conditions:
- attribute: permissions
operator: includes
value: write

notIncludes

# ...
conditions:
- attribute: permissions
operator: notIncludes
value: write

matches

# ...
conditions:
- attribute: email
operator: matches
value: ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$
# optional regex flags
regexFlags: i # case-insensitive

Ordinary capture groups and character classes are supported. Keep patterns within the portable subset described at the start of this page so the same datafile behaves consistently in every SDK.

notMatches

# ...
conditions:
- attribute: email
operator: notMatches
value: ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$
# optional regex flags
regexFlags: i # case-insensitive

Advanced conditions

Conditions can also be combined using and, or, and not operators.

and

When using and, all direct child conditions must match.

# ...
conditions:
and:
- attribute: country
operator: equals
value: us
- attribute: device
operator: equals
value: iPhone

By default if and is not specified directly under conditions, it is implied.

or

When using or, at least one direct child condition must match.

# ...
conditions:
or:
- attribute: country
operator: equals
value: us
- attribute: country
operator: equals
value: ca

not

not negates the implicit AND of its direct children. A list with two conditions means “not all of these match”.

# ...
conditions:
not:
- attribute: country
operator: equals
value: us

To express “none of these match”, place an or inside not:

conditions:
not:
- or:
- attribute: country
operator: equals
value: us
- attribute: country
operator: equals
value: ca

and, or, and not must contain at least one child.

Complex

and and or can be combined to create complex conditions:

# ...
conditions:
- and:
- attribute: device
operator: equals
value: iPhone
- or:
- attribute: country
operator: equals
value: us
- attribute: country
operator: equals
value: ca

You can also nest and, or, and not operators:

# ...
conditions:
- not:
- or:
- attribute: country
operator: equals
value: us
- attribute: country
operator: equals
value: ca
Previous
Lookups