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

  1. You set targeting rules on a flag-environment (e.g. checkout-redesign in development)
  2. The SDK calls the evaluate endpoint with the user’s context
  3. If the flag is disabled, rules are skipped entirely and the flag’s offValue is returned
  4. If the flag is enabled, rules are checked in priority order — the first match wins
  5. If no rule matches and targeting rules exist, the flag’s offValue is returned (user is not targeted)
  6. If no targeting rules are defined, the flag’s defaultValue is 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 matches
  • rolloutPercentage — 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

OperatorDescriptionExample
equalsExact matchplan equals "pro"
not_equalsInverse matchplan not_equals "free"
containsSubstring matchemail contains "@acme.com"
not_containsInverse substringemail not_contains "test"
starts_withPrefix matchemail starts_with "admin"
ends_withSuffix matchemail ends_with ".edu"
inValue in listcountry in ["US", "CA", "UK"]
not_inValue not in listcountry not_in ["CN", "RU"]
gtGreater than (numeric)age gt 18
ltLess 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"
}
ReasonDescription
targeting_ruleA targeting rule with conditions/segment matched
rolloutA rollout percentage rule matched
no_matchTargeting rules exist but none matched — returned flag’s offValue
defaultNo targeting rules defined — returned flag’s defaultValue
disabledFlag is disabled in this environment — returned flag’s offValue