Decide methods for the Android SDK
Overview of the decide methods which you can use to return a flag decision for a user in Optimizely Feature Experimentation.
You can use the decide methods to return a flag decision for a user. The flag decision includes a flag-enabled or disabled status and the flag variation.
Decide
Returns a flag decision for a user.
Minimum SDK version – v3.9+
Description
The decide method handles the variation decision for an individual experiment. It returns a decision result for a flag key for a user in an OptimizelyDecision
object and contains the data required to deliver the flag rule.
This method ensures that Feature Experimentation properly buckets the user in experiment analytics, and you should use it if there is no need for pre-rendering decisions.
Note
Decide is a method of the
UserContext
object. See OptimizelyUserContext for details.
See the OptimizelyDecision for details of the returned decision object.
Key features
- Single experiment decision – Returns the variation for a specific experiment.
- Bucketing in results – Ensures Feature Experimentation records the user in the experiment results page for proper analysis.
- Complement to decide all method – If you use the decide all method to pre-fetch variations, you should also call the decide method for each experiment that the user interacts with. This dual approach guarantees that Feature Experimentation accurately tracks the user's participation and that the correct variation is served through caching.
Parameters
The following table describes the parameters for the decide method:
Parameter | Type | Description |
---|---|---|
flagKey | String | The key of the feature flag |
options (optional) | Array | Array of OptimizelyDecideOption enums. |
OptimizelyDecideOption
OptimizelyDecideOption
The following table lists the OptimizelyDecideOption
enums 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 the Android SDK.
OptimizelyDecideOption enum | If set |
---|---|
OptimizelyDecideOption.DISABLE_DECISION_EVENT | Prevents the visitor from firing an impression while still being served the variation, which disables displaying results of the decide method on the Optimizely Experiment Results page. This setting can be why the Decision Event Dispatched enum is false in the returned OptimizelyDecision object or the decision notification listener payload. |
OptimizelyDecideOption.ENABLED_FLAGS_ONLY | Returns decisions for enabled flags only. This option is valid only for methods that decide multiple flags, like the decide all method and is ignored if it is invalid. When this option is not set, the Android SDK returns all decisions regardless of whether the flag is enabled. |
OptimizelyDecideOption.IGNORE_USER_PROFILE_SERVICE | Bypasses the user profile service (both lookup and save) for the decision. When this option is not set, user profile service overrides audience targeting, traffic allocation, and experiment mutual exclusion groups. |
OptimizelyDecideOption.INCLUDE_REASONS | Returns log messages in the Reasons field of OptimizelyDecision object. Unlike info or debug messages, critical error messages are always returned, regardless of this setting. |
OptimizelyDecideOption.EXCLUDE_VARIABLES | Excludes flag variable values from the decision result. Use this option to minimize the returned decision by skipping large JSON variables. |
The following code sample shows how to implement the OptimizelyDecideOption
as a global default and locally in a decide method call.
// set global default decide options when initializing the client
var options: List<OptimizelyDecideOption>
options = Arrays.asList(OptimizelyDecideOption.DISABLE_DECISION_EVENT)
val optimizelyManager = OptimizelyManager.builder()
.withSDKKey("<YOUR_SDK_KEY>")
.withDefaultDecideOptions(options)
.build(context)
// set additional options in a decide call
val optimizelyClient = optimizelyManager.initialize(context, R.raw.datafile)
val user = optimizelyClient.createUserContext("user123")
options = Arrays.asList(OptimizelyDecideOption.DISABLE_DECISION_EVENT,
OptimizelyDecideOption.DISABLE_DECISION_EVENT)
val decisions = user!!.decideAll(options)
// set global default decide options when initializing the client
List<OptimizelyDecideOption> options;
options = Arrays.asList(OptimizelyDecideOption.DISABLE_DECISION_EVENT);
OptimizelyManager optimizelyManager = OptimizelyManager.builder()
.withSDKKey("<YOUR_SDK_KEY>")
.withDefaultDecideOptions(options)
.build(context);
// set additional options in a decide call
OptimizelyClient optimizelyClient = optimizelyManager.initialize(context, R.raw.datafile);
OptimizelyUserContext user = optimizelyClient.createUserContext("user123");
options = Arrays.asList(OptimizelyDecideOption.DISABLE_DECISION_EVENT,
OptimizelyDecideOption.DISABLE_DECISION_EVENT);
Map<String, OptimizelyDecision> decisions = user.decideAll(options);
Returns
The decide method returns an OptimizelyDecision
object. For information, see OptimizelyDecision.
If the method encounters a critical error (SDK not ready, invalid flag key, and so on), then it returns a decision with a null Variation Key field and populates the Reasons field with error messages (regardless of the OptimizelyDecideOption.INCLUDE_REASONS
option).
Example decision
The following code sample shows calling the decide method and accessing the returned OptimizelyDecision
object:
// create the user and decide which flag rule & variation they bucket into
val attributes: MutableMap<String, Any> = HashMap()
attributes["logged_in"] = true
val user = optimizelyClient.createUserContext("user123", attributes)
val decision = user!!.decide("product_sort")
// variation. if null, decision fail with a critical error
val variationKey = decision.variationKey
// flag enabled state:
val enabled = decision.enabled
// all variable values
val variables = decision.variables
// String variable value
var vs: String? = null
try {
vs = variables.getValue("sort_method", String::class.java)
} catch (e: JsonParseException) {
e.printStackTrace()
}
// Boolean variable value
val vb = variables.toMap()!!["k_boolean"] as Boolean?
// flag key for which decision was made
val flagKey = decision.flagKey
// user for which the decision was made
val userContext = decision.userContext
// reasons for the decision
val reasons = decision.reasons
// create the user and decide which flag rule & variation they bucket into
Map<String, Object> attributes = new HashMap<>();
attributes.put("logged_in", true);
OptimizelyUserContext user = optimizelyClient.createUserContext("user123", attributes);
OptimizelyDecision decision = user.decide("product_sort");
// variation. if null, decision fail with a critical error
String variationKey = decision.getVariationKey();
// flag enabled state:
boolean enabled = decision.getEnabled();
// all variable values
OptimizelyJSON variables = decision.getVariables();
// String variable value
String vs = null;
try {
vs = variables.getValue("sort_method", String.class);
} catch (JsonParseException e) {
e.printStackTrace();
}
// Boolean variable value
Boolean vb = (Boolean) variables.toMap().get("k_boolean");
// flag key for which decision was made
String flagKey = decision.getFlagKey();
// user for which the decision was made
OptimizelyUserContext userContext = decision.getUserContext();
// reasons for the decision
List<String> reasons = decision.getReasons();
Side effect
Invokes the decision notification listener if this listener is enabled.
Decide all
Returns decisions for all active (unarchived) flags for a user. See OptimizelyDecision for details.
Minimum SDK version – v3.7+
Description
You can ue the decide all method to fetch variation assignments for all experiments 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.
DISABLE_DECISION_EVENT
– Must be paired with DISABLE_DECISION_EVENT to prevent prematurely bucketing the user into experiment results. Ensures that the decision event (logging the experiment bucketing) is not triggered until the user sees the change.
Parameters
The following table describes the parameters for the decide all method:
Parameter | Type | Description |
---|---|---|
options (optional) | Array | Array of OptimizelyDecideOption enums. See OptimizelyDecideOption. |
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 an empty map. 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 decide all
// make decisions for all active (unarchived) flags in the project for a user
val options = Arrays.asList(OptimizelyDecideOption.ENABLED_FLAGS_ONLY)
val decisions = user!!.decideAll(options)
val allKeys: Set<String> = decisions.keys
val decisionForFlag1 = decisions["flag_1"]
// make decisions for all active (unarchived) flags in the project for a user
List<OptimizelyDecideOption> options = Arrays.asList(OptimizelyDecideOption.ENABLED_FLAGS_ONLY);
Map<String, OptimizelyDecision> decisions = user.decideAll(options);
Set<String> allKeys = decisions.keySet();
OptimizelyDecision decisionForFlag1 = decisions.get("flag_1");
Side effect
Invokes the decision notification listener for each decision, if this listener is enabled.
Decide for keys
Returns a map of flag decisions for specified flag keys.
Minimum SDK version – v3.7+
Description
Get a map of flag decisions for specific flag keys.
Parameters
The following table describes parameters for the decide for keys method:
Parameter | Type | Description |
---|---|---|
keys | Array | Array of string flag keys. |
options (optional) | Array | Array of OptimizelyDecideOption enums. See OptimizelyDecideOption . |
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 an empty map. 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
The following is an example of getting specified flags for the user:
// make decisions for specific flags
val keys = Arrays.asList("flag-1", "flag-2")
val decisions = user!!.decideForKeys(keys)
val decision1 = decisions["flag-1"]
val decision2 = decisions["flag-2"]
// make decisions for specific flags
List<String> keys = Arrays.asList("flag-1", "flag-2");
Map<String, OptimizelyDecision> decisions = user.decideForKeys(keys);
OptimizelyDecision decision1 = decisions.get("flag-1");
OptimizelyDecision decision2 = decisions.get("flag-2");
Side effects
Invokes the decision notification listener for each decision, if this listener is enabled.
Best practices
- Early and late invocation
- Use the decide all method early in your application's rendering process to load the correct cached content. For example, on the CDN with an Edge SDK.
- Use the decide method at the point of user interaction or when you must ensure Feature Experimentation records the decision in your experiment analytics.
- Combining methods – When using the decide and decide all methods, always pair the decide all method with the decide method for each experiment the user encounters. This prevents discrepancies between served content and analytics data.
- Parameter management – Ensure you use the
DISABLE_DECISION_EVENT
parameter with the decide all method to avoid premature bucketing, then use the decide method to handle the decision event when the user experiences the content.
Source files
The language and platform source files containing the implementation for the Android SDK are available on GitHub.
Updated 4 days ago