User Targeting
Serve a different value to a specific audience, beta users, internal staff, enterprise customers, anyone in a given country, with rules that match against your context attributes.
Targeting rules
A rule is an ordered list of conditions, all of which must match, plus the value to serve. Rules are evaluated top to bottom and the first decisive one wins. A rule with an empty condition list matches everyone, which is how you express "the rest of the traffic".
Each condition has three parts:
- Attribute: any key from the evaluation context.
- Operator: one of the operators below.
- Value: a literal or, for
in/not_in, a list.
Operators
These are the exact identifiers the API accepts. They are short, not
spelled out, eq rather than equals.
| Operator | Matches when | Value type |
|---|---|---|
eq | Attribute equals the value | literal |
neq | Attribute does not equal the value | literal |
contains | Attribute contains the value as a substring | string |
not_contains | Attribute does not contain the substring | string |
starts_with | Attribute begins with the value | string |
ends_with | Attribute ends with the value | string |
gt | Attribute is numerically greater than the value | number |
gte | Greater than or equal | number |
lt | Less than | number |
lte | Less than or equal | number |
in | Attribute appears in the list | array |
not_in | Attribute does not appear in the list | array |
regex | Attribute matches the pattern (unanchored) | string |
segment_match | User belongs to any of the named segments | segment key or list |
Matching semantics
A few behaviors are worth knowing before you write rules against them:
- Comparisons are string-based. The context value is
converted to a string before matching, so
eqagainsttruematches the booleantrueand the string"true"alike. Onlygt,gte,lt, andltecoerce to numbers. - A missing attribute never matches. If the attribute is
absent,
undefined, ornull, the condition is false, including for negative operators.neqagainst an attribute you didn't send is false, not true. -
inandnot_inrequire an array. Given a non-array value both return false, so a malformednot_insilently fails closed rather than matching everyone. -
regexis unanchored and hardened. It behaves liketest(), so anchor with^and$when you mean a full match. Patterns over 256 characters, inputs over 4096 characters, invalid patterns, and nested-quantifier shapes such as(a+)+are rejected as non-matches to prevent ReDoS.
Common patterns
// Beta users
{ "attribute": "plan", "operator": "eq", "value": "beta" }
// Internal staff
{ "attribute": "email", "operator": "ends_with", "value": "@yourcompany.com" }
// Geographic
{ "attribute": "country", "operator": "in", "value": ["US", "CA"] }
// Accounts above a seat threshold
{ "attribute": "seats", "operator": "gte", "value": 50 }
// Pro tier AND opted in — two conditions on one rule are ANDed
{ "attribute": "plan", "operator": "eq", "value": "pro" }
{ "attribute": "betaOptIn", "operator": "eq", "value": true }
// Anyone in a reusable segment
{ "attribute": "segmentKey", "operator": "segment_match", "value": "enterprise-accounts" } Conditions within a rule are ANDed. For OR, use separate rules that serve the same value, or a segment, whose rules are ORed.
Custom attributes
Anything you put in the context object is fair game. Common additions:
orgId: for B2B targeting at the workspace level.signupAt: to gate features for users created after a date.experimentArm: when chaining experiments.locale: to ship language-specific UI gradually.
Values must be strings, numbers, or booleans. Nested objects and arrays are
not part of the attribute model, flatten them before you pass them
(org.tier becomes orgTier).
Rule ordering
Rules evaluate top-to-bottom. Put your highest-specificity rules first (internal staff) and your broadest last (a catch-all ramp). Reordering in the dashboard propagates within seconds.
Ordering interacts with rollouts: a user who matches a rule but falls outside its percentage falls through to the next rule rather than ending evaluation. See Rules and rollouts together.