Run experiments
The justtrack SDK lets you run server-side experiments (A/B tests) in your app. Experiments are configured on the justtrack backend, which assigns each user to a variant. The SDK fetches these assignments and gives you typed access to config values so you can branch your app logic accordingly.
In this guide, you'll learn to:
- Fetch experiment assignments from the server
- Activate experiments to confirm user enrollment
- Read experiment values in your app
- Configure the fetch interval
Fetch experiment assignments
Call fetch to pull the latest experiment assignments from the justtrack backend.
The SDK caches assignments locally, so subsequent reads are fast and offline-safe.
For example, on app launch you'd fetch the latest assignments so your UI reflects the user's assigned variants:
- Android
- iOS
- Unity
- React Native
sdk.remoteConfig.fetch().await()
try await sdk.remoteConfig.fetch()
IRemoteConfig remoteConfig = JustTrackSDK.GetRemoteConfig();
remoteConfig.Fetch(
() => { Debug.Log("Fetch succeeded"); },
(error) => { Debug.LogError("Fetch failed: " + error); }
);
await JustTrackSdk.remoteConfig.fetch();
The SDK respects a minimum fetch interval to avoid excessive network requests. If you call fetch again before the interval has elapsed, the SDK returns the cached assignments without contacting the server. See Configure the fetch interval for details.
Activate experiments
Fetching assignments downloads them to the device, but doesn't tell the backend the user was actually exposed to the experiment.
Call activate to confirm enrollment — only activated experiments count toward your experiment results in the dashboard.
For example, after the user sees a new onboarding flow, activate that experiment so justtrack records the exposure:
- Android
- iOS
- Unity
- React Native
val assignments = sdk.remoteConfig.getAll()
val experimentIds = assignments?.map { it.experimentId } ?: emptyList()
sdk.remoteConfig.activate(experimentIds).await()
let assignments = sdk.remoteConfig.allAssignments
let experimentIds = assignments.map { $0.experimentId }
try await sdk.remoteConfig.activate(experimentIds: experimentIds)
IRemoteConfig remoteConfig = JustTrackSDK.GetRemoteConfig();
Assignment[] assignments = remoteConfig.GetAll();
string[] experimentIds = assignments.Select(a => a.ExperimentId).ToArray();
remoteConfig.Activate(experimentIds,
() => { Debug.Log("Activation succeeded"); },
(error) => { Debug.LogError("Activation failed: " + error); }
);
const assignments = JustTrackSdk.remoteConfig.getAll();
const experimentIds = assignments.map(a => a.experimentId);
await JustTrackSdk.remoteConfig.activate(experimentIds);
Fetch and activate in one step
If you want to fetch the latest assignments and immediately confirm enrollment for all of them, use fetchAndActivate. This is useful at app startup when you want to get everything ready in a single call:
- Android
- iOS
- Unity
- React Native
sdk.remoteConfig.fetchAndActivate().await()
try await sdk.remoteConfig.fetchAndActivate()
IRemoteConfig remoteConfig = JustTrackSDK.GetRemoteConfig();
remoteConfig.FetchAndActivate(
() => { Debug.Log("Fetch and activate succeeded"); },
(error) => { Debug.LogError("Fetch and activate failed: " + error); }
);
await JustTrackSdk.remoteConfig.fetchAndActivate();
Read experiment values
After fetching, you can read experiment values from the local cache. Values are available immediately and don't require a network call.
Get all assignments
To list every experiment the user is enrolled in, call getAll. Each assignment contains the config key, its value, the experiment ID, and whether it's still pending activation.
This is useful for building a debug screen or iterating over all active experiments:
- Android
- iOS
- Unity
- React Native
val assignments = sdk.remoteConfig.getAll()
assignments?.forEach { assignment ->
Log.d("Experiment", "${assignment.configKey} = ${assignment.configValue}")
}
let assignments = sdk.remoteConfig.allAssignments
for assignment in assignments {
print("\(assignment.configKey) = \(assignment.configValue)")
}
IRemoteConfig remoteConfig = JustTrackSDK.GetRemoteConfig();
Assignment[] assignments = remoteConfig.GetAll();
foreach (Assignment assignment in assignments)
{
Debug.Log($"{assignment.ConfigKey} = {assignment.ConfigValue}");
}
const assignments = JustTrackSdk.remoteConfig.getAll();
assignments.forEach(a => {
console.log(`${a.configKey} = ${a.configValue}`);
});
Each assignment has the following fields:
| Field | Description |
|---|---|
configKey | The key you use to look up this value (e.g. "onboarding_variant"). |
configValue | The raw string value assigned to this user. |
experimentId | The unique ID of the experiment this assignment belongs to. |
isPending | true if the assignment hasn't been activated yet. |
Get a value by config key
To check a specific experiment value, use one of the typed getter methods. For example, to decide which onboarding flow to show:
- Android
- iOS
- Unity
- React Native
val variant = sdk.remoteConfig.getString("onboarding_variant")
if (variant == "new_flow") {
showNewOnboarding()
} else {
showDefaultOnboarding()
}
let variant = sdk.remoteConfig.getString(configKey: "onboarding_variant")
if variant == "new_flow" {
showNewOnboarding()
} else {
showDefaultOnboarding()
}
IRemoteConfig remoteConfig = JustTrackSDK.GetRemoteConfig();
string variant = remoteConfig.GetString("onboarding_variant");
if (variant == "new_flow")
{
ShowNewOnboarding();
}
else
{
ShowDefaultOnboarding();
}
const variant = JustTrackSdk.remoteConfig.getString('onboarding_variant');
if (variant === 'new_flow') {
showNewOnboarding();
} else {
showDefaultOnboarding();
}
The following typed getters are available:
| Type | Android | iOS | Unity | React Native |
|---|---|---|---|---|
| String | getString() | getString() | GetString() | getString() |
| Boolean | getBoolean() | getBool() | GetBoolean() | getBoolean() |
| Integer | getInt() | getInt() | GetInt() | getNumber() |
| Double | getDouble() | getDouble() | GetDouble() | getNumber() |
| Long | getLong() | — | GetLong() | — |
All getters return null if no assignment exists for the given config key.
Configure the fetch interval
The SDK enforces a minimum interval between server fetches to avoid unnecessary network requests. If you call fetch before the interval has elapsed, the SDK returns cached assignments instead.
The default interval is 24 hours (86,400 seconds).
During development, you can lower this interval to iterate faster:
- Android
- iOS
- Unity
- React Native
sdk.remoteConfig.setConfig(JusttrackRemoteConfigSettings(60))
sdk.remoteConfig.setConfig(JusttrackRemoteConfigSettings(minFetchIntervalInSec: 60))
IRemoteConfig remoteConfig = JustTrackSDK.GetRemoteConfig();
remoteConfig.SetConfig(new JusttrackRemoteConfigSettings(60));
JustTrackSdk.remoteConfig.setConfig({ minFetchIntervalInSeconds: 60 });
Keep the default interval in production. Lowering it causes more network requests from every user, which increases load on your app and the justtrack backend.
Example: A/B test your onboarding flow
Here's a complete example that ties everything together. Suppose you've configured an experiment on the justtrack backend with a config key onboarding_variant. Users are assigned either "control" (the existing flow) or "new_flow" (a redesigned experience).
At app startup, fetch and activate the experiment, then branch your logic based on the assigned variant:
- Android
- iOS
- Unity
- React Native
// Fetch the latest experiment assignments and activate them
sdk.remoteConfig.fetchAndActivate().await()
// Read the assigned variant
val variant = sdk.remoteConfig.getString("onboarding_variant")
when (variant) {
"new_flow" -> showNewOnboarding()
else -> showDefaultOnboarding()
}
// Fetch the latest experiment assignments and activate them
try await sdk.remoteConfig.fetchAndActivate()
// Read the assigned variant
let variant = sdk.remoteConfig.getString(configKey: "onboarding_variant")
switch variant {
case "new_flow":
showNewOnboarding()
default:
showDefaultOnboarding()
}
IRemoteConfig remoteConfig = JustTrackSDK.GetRemoteConfig();
// Fetch the latest experiment assignments and activate them
remoteConfig.FetchAndActivate(
() =>
{
// Read the assigned variant
string variant = remoteConfig.GetString("onboarding_variant");
if (variant == "new_flow")
{
ShowNewOnboarding();
}
else
{
ShowDefaultOnboarding();
}
},
(error) =>
{
Debug.LogError("Failed to fetch experiments: " + error);
// Fall back to the default experience
ShowDefaultOnboarding();
}
);
// Fetch the latest experiment assignments and activate them
await JustTrackSdk.remoteConfig.fetchAndActivate();
// Read the assigned variant
const variant = JustTrackSdk.remoteConfig.getString('onboarding_variant');
if (variant === 'new_flow') {
showNewOnboarding();
} else {
showDefaultOnboarding();
}