Skip to content

User Object

Every assignment in ABetterChoice is tied to a user object. The user object carries two pieces of information:

  • a unit ID that decides which experiment group the call lands in;
  • optional attributes that decide which audience targeting rules the call satisfies.

This page describes how to build a user object correctly across SDKs and the HTTP API.

The Go and HTTP code paths below are generally available today. The iOS, Android, JavaScript, and C++ snippets are a shape preview — those SDKs are tagged Coming soon under Settings → SDK&Key.

Unit ID

A unit ID is a stable string that identifies the unit of randomization for your experiments. The platform always assigns the same unit ID to the same group for the life of an experiment.

Use this kind of IDWhen
User IDThe experiment compares logged-in users; you have a stable internal ID.
Session IDPre-login flows where a user ID does not exist yet.
Device / install IDMobile apps where you want to keep assignments tied to the install.

Build the unit ID once, server-side or at first launch, and reuse it. Avoid concatenating PII into the unit ID (user@example.com:1) — it leaks into exposure logs.

go
ctx := abc.NewUserContext("user_id_1")        // Go
objective-c
expOptions.unitId = @"user_id_1";              // iOS
javascript
abc.init({ projectId, unitId: "user_id_1", ... }) // JavaScript

Switching unit ID

Client SDKs support switchUnitId for cases where the same app session sees a different unit later (the user logs in, switches account, etc.). The SDK re-fetches assignments for the new unit:

java
mAbcExpSDK.switchUnitId("otherUnitID", listener);    // Android
javascript
abc.switchUnitId("other_unit_id");                    // JavaScript

Server SDKs do not need a switch call — every request can construct its own user context, so the unit ID changes naturally per request.

Attributes (profiles)

Attributes let an experiment or feature flag target a subset of units (for example country == "US" AND app_version >= 1.3.0). Build the attribute set on the call site, the SDK or HTTP request forwards it:

go
ctx := abc.NewUserContextWithAttrs("user_id_1", map[string]string{
    "country":     "US",
    "app_version": "1.3.0",
})
javascript
abc.init({
  projectId, unitId, secretKey,
  attributes: { country: "US", app_version: "1.3.0" },
});

For HTTP API calls, attributes go into the profiles map on the request body:

json
{
  "project_id": "6666",
  "unit_id": "user_id_1",
  "profiles": { "country": { "user_attrs": ["US"] }, "age": { "user_attrs": ["18"] } }
}

Built-in attributes today include country, app_version, media_source, os_platform, ram_total, first_install_version, time_since_join, and user_type. Custom attributes are created in the console under Audiences → Attributes — see Audience.

Attribute types

TypeConsole labelComparison
StringStringEquality, IN, NOT IN, regex.
NumberNumberEquality, range, IN, NOT IN.
VersionVersionSemantic version compare (>=, <, =).

The HTTP API accepts attribute values as strings only — convert numbers and booleans to strings before sending ("18", "true").

Sticky assignment

The platform hashes (unit_id, layer_or_experiment_seed) to decide the group. The hash is deterministic, so:

  • the same unit ID always lands in the same group as long as the experiment's traffic allocation and salt are unchanged;
  • adding or removing other experiments in the same project does not move the unit ID's group in this experiment;
  • changing the layer's % of global traffic can move units across the included / excluded boundary — covered in Layers.