Decide methods for the Flutter SDK
Overview of the decide methods which can be used to return a flag decision for a user in Optimizely Feature Experimentation.
Minimum SDK version – v1.0.1+
Note
Decide is a method of the UserContext object. See OptimizelyUserContext for details.
See the OptimizelyDecision documentation for details of the returned decision object.
Parameters
The following table describes parameters for the decide method:
| Parameter | Type | Description |
|---|---|---|
key | String | The key of the feature flag. |
options (optional) | Set <OptimizelyDecideOption> | Set of OptimizelyDecideOption enums. |
Returns
The decide method returns an OptimizelyDecision object. See OptimizelyDecision.
If the method encounters a critical error (SDK not ready, invalid flag key, and so on), it returns a decision with a null variationKey field and populates the reasons field with error messages (regardless of the OptimizelyDecideOption.INCLUDE_REASONS option).
Example decide
decideMap<String, dynamic> attributes = {};
attributes["logged_in"] = true;
var user = await flutterSDK.createUserContext(userId: "user123", attributes: attributes);
var decideResponse = await user!.decide("product_sort");
// variation. if null, decision fail with a critical error
var variationKey = decideResponse.decision!.variationKey;
// flag enabled state:
var enabled = decideResponse.decision!.enabled;
// all variable values
var variables = decideResponse.decision!.variables;
// String variable value
var vs = variables["sort_method"] as String;
// Boolean variable value
var vb = variables["k_boolean"] as bool;
// flag key for which decision was made
var flagKey = decideResponse.decision!.flagKey;
// user for which the decision was made
var userContext = decideResponse.decision!.userContext;
// reasons for the decision
var reasons = decideResponse.decision!.reasons;
Side effect
Invokes the decide notification listener if this listener is enabled.
Minimum SDK version – 1.0.1
Description
Use the decide all method to retrieve decisions for all active flags before rendering content. This is particularly useful when you need to serve the correct cached version of your page or component based on the user's variation. For example when using an edge worker or cloud function.
Key features
- Pre-rendering decision – Lets you know all variation assignments ahead of time.
- Cache control – Lets you serve the correct cached content based on the user's pre-determined variations.
- Delay experiment tracking – Use
DISABLE_DECISION_EVENTto prevent the SDK from recording a decision before the user sees the feature. This ensures that participation is only tracked when the experience is delivered. - CMAB support – For CMAB experiments (SDK v3.4.0+), decisions are automatically cached to reduce latency. The cache is invalidated when CMAB attributes change or TTL expires. Use CMAB-specific decide options (
ignoreCmabCache,invalidateUserCmabCache,resetCmabCache) to override default caching behavior. See CMAB cache control.
Parameters
The following table describes parameters for the decide all method:
| Parameter | Type | Description |
|---|---|---|
options (optional) | Set | Set of OptimizelyDecideOption enums. |
Returns
Returns a map of OptimizelyDecisions. See OptimizelyDecision.
If the method fails for all flags (for example, the SDK is not ready or the user context is invalid), it returns a decision response with success status false, and reason and decision as null objects. If the method detects an error for a specific flag, it returns error messages in the reasons field of the decision for that flag.
Example decideAll
decideAll// make decisions for all active (unarchived) flags in the project for a user
Set<OptimizelyDecideOption> options = const { OptimizelyDecideOption.enabledFlagsOnly };
var decisionsResponse = await user!.decideAll(options);
var decisionMap = decisionsResponse.decisions;
var decisionForFlag1 = decisionMap["flag_1"];
Side effect
Invokes the DECISION notification listener for each decision, if this listener is enabled.
Minimum SDK version – v1.0.1+
Parameters
The following table describes parameters for the decide for keys method:
| Parameter | Type | Description |
|---|---|---|
keys | Array | Array of string flag keys. |
options (optional) | Set | Array of OptimizelyDecideOption enums. |
Returns
Returns a map of OptimizelyDecisions. For information, see OptimizelyDecision.
If the method fails for all flags (for example, the SDK is not ready or the user context is invalid), it returns a decision response with success status false, reason and decision as null objects. If the method detects an error for a specific flag, it returns error messages in the reasons field of the decision for that flag.
Example decideForKeys
decideForKeysvar keys = ["flag-1", "flag-2"];
var decisionsResponse = await user!.decideForKeys(keys);
var decisionMap = decisionsResponse.decisions;
var decision1 = decisionMap["flag_1"];
var decision2 = decisionMap["flag_2"];
Side effect
Invokes the decision notification listener for each decision, if this listener is enabled.
Minimum SDK version – v3.4.0+
Example decideAsync
decideAsyncMap<String, dynamic> attributes = {};
attributes["logged_in"] = true;
var user = await flutterSDK.createUserContext(userId: "user123", attributes: attributes);
var decideResponse = await user!.decideAsync("product_sort");
// variation. if null, decision fail with a critical error
var variationKey = decideResponse.decision!.variationKey;
// flag enabled state:
var enabled = decideResponse.decision!.enabled;
// reasons for the decision
var reasons = decideResponse.decision!.reasons;
Example decideAllAsync
decideAllAsync// make decisions for all active (unarchived) flags in the project for a user
Set<OptimizelyDecideOption> options = const { OptimizelyDecideOption.enabledFlagsOnly };
var decisionsResponse = await user!.decideAllAsync(options);
var decisionMap = decisionsResponse.decisions;
var decisionForFlag1 = decisionMap["flag_1"];
Example decideForKeysAsync
decideForKeysAsyncvar keys = ["flag-1", "flag-2"];
var decisionsResponse = await user!.decideForKeysAsync(keys);
var decisionMap = decisionsResponse.decisions;
var decision1 = decisionMap["flag_1"];
var decision2 = decisionMap["flag_2"];
OptimizelyDecideOption
OptimizelyDecideOptionThe following table lists the OptimizelyDecideOption enum with an explanation what happens if you set them. In addition to setting these options individually for a decide method, you can also set them as global defaults when you instantiate the Optimizely client. See Initialize Flutter SDK.
The following code sample shows how to implement the OptimizelyDecideOption:
// Set options in a decide call
var flutterSDK = OptimizelyFlutterSdk("YOUR_SDK_KEY"); // Replace with your SDK key
var response = await flutterSDK.initializeClient();
// Flag decision
var user = await flutterSDK.createUserContext(userId: "user123");
Set<OptimizelyDecideOption> options = {};
options.add(OptimizelyDecideOption.disableDecisionEvent);
var decisions = user!.decideAll(options);
CMAB cache control
Minimum SDK version – v3.4.0+
For Contextual Multi-Armed Bandit (CMAB) experiments, the Flutter SDK automatically caches variation assignments to reduce latency and API calls. The cache stores decisions based on user ID, experiment ID, and CMAB attribute values.
Automatic cache invalidation
The cache is automatically invalidated when
- The cached entry's TTL expires (default: 30 minutes).
- CMAB attribute values change for a user (detected through attribute hash comparison).
Manual cache control
Use CMAB-specific decide options to control cache behavior on a per-decision basis.
// Initialize Flutter SDK with default CMAB configuration
// Default cache size: 100, cache timeout: 1800 seconds (30 minutes)
var flutterSDK = OptimizelyFlutterSdk(
SDK_KEY,
cmabConfig: CmabConfig(), // Uses defaults
);
// Example 1: Use default cmab and caching logic
try {
var response = await flutterSDK.initializeClient();
var userContext = await flutterSDK.createUserContext(
userId: 'user_123',
attributes: {
'country': 'us'
},
);
var decision = await userContext.decideAsync(
"cmab_flag_key",
{OptimizelyDecideOption.ignoreUserProfileService},
);
}
// Example 2: Ignore CMAB cache (bypass cache, make fresh request).
try {
var decision = await userContext.decideAsync(
"cmab_flag_key",
{
OptimizelyDecideOption.ignoreCmabCache,
OptimizelyDecideOption.ignoreUserProfileService,
},
);
}
// Example 3: Invalidate cache when user context changes significantly
try {
var decision = await userContext.decideAsync(
"cmab_flag_key",
{
OptimizelyDecideOption.invalidateUserCmabCache,
OptimizelyDecideOption.ignoreUserProfileService,
},
);
}
// Example 4: Reset entire CMAB cache (use sparingly)
try {
var decision = await userContext.decideAsync(
"cmab_flag_key",
{
OptimizelyDecideOption.resetCmabCache,
OptimizelyDecideOption.ignoreUserProfileService,
},
);
}
CMAB decision reasons
When using includeReasons, CMAB-related information display in the decision's reasons field.
try {
var decision = await userContext.decideAsync(
"cmab_flag_key",
{
OptimizelyDecideOption.resetCmabCache,
OptimizelyDecideOption.ignoreUserProfileService,
OptimizelyDecideOption.includeReasons
},
);
print("[decide] reasons: ${decision.reasons}")
// Examples:
// User (user123) does not fall into cmab traffic allocation in experiment (exp_1).
// CMAB is not supported in sync mode.
// Failed to fetch CMAB data for experiment (exp_2).
}
Configure cache settings
// Create CMAB service with custom cache and prediction endpoint
var customCmabConfig = CmabConfig(
cacheSize: 50, // Set cache size (default: 100)
cacheTimeoutInSecs: 120, // Set TTL in seconds (default: 1800 = 30 minutes)
predictionEndpoint: "https://prediction.cmab.com/predict/{ruleId}" // Set your custom prediction endpoint template
)
// Initialize client with custom cmab config
var flutterSDK = OptimizelyFlutterSdk(
SDK_KEY,
cmabConfig: customCmabConfig,
);
Configure CMAB cache settings (size, TTL) and prediction endpoint at client initialization time. See Initialize Flutter SDK for details.
Source files
The language and platform source files containing the implementation for Flutter (Android) are at Optimizely.java and Flutter (Swift) are at OptimizelyClient.swift .
Updated 5 days ago
