Attributes (Feature Flags)

Feature Flag projects manage user attributes from the Audiences > Attributes tab. An attribute is a fact about a visitor, such as their browser or their subscription plan, that you can target on in an audience rule. Attributes come in two kinds: 11 built-in keys every Feature Flag project starts with, and custom attributes you add yourself.

  1. The built-in attributes table. These 11 keys are always there and cannot be edited or deleted.
  2. Click Add Attribute to register a custom attribute of your own (steps below).

Built-in attribute keys

Every Feature Flag project starts with 11 attribute keys already registered, each with the right name and type set up. You do not have to define them yourself before using them in an audience condition.

No SDK fills in a value for these keys automatically today. Your own code works out each value: reading a browser's user agent, looking up a country, reading a screen size. It then passes the value in the evaluation context, under the exact key name shown below. A key you never pass is treated as missing, and a condition on it evaluates to false.

Available in both client-side and server-side SDKs

  • browser: Browser name (Chrome, Firefox, Safari, etc.).
  • browserVersion: Browser version string.
  • os: Operating system (Windows, macOS, Linux, iOS, Android).
  • osVersion: OS version string.
  • deviceType: Device category: desktop, mobile, or tablet.
  • country: Two-letter country code.

The examples on this page share this setup:

TypeScript
import { AvsbServer } from '@avsbhq/node'const client = new AvsbServer({ sdkKey: process.env.AVSB_SDK_KEY! })// Stand-ins for your own request and data layer. detectBrowser stands for// whatever user-agent parsing you use; it is not part of A vs B.declare const req: { headers: Record<string, string | undefined> }declare const detectBrowser: (userAgent: string | undefined) => {  browser: string  os: string  deviceType: string}declare const user: {  id: string  subscription: { plan: string }  company: { employeeCount: number }}declare const cart: { total: number }declare const session: { viewedSkus: string[] }declare const orders: { createdAt: Date }[]declare const customer: { lifetimeSpend: number }
TypeScript21 lines

Attributes ride on the evaluation context alongside kind and key. Work out each value yourself and pass it under its key name:

TypeScript
const detected = detectBrowser(req.headers['user-agent'])client.getFlag('flag_key', false, {  kind: 'user',  key: user.id,  browser: detected.browser,  os: detected.os,  deviceType: detected.deviceType,})
TypeScript9 lines

Client-only attributes

  • language: Browser language code (en-US, fr, de).
  • timezone: IANA timezone (America/New_York).
  • screenWidth: Screen width in pixels.
  • screenHeight: Screen height in pixels.
  • darkMode: Whether the user prefers dark color scheme.

A server request carries no screen size and no color-scheme preference. These five keys only make sense from a browser-based SDK such as @avsbhq/react.

Client-only attributes in server-side SDKs

A condition on a client-only attribute never matches in server-side SDK evaluations, because a server-side context never carries a value for it. The condition fails closed: it does not match, so the visitor falls through to your next rule or the default variation.

Custom attributes

Custom attributes represent properties from your application: user identity, subscription plan, feature entitlements, team membership, or any other data you want to target by.

Registering a custom attribute

  1. Go to Audiences > Attributes.
  2. Click "Add Attribute".
  3. Fill in the key (alphanumeric with underscores, e.g. userId), display name, and type (String, Number, Boolean, or JSON). A description is optional.
  4. For String attributes, you can add suggested values (e.g. free, pro, enterprise). These appear as dropdown options in the audience builder.

If a value is refused, the reason appears under the field it belongs to, for example "Key must be alphanumeric with underscores". It clears as soon as you edit that field.

Creating attributes inline from the audience builder

You can also create a new attribute without leaving the audience you are building. When you add a Custom Attribute condition, the attribute picker has a + New attribute affordance at the bottom of the dropdown. Click it to open a small form and register the attribute. It is then auto-selected for the condition you were editing, with no round-trip to the Attributes tab.

Passing custom attributes in your code

TypeScript
client.getFlag('checkout_redesign', false, {  kind: 'user',  key: user.id,  userId: user.id,  plan: user.subscription.plan,  companySize: user.company.employeeCount,})
TypeScript7 lines

Attribute types and operators

Each attribute type supports different comparison operators in audience conditions:

  • String: equals, does not equal, contains, does not contain, starts with, ends with, regex, in list, not in list, exists, does not exist.
  • Number: equals, does not equal, greater than, less than, greater than or equal, less than or equal, exists, does not exist.
  • Boolean: equals, does not equal, exists, does not exist.
  • JSON: contains, does not contain, exists, does not exist.

Commerce attributes (server-side evaluation)

The Commerce Conditions (cart value, products viewed, purchase history) also work in feature-flag rules evaluated by server SDKs. A server has no browser storage or visitor profile lookup to draw on. So your code supplies the commerce data in the evaluation context, using these reserved attribute keys:

AttributeTypeUsed by
cartValuenumber: the cart total as a decimal in the project currency (e.g. 49.99)Cart value conditions
viewedSkusstring[]: product SKUs the user has viewedProducts viewed conditions matching by SKU
viewedCategoriesstring[]: product categories the user has viewedProducts viewed conditions matching by category
purchaseHistoryobject: { hasPurchased: boolean; lastPurchaseAt?: number; lifetimeSpend?: number; orderCount?: number }Purchase history conditions

purchaseHistory field details: lastPurchaseAt is epoch milliseconds; lifetimeSpend is a decimal amount in the project currency. Amounts you configured in the dashboard condition are compared against these decimals using the project currency's minor-unit rules: you never pass cents.

TypeScript
client.getFlag('free_shipping_banner', false, {  kind: 'user',  key: user.id,  cartValue: cart.total,                       // 124.50  viewedSkus: session.viewedSkus,              // ['SKU-001', 'SKU-204']  purchaseHistory: {    hasPurchased: orders.length > 0,    lastPurchaseAt: orders[0]?.createdAt.getTime(),    lifetimeSpend: customer.lifetimeSpend,    orderCount: orders.length,  },})
TypeScript12 lines

A missing or wrongly-typed attribute makes the condition evaluate to false: the same fail-closed behavior as every other attribute condition. Two behaviors deliberately differ from the browser snippet, and are worth knowing:

Server difference 1: absent purchaseHistory fails every operator

In the browser, "no profile found" is an authoritative answer (the visitor never purchased), so Has not purchased matches. On the server, an absent purchaseHistory attribute just means your code didn't provide it, so all purchase-history operators evaluate to false, including Has not purchased. To target never-purchasers server-side, pass it explicitly: purchaseHistory: { hasPurchased: false }.

Server difference 2: dataset lists never match

Products-viewed conditions that reference a LIST dataset evaluate to false in server SDKs: the server SDK does not resolve dataset membership during flag evaluation. For server-evaluated rules, use conditions with a literal SKU/category list instead.

One more difference in kind rather than behavior: the snippet distinguishes the session window from the 30-day window automatically. A server SDK cannot: it checks whatever lists you pass as viewedSkus / viewedCategories, so the window is effectively whatever recency your code applies when building those arrays.

Deleting attributes

Custom attributes can be deleted from Audiences > Attributes. Built-in attributes cannot be deleted.

If a custom attribute is used in any audience condition, deletion is blocked. Remove the attribute from all audience conditions first, then delete it.

Was this helpful?