Optimizely will be sunsetting Full Stack Experimentation on July 29, 2024. See the recommended Feature Experimentation migration timeline and documentation.

Dev GuideAPI Reference
Dev GuideAPI ReferenceUser GuideGitHubNuGetDev CommunitySumbit a ticketLog In
GitHubNuGetDev CommunitySumbit a ticket
These docs are for v2.0. Click to read the latest docs for v3.0.

Configure the event dispatcher

The Optimizely SDKs make HTTP requests for every impression or conversion that gets triggered. Each SDK has a built-in event dispatcher for handling these events, but we recommend overriding it based on the specifics of your environment.

SDKs with out-of-the-box asynchronous dispatchers:

  • Java
  • C#
  • JavaScript
  • Objective-C
  • Swift
  • Android

SDKs with out-of-the-box synchronous dispatchers:

  • Python
  • Ruby
  • PHP

🚧

Important

Performance risks with synchronous dispatchers: It is important to customize your event dispatcher when using an SDK for a blocking language (PHP, Ruby, and Python) to ensure that you can retrieve variations without waiting for the corresponding network request to return.

Regardless of the SDK you're using, we recommend customizing the event dispatcher you use in production to ensure that you queue and send events in a manner that scales to the volumes handled by your application. Customizing the event dispatcher allows you to take advantage of features like batching, which makes it easier to handle large event volumes efficiently or to implement retry logic when a request fails. You can build your dispatcher from scratch or start with the provided dispatcher.

To customize the event dispatcher, initialize the Optimizely client (or manager) with an event dispatcher instance:

import com.optimizely.ab.android.sdk.OptimizelyManager;
import com.optimizely.ab.event.EventHandler;
import com.optimizely.ab.android.event_handler.EventRescheduler;

// Using an anonymous class here to implement the EventHandler interface. 
// Feel free to create an explicit class that implements the interface instead.
EventHandler eventHandler = new EventHandler() {
    @Override
    public void dispatchEvent(LogEvent logEvent) throws Exception {
        // Send event to our log endpoint as documented in https://developers.optimizely.com/x/events/api/index.html
    }
};

// Build a manager
optimizelyManager = OptimizelyManager.builder()
  .withSDKKey("SDK_KEY_HERE")
  .withEventDispatchInterval(60L * 10L)
  .withEventHandler(eventHandler)
  .withDatafileDownloadInterval(60L * 10L)
  .build(getApplicationContext());

/** 
 * With the new Android O differences, you need to register the
 * service for the intent filter you desire in code instead of 
 * in the manifest.
 */
EventRescheduler eventRescheduler = new EventRescheduler();

getApplicationContext().registerReceiver(eventRescheduler, new IntentFilter(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION));
using OptimizelySDK;
using OptimizelySDK.Event.Dispatcher;

// Create an Optimizely client with the default event dispatcher
	Optimizely OptimizelyClient = new Optimizely(
			datafile: datafile,
			eventDispatcher: new DefaultEventDispatcher(new OptimizelySDK.Logger.DefaultLogger()));
import com.optimizely.ab.Optimizely;
import com.optimizely.ab.config.parser.ConfigParseException;
import com.optimizely.ab.event.AsyncEventHandler;
import com.optimizely.ab.event.EventHandler;

/**
 * Creates an async event handler with a max buffer of
 *  20,000 events and a single dispatcher thread
 */
EventHandler eventHandler = new AsyncEventHandler(20000, 1);

Optimizely optimizelyClient;
try {
    // Create an Optimizely client with the default event dispatcher
    optimizelyClient = Optimizely.builder(datafile,
                                          eventHandler).build();
} catch (ConfigParseException e) {
    // Handle exception gracefully
    return;
}
var defaultEventDispatcher = require('@optimizely/optimizely-sdk/lib/plugins/event_dispatcher/index.browser');

// Create an Optimizely client with the default event dispatcher
var optimizelyClientInstance = optimizely.createInstance({
  datafile: datafile,
  eventDispatcher: defaultEventDispatcher
});
// Client with defaultEventDispatcher
const defaultEventDispatcher = require("@optimizely/optimizely-sdk/lib/plugins/event_dispatcher/index.node");

// Create an Optimizely client with the default event dispatcher
var optimizelyClientWithDefaultDispatcher = optimizely.createInstance({
  datafile,
  eventDispatcher: defaultEventDispatcher
});
CustomEventDispatcher *customEventDispatcher = [[CustomEventDispatcher alloc] init];

/** 
 * Initialize your Manager 
 *  (settings will propagate to OPTLYClient and Optimizely)
 */
  OPTLYManager *manager = [[OPTLYManager alloc] initWithBuilder:[OPTLYManagerBuilder  builderWithBlock:^(OPTLYManagerBuilder * _Nullable builder) {
      builder.sdkKey = @"SDK_KEY_HERE";
			builder.eventDispatcher = customEventDispatcher;
    }]];
use Optimizely\Event\Dispatcher\DefaultEventDispatcher;

/** 
 * Create an Optimizely client with the default event dispatcher.
 * Please note, if not provided it will default to this event dispatcher.
 */
$optimizelyClient = new Optimizely($datafile, new DefaultEventDispatcher());

/**
 * You can provide your own implementation of the event dispatcher
 * for sending events to Optimizely. It should however implement
 * Optimizely\Event\Dispatcher\EventDispatcherInterface.
 */
from optimizely.event_dispatcher import EventDispatcher as event_dispatcher
from optimizely import optimizely

# Create an Optimizely client with the default event dispatcher
optimizely_client = optimizely.Optimizely(datafile,
                                          event_dispatcher=event_dispatcher)
# Create an Optimizely client with the default event dispatcher
optimizely_client = Optimizely::Project.new(datafile,
                                            Optimizely::EventDispatcher.new)
let customEventDispatcher: CustomEventDispatcher = CustomEventDispatcher.init()

/**
 * Initialize your Manager 
 * (settings will propagate to OPTLYClient and Optimizely)
 */
 let manager = OPTLYManager(builder: OPTLYManagerBuilder(block: { (builder) in
  builder?.sdkKey = "SDK_KEY_HERE"
  builder?.eventDispatcher = customEventDispatcher
 }))

The event dispatcher should implement a dispatchEvent function, which takes in three arguments: httpVerb, url, and params, all of which are created by the internal EventBuilder class. In this function, you should send a POST request to the given url using the params as the body of the request (be sure to stringify it to JSON) and {content-type: 'application/json'} in the headers.

Android

The included event handler implementation includes queueing and flushing, so it will work even if an app is offline. The event handler uses an IntentService to queue up events to dispatch. If they fail to send, they are stored in a sqlite database and scheduled to be dispatched later. If you want to have events flushed when Wi-Fi is available or after reboot or reinstall using the default event handler, you need to augment your AndroidManifest.xml to include the intent filter declarations.

  <!--
    Add these lines to your manifest if you want the event handler background services to schedule 
    themselves again after a boot or package replace.
  -->
  <receiver
      android:name="com.optimizely.ab.android.event_handler.EventRescheduler"
      android:enabled="true"
      android:exported="false">
      <intent-filter>
          <action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
          <action android:name="android.intent.action.BOOT_COMPLETED" />
          <action android:name="android.net.wifi.supplicant.CONNECTION_CHANGE" />
      </intent-filter>
  </receiver>

You will need to implement EventHandler to use your own event handler.

📘

Note

To handle backgrounding in Android O and later, you also need to register your event handler rescheduler in code. See the code sample above.

iOS

The included event handler implementation, OptimizelySDKEventDispatcher, includes queueing and flushing, so will work even if an app is offline. You will need to implement OPTLYEventDispatcher to use your own event handler.

Java

We provide an asynchronous event dispatcher, optimizely-sdk-httpclient, that requires org.apache.httpcomponents:httpclient:4.5.2 and is parameterized by in-memory queue size and number of dispatch worker threads.

To use your own event dispatcher, implement the dispatchEvent method in our EventHandler interface. dispatchEvent takes in a LogEvent object containing all of the information needed to dispatch an event to Optimizely's backend. Events should be sent to LogEvent.getEndpointUrl as a POST request with LogEvent.getBody as the payload and content-type: "application/json" as the header.

JavaScript

By default, our JavaScript SDK uses a basic asynchronous event dispatcher.

PHP

Our PHP SDK includes a basic synchronous event dispatcher.

Python

Our Python SDK includes a basic synchronous event dispatcher.
Examples of alternative approaches are available here:

Ruby

Our Ruby SDK includes a basic synchronous event dispatcher. If you are using the SDK in a production environment, you should provide your own event dispatcher using the networking library of your choice. Examples of alternative approaches are available here: