Targeting
Targeting lets you control which users see a feature based on their attributes. Instead of turning a flag on or off for everyone, you define rules that match specific users or segments.
How targeting works
- You set targeting rules on a flag-environment (e.g.
checkout-redesignindevelopment) - The SDK calls the evaluate endpoint with the user’s context
- If the flag is disabled, rules are skipped entirely and the flag’s
offValueis returned - If the flag is enabled, rules are checked in priority order — the first match wins
- If no rule matches and targeting rules exist, the flag’s
offValueis returned (user is not targeted) - If no targeting rules are defined, the flag’s
defaultValueis returned
const result = await flagify.evaluate('checkout-redesign', {
id: 'user-456',
plan: 'pro',
country: 'US',
});
// result: { key: "checkout-redesign", value: true, reason: "targeting_rule" }
Targeting rules
Each flag-environment can have multiple targeting rules, ordered by priority. A rule can match via:
- Segment — reference a reusable segment (e.g. “Pro Users”)
- Inline conditions — conditions attached directly to the rule
- Both — segment AND conditions must all match
- Neither — catch-all rule that always matches
Each rule can optionally include:
valueOverride— the value to return when this rule matchesrolloutPercentage— only apply to X% of matching users
Setting rules via the API
curl -X PUT /v1/flag-environments/{feid}/targeting-rules \
-d '{
"rules": [
{
"segmentId": "seg_pro_users",
"valueOverride": "pro-checkout",
"enabled": true
},
{
"conditions": [
{ "attribute": "country", "operator": "equals", "value": "US" }
],
"valueOverride": "us-checkout",
"enabled": true
}
]
}'
Rules use a replace-all pattern — each PUT replaces all existing rules.
Supported operators
| Operator | Description | Example |
|---|---|---|
equals | Exact match | plan equals "pro" |
not_equals | Inverse match | plan not_equals "free" |
contains | Substring match | email contains "@acme.com" |
not_contains | Inverse substring | email not_contains "test" |
starts_with | Prefix match | email starts_with "admin" |
ends_with | Suffix match | email ends_with ".edu" |
in | Value in list | country in ["US", "CA", "UK"] |
not_in | Value not in list | country not_in ["CN", "RU"] |
gt | Greater than (numeric) | age gt 18 |
lt | Less than (numeric) | age lt 65 |
Percentage rollouts
Roll out a feature to a percentage of users:
{
"rolloutPercentage": 25,
"valueOverride": "new-experience",
"enabled": true
}
Flagify uses consistent hashing (murmur3(flagKey + ":" + userId) % 100) so the same user always gets the same result for a given flag. Gradually increase the percentage to ramp up exposure.
User segments
Segments are reusable groups of users, scoped to a project. Each segment has rules with a match type:
- ALL — all rules must match (AND logic)
- ANY — at least one rule must match (OR logic)
curl -X POST /v1/projects/{pid}/segments \
-d '{
"name": "Pro Users",
"matchType": "ALL",
"rules": [
{ "attribute": "plan", "operator": "equals", "value": "pro" }
]
}'
Reference segments in targeting rules by their ID. Updating a segment automatically affects all flags that reference it.
Evaluate endpoint
The SDK’s evaluate() method calls the API with user context:
import { Flagify } from '@flagify/node';
const flagify = new Flagify({
projectKey: 'my-project',
publicKey: 'pk_dev_abc123_xxx',
});
const result = await flagify.evaluate('checkout-flow', {
id: 'user-123',
plan: 'pro',
country: 'US',
});
if (result.reason === 'targeting_rule') {
// User matched a targeting rule
renderCheckout(result.value);
} else {
// Default value
renderCheckout(result.value);
}
Response
{
"key": "checkout-flow",
"value": "pro-checkout",
"reason": "targeting_rule"
}
| Reason | Description |
|---|---|
targeting_rule | A targeting rule with conditions/segment matched |
rollout | A rollout percentage rule matched |
no_match | Targeting rules exist but none matched — returned flag’s offValue |
default | No targeting rules defined — returned flag’s defaultValue |
disabled | Flag is disabled in this environment — returned flag’s offValue |