Optimizely Classic Android SDK Reference

Optimizely Classic will sunset on September 30, 2018. Please transition to Optimizely X Full Stack. Have questions? Our support team is here to help.

This section provides information on how to customize your SDK installation and code snippets for how to implement Optimizely's APIs.

Key things you can do include:

Connecting to Optimizely's Editor

It is highly recommended to use Optimizely's 'O' gesture to connect your app to Optimizely's editor. However, there are other options should you choose not to implement Optimizely's URL scheme.

Programmatically Enable Edit Mode

Typically Optimizely's 'O' gesture will put your app into Edit Mode, which will then allow you to connect with Optimizely's editor. However, if you choose not to implement the URL scheme in your app or are unable to put the app into 'Edit Mode', prior to startOptimizelyWithAPIToken, you can call enableEditor in the development version of your app so that you can make changes.

Optimizely.startOptimizelyWithAPIToken(getOptimizelyToken(), getApplication());

Note that you should always remove the enableEditor call prior to releasing your app to the App store.

Disable Gesture

By default, Optimizely's Android SDK disables the gesture if the app is live in the Play store. However, if you would like to ensure that your end users are not able to put the app into edit mode (e.g. if you have an enterprise app that you release to internal employees), you can call the setEditGestureEnabled method prior to startOptimizelyWithAPIToken.

An example of how to implement this method can be found below:

Optimizely.startOptimizelyWithAPIToken(getOptimizelyToken(), getApplication());

Visual Editor Configuration

The Optimizely Visual Editor allows you to modify existing views in your app. The first time you connect your app to Optimizely's Visual Editor, you can see which views are automatically detected by Optimizely. Optimizely is able to detect and allows you to modify these views by:

Tag Your Views

There are some cases where Optimizely will not be able to detect your views. For those views, you should give them a unique optimizelyId. An example of how to do this is below:

TextView priceTextView = (TextView) rowView.findViewById(R.id.textViewPrice);
Optimizely.setOptimizelyId("price_text_label", priceTextView);

Disable Visual Editor

If you decide you want to exclusively use Live Variables and Code Blocks, you can set setVisualExperimentsEnabled to false.

Note: Disabling the Visual Editor will also disable the ability to track tap goals. If you disable the Visual Editor, you'll need to rely only on view goals and custom event goals to track conversions.

Register Live Variables

Live Variables allow you to designate variables in your app that can be assigned values in the Optimizely editor. These values can be modified by Optimizely's editor even after you have released your app to the app store. For example, you might want to create an experiment that tests various values for gravity. Live Variables can be accessed anywhere in your application. These values can be used as feature flags, to modify the behavior of your app, or as a convenient way to update your app with new styling.

public class MyActivity extends Activity {
  private static LiveVariable<Float> gravityVariable = Optimizely.floatForKey("Gravity", 9.8f /* default value */);
  private static LiveVariable<Boolean> enableGravityVariable = Optimizely.booleanForKey("EnableGravity", true /* default value */);

  private float updateSpeed(float currentSpeed) {
    if (enableGravityVariable.get()) {
        return currentSpeed + gravityVariable.get();
    } else {
      return currentSpeed;

Once a variable is defined, each variation can specify a different value for that variable.

Optimizely defines different <type>Variable() functions for all the basic Java types. See the Class Documentation for more information. In order to access the variable, call Optimizely.<type>Variable and provide the corresponding variable name. Variables are scoped at an application level, thus repeated calls to Optimizely.<type>Variable will return the same value throughout your application.

import com.optimizely.Optimizely;

public class GameUtils {
  private static World makeNewWorld() {
      double gravity = Optimizely.floatVariable("Gravity", 9.8).get();

      // Use gravity here...

You're now ready to edit your Live Variables using the Optimizely web editor:

  1. Make sure you have not called Optimizely.setEditGestureEnabled(false).
  2. Load your application and draw a large circle to connect in edit mode.
  3. Navigate to the variables section of the editor. Drawing
  4. Click the "Add Variable" button to open a dialog where you can select variables to add to your experiment.
  5. Once you have added a variable to the experiment, you can select a value for each variation in the variables section of the editor.
  6. While in edit mode, changes to the variable will be applied on subsequent reads, thereby allowing you to quickly test your variable logic. However, we recommend that you verify your variable tests in preview mode prior to going live with the experiment.
  7. Once you've connected your app to the editor, you can later edit live variables without connecting a device. However, if you make any changes to your app, make sure to connect it again to allow your changes to sync with the editor.

Register Variable Callback

By default, in Edit Mode, Optimizely's editor will apply variable value changes once the screen the variable is defined on is reloaded. However, there may be times where you want the changed value of the variable to be reflected in your app without the screen being refreshed while you're making experiment changes. To do so, you can use the overloaded Optimizely.<type>Variable methods like "stringVariable(String variableKey, String defaultValue, Callback callback)".

An example implementation of this can be found below:

Optimizely.stringVariable("variableKey", "defaultValue", new LiveVariable.Callback<String>() {
  public void execute(String variableKey, @Nullable String value) {
    Log.i("log-tag", String.format("The value of Optimizely's Live Variable: %s is now %s",
              variableKey, value));

Code Blocks

Code Blocks allow developers to create variations that execute different code paths. Code Blocks are declared as static variables and then can be accessed anywhere in your application. For example, one use case might be to test various checkout flows.

Note: The syntax for Code Blocks was changed in version 1.0+

First, define your CodeBlock as a static variable, then, add handlers for each of the possible branches in your code:

private static OptimizelyCodeBlock checkoutFlow = Optimizely.codeBlock("CheckoutFlow")
        .withBranchNames("shortCheckout", "longCheckout");

The above Code Block will have 3 branches: the "default" branch, and a branch named "shortCheckout" and a branch named "longCheckout".

This is what the implementation of that Code Block looks like. Be sure to implement your Code Block branches in the same order as you declare them when initializing the Code Block.

public class CommerceActivity extends Activity {
  private static OptimizelyCodeBlock checkoutFlow = Optimizely.codeBlock("CheckoutFlow").withBranchNames("shortCheckout", "longCheckout");

  private void checkout() {
    // This line defines Code Blocks "shortCheckout", "longCheckout", and a
    // default block that is executed in the case that the experiment is
    // not activated.
    checkoutFlow.execute(new DefaultCodeBranch() {
            public void execute() {
                // This block is executed by default
        }, new CodeBranch() {
            public void execute() {
                // This block is executed when myCheckoutTest -> shortCheckout
        }, new CodeBranch() {
            public void execute() {
                // This block is executed when myCheckoutTest -> longCheckout

You're now ready to implement your experiment using the Optimizely web editor:

  1. Make sure you have not called Optimizely.setEditGestureEnabled(false).
  2. Load your application and draw a large circle to connect in edit mode.
  3. Navigate to the Code Blocks section of the editor. Drawing
  4. Click the "Add Code Block" button to open a dialog where you can select Code Blocks to add to your experiment.
  5. Once you have added a Code Block to the experiment, you can select a value for each variation in the Code Blocks section of the editor.
  6. While in edit mode, changes to the active block will be applied on subsequent executions, thereby allowing you to quickly test your Code Block's logic. However, we recommend that you verify your Code Blocks in preview mode prior to going live with the experiment.
  7. Once you've connected your app to the editor, you can later edit code blocks without connecting a device. However, if you make any changes to your app, make sure to connect it again to allow your changes to sync with the editor.

For more details, please see the Code Blocks API Reference

Register Code Block Callback

By default, in Edit Mode, Optimizely's editor will apply code block branch changes once the code block is executed again. However, there may be times where you want the new code block branch to be executed in your app without the screen being refreshed while you're making experiment changes. To do so, you can use the Optimizely.CodeBlock method setCallback(new OptimizelyCodeBlock.Callback(){...})

An example implementation of this can be found below:

OptimizelyCodeBlock myCodeBlock = Optimizely.codeBlock("myCodeBlock").setCallback(new OptimizelyCodeBlock.Callback() {
        public void onBranchChange() {
            // Calling renderViews will allow us to execute the code that wraps our code block
    }).withBranchNames("branch1", "branch2");

Phased Rollouts

A common use case for Code Blocks are phased rollouts. Phased rollouts allow you to release a feature to a subset of users, which will help you mitigate the risk of crashes and help you understand how users will react to your new feature prior to rolling out a new feature to all users. To learn more about to implement a phased rollout using Optimizely, you can refer to the article in Optiverse here.

Custom Targeting


Use attributes to segment your experiment results for more insight. This allows you to drill down into experiment results and discover how certain segments of users are behaving differently. This will allow you to create future experiments targeted to them.

To set the value for an Attribute use one of these four methods.

boolean success = Optimizely.setValueForAttributeId(String, String);
boolean success = Optimizely.setValueForAttributeApiName(String, String);
boolean success = Optimizely.setValueForAttributeId(String, String, Context);
boolean success = Optimizely.setValueForAttributeApiName(String, String Context);

Both methods will return a boolean that determines whether the value was successfully set for the Attribute. If the string you passed in for the Attribute Id or the Attribute API Name do not match an Attribute in your project, it will return false. If Optimizely was able to locate the Attribute and set the value, it will return true. If you are using these methods before starting Optimizely, you MUST pass in the current Context. When the latter 2 methods are called before starting Optimziely they will always return true even if the Attribute Id or Attribute API Name do not match an existing Attribute. If you use both setValueForAttributeId(String, String, Context) and setValueForAttributeApiName(String, String, Context) before starting Optimizely for the same attribute, setValueForAttributeId(String, String, Context) will override setValueForAttributeApiName(String, String, Context) when the Attribute is initialized.

To get the current value of an Attribute use one of these two methods.

String value = Optimizely.getValueForAttributeId(String);
String value = Optimizely.getValueForAttributeApiName(String);
String value = Optimziely.getValueForAttributeId(String, Context);
String value = Optimizely.getValueForAttributeApiName(String, Context);

Both methods will return an String object whose value is the current value for the associated Attribute. If the Attribute does not exist, it will return null. If you use these methods before starting Optimizely, you MUST passin the current Context. When called before starting Optimizely, they will return the last value you provided through the corresponding setValueForAttributeId(String, String, Context): or setValueForAttributeApiName(String, String, Context) call. But getValueForAttributeId(String, Context) will not be able to return the value for an Attribute whose value you have attempted to set through setValueForAttributeApiName(String, String, Context). Likewise, getValueForAttributeApiName(String, Context) will not be able to return the value for an Attribute whose value you have attempted to set through setValueForAttributeId(String, String, Context).

To get an Array of all the current Attributes, use

ArrayList<OptimizelyAttribute> *attributes = Optimizely.getAttributes();

This method returns a copy of all attributes that are defined in the data file. If this is called before Optimizely starts, it will return an empty array. If there are no attributes, it will return an empty array. Each attribute will be an index in the ArrayList represented by an instance of the OptimizelyAttribute class.

Custom Tags

Custom Tags allow you to target users based on variables and attributes before Optimizely starts. You will be able to run your experiment and target visitors based on those custom attributes, effectively only bucketing those who meet your targeting conditions. To create an experiment targeting a Custom Tag, open the Optimizely editor, click on "Options", followed by "Targeting" and selecting "Custom Tag" within the Optimizely editor.

For example, to create the Custom Tag "returning_customer" with a value of "true":

protected void onCreate(Bundle savedInstanceState) {

    // more create logic
    Optimizely.setCustomTag("returning_customer", "true");
    Optimizely.startOptimizelyWithAPIToken("<API Token>", getApplication());

Make sure to call setCustomTag prior to startOptimizelyWithAPIToken and any time custom tag values are expected to change. To do that you can make the setValue:forCustomTag: call in the following ways:

Please refer to our API Docs for more details.

Experiment Reload

refreshExperiments should be called any time custom tag values are expected to change. refreshExperiments allows Optimizely to take into account a user's newly added or changed custom tag values and re-buckets users based on updated targeting.

For example, here's a use case where the user logs in, the developer sets a logged in custom tag, and then calls refreshExperiments:

  private void userDidLogIn(String username) {
    Optimizely.setCustomTag("returning_customer", "true");

Note: Manually activated experiments will need to be re-activated after refreshExperments for the new audience conditions to take effect.

Goal Tracking

Track Event

Custom goals allow you to track events other than taps and view changes. There are two steps to creating a custom goal. The first step occurs in the web editor. Click "Goals", then "Create a New Goal", and select "Custom Goal" from the drop-down. You will be prompted for a string to uniquely identify your custom goal. In order to track this goal, send this same string as a parameter to


For example, if we wanted a goal for users deleting a task with a swipe, we might create a custom goal "User Deleted Task" and then call trackEvent with this string in our event handler as follows:

private void userDidSwipeTask() {
    //The rest of your handler

As of SDK version 1.1, if you aren't sure of the exact spelling of your custom goal string, you can trigger custom events in your simulator or connected device, and the strings will appear in the dialog in the order they were triggered.

For more details and to learn about tap and view goals, refer to the following guide from our Knowledge Base.

Revenue Tracking

The Revenue goal allows you to track purchases made by your users. There are two steps to adding the revenue goal to your experiment. The first step occurs in the web editor. Click "Goals", then "Add a Saved Goal", hover over the "Total Revenue" goal, and click the "Add" button. In order to track this goal, use the revenue API by passing an integer number of cents:

private void userCompletedPurchase() {
    Optimizely.trackRevenue(price * 100));
    //The rest of your handler

Analytics Integrations

Optimizely offers a number of configurable 3rd party analytics integrations in order to easily tag your analytics data with Optimizely experiments. Each integration is available as a separate package.

Currently, we support the following frameworks in our Android SDK. Detailed integration instructions can be found if you follow the respective link:

For basic configuration instructions, you can scroll down to the 3rd party analytics tool to find code that needs to be added to the app. For all integrations, Optimizely should be initialized after your third party analytics tool is initialized in your code. Once you have followed the configuration instructions below, you can enable the integration through your Optimizely Project Dashboard.



Gradle dependency:

dependencies {


Gradle dependency:

dependencies {


Gradle dependency:

dependencies {


MixpanelAPI mixpanelAPI = MixpanelAPI.getInstance(this, "API_TOKEN");
Optimizely.startOptimizelyWithAPIToken("<API Token>", getApplication());

Universal Analytics (Google Analytics)

Gradle dependency:

dependencies {


Tracker tracker = GoogleAnalytics.getInstance(this).newTracker("TRACKER_ID");

Custom Integration

You can also build your own analytics integrations by accessing the experiments and variations active for a given user directly using the Optimizely.getVisitedExperiments() and pass that data to internal or other analytics frameworks. For more details about this property, you can refer to the API documentation).

When building your own analytics integration, the recommended time to access the Optimizely.getVisitedExperiments() data and send that to the analytics framework is in the method onOptimizelyExperimentViewed(OptimizelyExperimentData experimentState) which can be found when you add the OptimizelyEventListener to Optimizely.

Network Settings

There are only two instances when the Optimizely Android SDK uses a network connection: when downloading the config file (which contains all experiment configuration information) and when returning event tracking data. By default, the config file is automatically downloaded every 2 minutes. Event tracking data is automatically uploaded whenever the user leaves a screen of your application (on every Activity.onPause). The Optimizely Android SDK allows you to customize how often these network calls are made by:

  1. Customizing the 2 minute interval
  2. By turning off automatic sending of events and allowing you to sending events manually.

The first option is to customize the interval for how often you want network calls to be made. To adjust the interval in seconds, you can call Optimizely.setDataFileDownloadInterval(long). Setting the download interval to 0 or a negative value will completely disable downloading of the data file (Not recommended). For example, to set the data file download to 5 minutes (300,000ms): Optimizely.setDataFileDownloadInterval(5 * 60 * 1000);

The second option is to turn off the automatic event sends and manually make network calls. Calling Optimizely.setAutomaticEventSending(false); will disable the automatic sending of events. You will need to send events manually using Optimizely.sendEvents() in order to collect experiment results.


To manually send events, in the appropriate function (e.g. where you make other network calls or after a custom event goal is triggered):

  private void userClickedImportantButton() {
      Optimizely.sendEvents(); // Manually send the event logs back to the server

Please refer to the documentation for trackEvent, and sendEventsfor more details.

Manual Activation

Experiment Activation Modes

There are two different types of activation modes for Optimizely Mobile experiments.

Automatic (Default)

By default, Optimizely buckets users and activates the experiment as soon as the app starts and the startOptimizely method is called (either synchronously or asynchronously). Experiments are marked as visited when the end user reaches an element that has been modified in the experiment.


In manual activation mode, developers can specify, via an in-app API call, at which point they want to activate a given experiment. Manual activation allows you to separate the experiment start (which buckets the users and activates the experiment) from startOptimizely, which loads the datafile and any remote assets, such as images. Manual activation is only available for SDK versions 1.3.0 and above.

Please note that visitors still must meet Audience targeting conditions for a manually activated experiment to be eligible for that experiment. Manual activation does not bypass Audience conditions.

Toggle between manual and automatic activation mode from the Options > Activation Mode menu in the Editor:


Use Cases

Use Case #1: Set additional metadata for your audiences before evaluating targeting conditions for an unactivated experiment.

Bucketing only occurs for your audiences when activateExperiment is called and NOT when startOptimizely is called, and thus any custom tags you set before the experiment starts will be considered for targeting. For example, you can mark a user as a “VIP” at one point during a session, then use this tag for an experiment later in the same session. With automatic activation mode, you can only target using tags set before the app was started (and thus set in a previous session).

Use Case #2: Bucket only a subset of users who access less frequently used areas of your app.

Bucketing users when the app loads, which is done in automatic mode, may not be the best choice for experiments involving an experience that not all users visit. For example, if you want to test a feature deep in your user experience that only 10% of users visit, you wouldn’t necessarily want to bucket all users when you launch your app (as is done with automatic mode), because this could lead to skewed sampling. If you manually activate your experiment only when users reach that experience, you can bucket users at the point where they visit that feature, and run tests on only those users.

Use Case #3: Quick-load assets for consistency.

Remote assets distributed by the Optimizely CDN, such as images you upload to our editor, start loading asynchronously when the app starts. As a result, if any assets fail to load before an experiment is viewed due to slow internet speeds, the user is not showed the variation and is instead shown the control even though that user has been bucketed. The variation will be shown to the user the next time he or she opens the app, assuming the assets have loaded before he or she views the experiment, leading to an inconsistent user experience and possibly even skewed results. In manual activation mode, you can activate experiments right when you want to show them, giving the user’s device more time to load assets associated with that experiment.

Manual Activation Example

// Calling start Optimizely will not activate any manual experiments.
// Instead you have to activate them manually for users to see your experiment
Optimizely.startOptimizelyWithAPIToken(myOptimizelyAPIKey, getApplication());


// You specify when you want to activate each manual experiment.
// For use case #1 above, this can be useful if you want to wait until you
// have additional data for a user and then store that data as custom tags.
// For example, we now know that the user is a VIP user so we set a tag for that
Optimizely.setCustomTag("accountType", "VIP");

// Activate a manual experiment that takes the custom tag we just set into account
boolean success = Optimizely.activateManualExperiment(myExperimentId);

Debugging Your Experiments

Adding an Event Listener

Clients can get notifications when various Optimizely events occur in the Optimizely SDK life cycle like start of the SDK or an experiment visited. To do that, client needs to register a callback with Optimizely and override methods which they are interested in.

  Optimizely.addOptimizelyEventListener(new OptimizelyEventListener() {

    public void onOptimizelyStarted() {
      Log.i(tag, "Optimizely started.");

    public void onOptimizelyFailedToStart(String errorMessage) {
      Log.i(tag, format("Optimizely failed to start with message {%s}", errorMessage));

    public void onOptimizelyExperimentVisited(OptimizelyExperimentData experimentState) {
      Log.i(tag, format("Optimizely experiment {%s} visited.", experimentState));

    public void onOptimizelyEditorEnabled() {
      Log.i(tag, "Optimizely is ready to connect to the editor.");

    public void onOptimizelyDataFileLoaded() {
      Log.i(tag, "Optimizely experiment data file loaded.");

    public void onGoalTriggered(String description,
                                List<OptimizelyExperimentData> affectedExperiments) {
      Log.i(tag, format("Optimizely goal {%s} part of experiments {%s} achieved.",
                          description, affectedExperiments));

    public void onMessage(String source, String messageType, Bundle payload) {
      Log.i(tag, format("Optimizely received message %s from %s {%s; %s} .",
                          messageType, source, payload));

Experiment Data Object

Optimizely's Experiment Object will provide information about what part of the experiment life cycle a user is part of. There are two main functions: getAllExperiments and getVisitedExperiments. getAllExperiments contains all running, paused, and draft experiments in your Optimizely project. getVisitedExperiments contains all experiments in your Optimizely project that a user has actually visited. You can also query for the OptimizelyExperimentData associated to a given experimentId by using getExperimentDataById.

Each experiment is represented as an OptimizelyExperimentData object. For more info on the properties contained there, see the class reference for OptimizelyExperimentData.

// This will get all your experiments
Map<String, OptimizelyExperimentData> allExperiments = Optimizely.getAllExperiments();

// This will get all your visited experiments
Map<String, OptimizelyExperimentData> visitedExperiments = Optimizely.getVisitedExperiments();

// This will get the experiment with the corresponding experimentId
OptimizelyExperimentData data = Optimizely.getExperimentDataById("EXPERIMENT_ID");

Audience Information

There are a couple utility functions that you can use to help aid in debugging audiences. getAudiences will return a JSONArray of all the audiences associated with your project. Each audience is represented as an JSONObject and you'll be able extract additional metadata through the following keys: audience_id, conditions, and name. From there you can check whether or not the user currently satisfy a given audience by calling isUserInAudience with a specific audienceId. Keep in mind that both of these methods need to be called after Optimizely is started.

Here's an example below:

// Make sure to call the helper functions after starting Optimizely
Optimizely.startOptimizelyWithAPIToken(myOptimizelyAPIKey, getApplication());

// Gets an array that holds all your project audiences
JSONArray audiences = Optimizely.getAudiences();

for(int i = 0; i < audiences.length(); i++) {
    JSONObject audience = audiences.getJSONObject(i);
    // You can access the metadata associated with each audience
    // Here we're just getting each audience's audienceId
    String audienceId = audience.getString("audience_id");

    // We can then check to see if the user currently satisfies those
    // audience conditions
    boolean included = Optimizely.isUserInAudience(audienceId);
    Log.d("tag", "The user " + (included ? "is" : "isn't") + " included in this audience:" + audienceId);

Forcing a Variation

Sometimes you'll want to try out your experiment before it goes live and outside of preview mode. You may spend a lot of time re-bucketing yourself in order to get into all the experiment combinations. Now you can opt to force an experiment into a given variation with forceVariation. You must force the variation before calling start Optimizely.

When you force a variation for a given experiment, we'll reset the app's userId and try to force that experiment/variation if they are both valid. This should be called before startOptimizely is called and keep in mind that you should only use this for testing your experiments. You should NOT ship this to your customers.

Here's an example below:

// Force the variation and experiment specified by those two ids
Optimizely.forceVariation(myVariationId, myExperimentId);

// Make sure to call it before start Optimizely is called
Optimizely.startOptimizelyWithAPIToken(myOptimizelyAPIKey, getApplication());

To find a variation's ID, head to the experiment editor and click on the "Variation Settings" button on the black bar on the far left-hand side of the window.

Note your experiment must not be paused for forceVariation to take effect.

Programmatically Enable Preview Mode

While preview mode can be enabled from the dashboard it can also be enabled from code. This allows you to preview variations across all of your experiments without needing to connect to the editor. Preview mode has UI that allows you easily switch variations and view event logs.

Optimizely.startOptimizelyWithAPIToken(getOptimizelyToken(), getApplication());

Resetting QA State

Uninstalling the app everytime to QA your builds with Optimizely can be quite tedious. Now you can use resetUserBucketing to clear any variations that the current app user may have already been bucketed into. This will also remove the cached data file. This is useful if you want to insure that you're treated as a new user each time you start the app. Keep in mind that you must call resetUserBucketing before you start Optimizely.

Here's an example below:

// Reset user bucketing

// Make sure to call it before start Optimizely is called
Optimizely.startOptimizelyWithAPIToken(myOptimizelyAPIKey, getApplication());

Verbose Logging

Enabling verbose logging allows you to view detailed log output. This will provide more information about experiments and its goals, your Live Variables, Code Blocks, and more.

// Enable verbose logging

// Make sure to call it before start Optimizely is called
Optimizely.startOptimizelyWithAPIToken(myOptimizelyAPIKey, getApplication());

Upgrading to a new SDK

  1. If you are using Gradle, simply replace the dependency declaration in your build.gradle with a dependency on the new version.

    Here are some examples with Gradle:

    • If you want to always stay up to date with our newest SDK version, allow Gradle to auto-update the Optimizely SDK:

      compile('com.optimizely:optimizely:+@aar') {
         transitive = true
    • If you want to specify when you want to upgrade to monthly SDK feature releases (numbered v X.Y) and automatically upgrade to the newest incremental releases and hotfixes for that release (numbered v X.Y.Z), in this case all releases 1.3 and after and up to 1.5:

      compile('com.optimizely:optimizely:1.3+@aar') {
         transitive = true
    • If you want to upgrade to a particular SDK version and stay at that version, in this case version 1.4.2:

      compile('com.optimizely:optimizely:1.4.2@aar') {
       transitive = true
  1. Starting with SDK version 1.1, Optimizely's Android SDK uses a unique URL scheme handler to help you edit and test your experiments.

    If you are upgrading from an SDK version more outdated than 1.1 to version 1.1 or later, please add the following intent filter to the MainActivity entry of your AndroidManifest.xml

        <!-- Existing intent-filters -->
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data android:scheme="optly[PROJECT_ID]" />

    Note: The scheme includes a unique identifier. Be sure to replace [PROJECT_ID] with your project id.

If you are using manual integration, please repeat the Manual Installation Steps for your platform.

Uninstalling Optimizely

Simply remove the dependency on Optimizely from your build.gradle. If you installed manually, you need to delete Optimizely.jar from your app.