Skip to Content
Config SystemDefining Segments

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 a segments: block and per-segment evaluationMode. They are now context dimensions (sourceType: 'segment'), always evaluated in real time. Replace any segments: / defineSegment in your config with contextDimensions: / defineContextDimension as 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

OperatorDescription
equalsExact match
not_equalsDoes not match
greater_thanGreater than a value
greater_than_equalsGreater than or equal
less_thanLess than a value
less_than_equalsLess than or equal
containsString contains value
not_containsString does not contain value
starts_withString starts with value
ends_withString ends with value
inValue is in a list
not_inValue is not in a list
is_empty / is_not_emptyValue is / isn’t empty
is_null / is_not_nullValue is / isn’t null
is_true / is_falseBoolean 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

Last updated on