Defining Context Dimensions (Segments)
Segments are context dimensions — named signals in your project’s targeting
context. A segment dimension carries a rule that is evaluated fresh on every
request into segment.<key> (true/false); a model dimension designates a
customer-owned model whose record hydrates the user.* targeting namespace.
Define them in your config to manage them as code — a foir push creates,
updates, and prunes the context dimensions its config declares.
Migrating from
segments:— Segments used to be a separate resource with asegments:block and per-segmentevaluationMode. They are now context dimensions (sourceType: 'segment'), always evaluated in real time. Replace anysegments:/defineSegmentin your config withcontextDimensions:/defineContextDimensionas shown below.
Context Dimension Interface
interface ApplyConfigContextDimensionInput {
key: string; // Unique identifier (e.g., 'vip-customers')
name: string; // Display name
description?: string; // What this dimension represents
sourceType: string; // 'segment' (rule-based) | 'model' (customer-context source)
evaluationRules?: Record<string, unknown>; // Rule for sourceType 'segment'
sourceModelKey?: string; // Customer-owned singleton model (sourceType 'model')
defaultRecordKey?: string; // Optional default record (sourceType 'model')
}Basic Example
import { defineConfig, defineContextDimension } from '@foir/cli/configs';
export default defineConfig({
key: 'my-app',
name: 'My App',
contextDimensions: [
defineContextDimension({
key: 'vip-customers',
name: 'VIP Customers',
description: 'Customers with total spend over $500',
sourceType: 'segment',
evaluationRules: {
type: 'condition',
left: { type: 'field', path: 'totalSpend' },
operator: 'greater_than',
right: { type: 'literal', value: 500 },
},
}),
],
});A customer matches this segment when the rule evaluates true against the
request’s targeting context. Reference it in variant / content targeting rules
as segment.vip-customers.
Rules Structure
evaluationRules uses the same condition-expression format as variant targeting.
Each rule specifies a left operand, an operator, and a right operand.
Simple Condition
evaluationRules: {
type: 'condition',
left: { type: 'field', path: 'orderCount' },
operator: 'greater_than',
right: { type: 'literal', value: 5 },
}Combining Conditions
Use a group node with logicalOperator set to 'AND' or 'OR' to combine
multiple conditions:
evaluationRules: {
type: 'group',
logicalOperator: 'AND',
conditions: [
{
type: 'condition',
left: { type: 'field', path: 'totalSpend' },
operator: 'greater_than',
right: { type: 'literal', value: 500 },
},
{
type: 'condition',
left: { type: 'field', path: 'orderCount' },
operator: 'greater_than',
right: { type: 'literal', value: 5 },
},
],
}Segment Chains
A segment rule can reference another segment (segment.gold == true). Segments
are evaluated in topological order, so a dependent segment sees the
already-evaluated result of the segments it references — no extra work required.
Available Operators
| Operator | Description |
|---|---|
equals | Exact match |
not_equals | Does not match |
greater_than | Greater than a value |
greater_than_equals | Greater than or equal |
less_than | Less than a value |
less_than_equals | Less than or equal |
contains | String contains value |
not_contains | String does not contain value |
starts_with | String starts with value |
ends_with | String ends with value |
in | Value is in a list |
not_in | Value is not in a list |
is_empty / is_not_empty | Value is / isn’t empty |
is_null / is_not_null | Value is / isn’t null |
is_true / is_false | Boolean value is true / false |
Ownership & Reconcile
Context dimensions declared in your config are owned by that config (a
config_id is stamped on create). A plain foir push:
- creates dimensions your config declares that don’t exist yet,
- updates ones it already owns, and
- deletes config-owned dimensions you removed from the config.
Dimensions you author in the admin UI (no config) are never touched by a push, and vice-versa — so config-as-code and the UI coexist safely.
Customer-Context Source (sourceType: 'model')
Designate a customer-owned singleton model as the source of the user.*
targeting namespace:
defineContextDimension({
key: 'customerContext',
name: 'Customer Context',
sourceType: 'model',
sourceModelKey: 'customer_profile',
})Examples
Mobile Users
defineContextDimension({
key: 'mobile-users',
name: 'Mobile Users',
sourceType: 'segment',
evaluationRules: {
type: 'condition',
left: { type: 'field', path: 'device' },
operator: 'equals',
right: { type: 'literal', value: 'mobile' },
},
})High-Spend Repeat Buyers
defineContextDimension({
key: 'high-spend-repeat',
name: 'High-Spend Repeat Buyers',
sourceType: 'segment',
evaluationRules: {
type: 'group',
logicalOperator: 'AND',
conditions: [
{
type: 'condition',
left: { type: 'field', path: 'totalSpend' },
operator: 'greater_than',
right: { type: 'literal', value: 1000 },
},
{
type: 'condition',
left: { type: 'field', path: 'orderCount' },
operator: 'greater_than_equals',
right: { type: 'literal', value: 10 },
},
],
},
})Next Steps
- Segments Concepts — how segments/context dimensions evaluate
- Configuration Reference — full config API reference
- Manage dimensions imperatively with
foir context-dimensions(see the CLI commands)