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:
- SDK Wrapper: Async Event Dispatcher by Cooper R
- SDK Wrapper: Bulk Event Dispatcher with AWS SQS by Matt A
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:
Updated 11 months ago