Skip to main content
Supported on: iOS SDK 1.0.61+ · Android SDK 1.0.33+ · Flutter SDK 1.0.3+
The experiments module assigns users to variants using a deterministic hash. No server call is needed — assignment is instant, works offline, and the same user always gets the same variant.

Get Variant

final variant = await AppDNA.experiments.getVariant("paywall-test");

switch (variant) {
  case "control":
    showStandardPaywall();
    break;
  case "variant_a":
    showNewPaywall();
    break;
  default:
    // null, archived, or user not in audience — always handle this branch.
    showStandardPaywall();
}
getVariant is asynchronous and returns the variant string or null if the experiment is not found, not running, or the user is not in the target audience.
Always handle the null / default case. Experiments can be archived or stopped at any time from the Console.

Check Membership

When you only need a boolean for a specific variant, isInVariant is a convenient shortcut:
if (await AppDNA.experiments.isInVariant("paywall-test", "variant_a")) {
  showNewPaywall();
} else {
  showStandardPaywall();
}

Module Access

final experiments = AppDNA.experiments;

Module Methods

MethodSignatureDescription
getVariantFuture<String?> getVariant(String experimentId)Get the assigned variant
isInVariantFuture<bool> isInVariant(String experimentId, String variantId)Check if the user is in a specific variant
getExposuresFuture<List<Map<String, dynamic>>> getExposures()Read recorded experiment exposures for the current user

Exposure Tracking

The SDK automatically tracks an experiment_exposure event the first time getVariant() is called for a given experiment in a session. Exposure events power the metrics that the experimentation engine uses to compute results — you do not need to fire them yourself. To inspect what the SDK has already recorded for the current user, call getExposures():
final exposures = await AppDNA.experiments.getExposures();

for (final exposure in exposures) {
  final experimentId = exposure["experimentId"] as String?;
  final variant = exposure["variant"] as String?;
  print("Exposed to $experimentId -> $variant");
}
This is useful for debugging, surfacing the active variant in a developer panel, or attaching the current bucket to your own analytics events.

Reacting to Assignment Changes

The SDK does not push assignment-change callbacks. Variant assignments are stable for a given user/experiment pair and only change when the experiment definition is updated on the server. If you need to refresh UI when the experiment configuration could have changed, re-read getVariant at natural moments in your app:
  • On app launch and on return from background
  • When you present the screen that depends on the variant
  • After a known config-refreshing action (e.g. login, environment switch)
class HomeScreenController {
  String? _paywallVariant;

  Future<void> refresh() async {
    _paywallVariant = await AppDNA.experiments.getVariant("paywall_redesign");
    // re-render UI that depends on _paywallVariant
  }
}
Assignment changes are rare. They occur only when the experiment definition changes on the server, not on every session start.

Experiment Lifecycle

StatusgetVariant() returns
Draftnull — not visible to SDKs
RunningAssigned variant string
CompletedWinning variant for all users
Archivednull — removed from config

Full Example

import 'package:appdna_sdk/appdna_sdk.dart';

class PaywallExperiment {
  Future<void> showPaywall() async {
    final variant =
        await AppDNA.experiments.getVariant("paywall_redesign");

    final paywallId =
        variant == "new_design" ? "paywall_v2" : "paywall_v1";

    await AppDNA.paywall.present(
      paywallId,
      context: PaywallContext(
        placement: "settings",
        customData: {
          "experiment": "paywall_redesign",
          "variant": variant ?? "control",
        },
      ),
    );
  }
}
Experiments are created in the Console under Experiments. The SDK uses MurmurHash3 for deterministic assignment — the same user always gets the same variant across sessions, platforms, and offline.