Supported on: iOS SDK
1.0.61+Two ways to run an experiment
- Servable surface experiments — A/B test a whole paywall, onboarding flow, in-app message, or survey with no branching code. You design the variants in the Console and the SDK serves the right one automatically. Best for testing the content or design of a managed surface.
- Code-level experiments — read the assigned variant yourself with
getVariantorgetExperimentConfigand branch in your own code. Best for feature flags, custom UI, or logic that isn’t a managed surface.
Servable Surface Experiments
Supported on: iOS SDK
1.0.65+- Treatment cohort → renders the treatment’s configuration in place of the live entity.
- Control cohort (and users on older SDK versions) → renders the live entity unchanged.
1.0.82+). The treatment configuration is not added to the live entity, so a user who isn’t bucketed into the treatment — or who is on an SDK version that predates this feature — never sees it.
This works for every managed surface: paywalls, onboarding flows, in-app messages, and surveys. You only reach for the code-level API below when you’re experimenting on something that isn’t a managed surface.
Get Variant
experimentId is the experiment’s ID, not its name — copy it from the experiment’s page or the ID column of the experiments list in the Console; "paywall-test" above is a placeholder. Returns the variant ID set in the Console ("control", "variant_a", etc.) or nil if the experiment is not in the config the SDK holds, is not running (paused, completed or archived), does not target iOS, or the user is outside its targeting rules or traffic allocation (SDK 1.0.82+; see Who Is in an Experiment). The country rule reads the device region (Locale.current, then the preferred languages), the minimum-version rule CFBundleShortVersionString, and “new users only” the app’s install date.
Check a Specific Variant
true only if the user is currently bucketed into the named variant. Useful as a guard before rendering variant-specific UI.
Get a Per-Variant Config Value
When an experiment variant carries a config payload, read individual keys with:Any? (string, number, boolean, array, or dictionary depending on what the Console stored).
Module Access
Module Methods
The top-level
AppDNA object also exposes AppDNA.getExperimentVariant(experimentId:), AppDNA.isInVariant(experimentId:variantId:), and AppDNA.getExperimentConfig(experimentId:key:) as convenience methods that delegate to this module.
Exposure Tracking
The SDK tracks anexperiment_exposure event the first time it assigns a variant for a given experiment — on getVariant(), isInVariant(), getExperimentConfig() or a servable surface. Further calls do not create duplicate events while the app keeps running. The SDK keeps exposures in memory, so after an app restart or AppDNA.reset() the next assignment is tracked again; a new session alone does not.
To inspect which experiments the user has been exposed to since the app started:
Experiment Lifecycle
A status change reaches the device with its next config fetch; until then the SDK keeps the definition it has. See Experiment Lifecycle.
Full Example
Experiments are created and managed in the Console under Experiments. The SDK uses MurmurHash3 for deterministic assignment — the same user ID always gets the same variant across sessions, platforms, and even offline.

