This guide will help you migrate your implementation from Optimizely JavaScript SDK v5 to v6. The new version introduces several architectural changes that provide more flexibility and control over SDK components.
- Major Changes
- Client Initialization
- Project Configuration Management
- Event Processing
- ODP Management
- VUID Management
- Error Handling
- Logging
- onReady Promise Behavior
- Dispose of Client
- Migration Examples
In v6, the SDK architecture has been modularized to give you more control over different components:
- The monolithic
createInstance
call is now split into multiple factory functions - Core functionalities (project configuration, event processing, ODP, VUID, logging, and error handling) are now configured through dedicated components created via factory functions, giving you greater flexibility and control in enabling/disabling certain components and allowing optimizing the bundle size for frontend projects.
- Event dispatcher interface has been updated to use Promises
- onReady Promise behavior has changed
import { createInstance } from '@optimizely/optimizely-sdk';
const optimizely = createInstance({
sdkKey: '<YOUR_SDK_KEY>',
datafile: datafile, // optional
datafileOptions: {
autoUpdate: true,
updateInterval: 300000, // 5 minutes
},
eventBatchSize: 10,
eventFlushInterval: 1000,
logLevel: LogLevel.DEBUG,
errorHandler: { handleError: (error) => console.error(error) },
odpOptions: {
disabled: false,
segmentsCacheSize: 100,
segmentsCacheTimeout: 600000, // 10 minutes
}
});
import {
createInstance,
createPollingProjectConfigManager,
createBatchEventProcessor,
createOdpManager,
createVuidManager,
createLogger,
createErrorNotifier,
DEBUG
} from "@optimizely/optimizely-sdk";
// Create a project config manager
const projectConfigManager = createPollingProjectConfigManager({
sdkKey: '<YOUR_SDK_KEY>',
datafile: datafile, // optional
autoUpdate: true,
updateInterval: 300000, // 5 minutes in milliseconds
});
// Create an event processor
const eventProcessor = createBatchEventProcessor({
batchSize: 10,
flushInterval: 1000,
});
// Create an ODP manager
const odpManager = createOdpManager({
segmentsCacheSize: 100,
segmentsCacheTimeout: 600000, // 10 minutes
});
// Create a VUID manager (optional)
const vuidManager = createVuidManager({
enableVuid: true
});
// Create a logger
const logger = createLogger({
level: DEBUG
});
// Create an error notifier
const errorNotifier = createErrorNotifier({
handleError: (error) => console.error(error)
});
// Create the Optimizely client instance
const optimizely = createInstance({
projectConfigManager,
eventProcessor,
odpManager,
vuidManager,
logger,
errorNotifier
});
In case an invalid config is passed to createInstance
, it returned null
in v5. In v6, it will throw an error instead of returning null.
In v6, datafile management must be configured by passing in a projectConfigManager
. Choose either:
For automatic datafile updates:
const projectConfigManager = createPollingProjectConfigManager({
sdkKey: '<YOUR_SDK_KEY>',
datafile: datafileString, // optional
autoUpdate: true,
updateInterval: 60000, // 1 minute
urlTemplate: 'https://custom-cdn.com/datafiles/%s.json' // optional
});
When you want to manage datafile updates manually or want to use a fixed datafile:
const projectConfigManager = createStaticProjectConfigManager({
datafile: datafileString,
});
In v5, a batch event processor was enabled by default. In v6, an event processor must be instantiated and passed in
explicitly to createInstance
via the eventProcessor
option to enable event processing, otherwise no events will
be dispatched. v6 provides two types of event processors:
Queues events and sends them in batches:
const batchEventProcessor = createBatchEventProcessor({
batchSize: 10, // optional, default is 10
flushInterval: 1000, // optional, default 1000 for browser
});
Sends events immediately:
const forwardingEventProcessor = createForwardingEventProcessor();
In both v5 and v6, custom event dispatchers must implement the EventDispatcher
interface. In v6, the EventDispatcher
interface has been updated so that the dispatchEvent
method returns a Promise instead of calling a callback.
In v5 (Before):
export type EventDispatcherResponse = {
statusCode: number
}
export type EventDispatcherCallback = (response: EventDispatcherResponse) => void
export interface EventDispatcher {
dispatchEvent(event: EventV1Request, callback: EventDispatcherCallback): void
}
In v6(After):
export type EventDispatcherResponse = {
statusCode?: number
}
export interface EventDispatcher {
dispatchEvent(event: LogEvent): Promise<EventDispatcherResponse>
}
In v5, ODP functionality was configured via odpOptions
and enabled by default. In v6, instantiate an OdpManager and pass to createInstance
to enable ODP:
const optimizely = createInstance({
sdkKey: '<YOUR_SDK_KEY>',
odpOptions: {
disabled: false,
segmentsCacheSize: 100,
segmentsCacheTimeout: 600000, // 10 minutes
eventApiTimeout: 1000,
segmentsApiTimeout: 1000,
}
});
const odpManager = createOdpManager({
segmentsCacheSize: 100,
segmentsCacheTimeout: 600000, // 10 minutes
eventApiTimeout: 1000,
segmentsApiTimeout: 1000,
eventBatchSize: 5, // Now configurable in browser
eventFlushInterval: 3000, // Now configurable in browser
});
const optimizely = createInstance({
projectConfigManager,
odpManager
});
To disable ODP functionality in v6, simply don't provide an ODP Manager to the client instance.
In v6, VUID tracking is disabled by default and must be explicitly enabled by createing a vuidManager with enableVuid
set to true
and passing it to createInstance
:
const vuidManager = createVuidManager({
enableVuid: true, // Explicitly enable VUID tracking
});
const optimizely = createInstance({
projectConfigManager,
vuidManager
});
Error handling in v6 uses a new errorNotifier object:
const optimizely = createInstance({
errorHandler: {
handleError: (error) => {
console.error("Custom error handler", error);
}
}
});
const errorNotifier = createErrorNotifier({
handleError: (error) => {
console.error("Custom error handler", error);
}
});
const optimizely = createInstance({
projectConfigManager,
errorNotifier
});
Logging in v6 is disabled by defualt, and must be enabled by passing in a logger created via a factory function:
const optimizely = createInstance({
logLevel: LogLevel.DEBUG
});
import { createLogger, DEBUG } from "@optimizely/optimizely-sdk";
const logger = createLogger({
level: DEBUG
});
const optimizely = createInstance({
projectConfigManager,
logger
});
The onReady()
method behavior has changed in v6. In v5, onReady() fulfilled with an object that had two fields: success
and reason
. If the instance failed to initialize, success
would be false
and reason
will contain an error message. In v6, if onReady() fulfills, that means the instance is ready to use, the fulfillment value is of unknown type and need not to be inspected. If the promise rejects, that means there was an error during initialization.
optimizely.onReady().then(({ success, reason }) => {
if (success) {
// optimizely is ready to use
} else {
console.log(`initialization unsuccessful: ${reason}`);
}
});
optimizely
.onReady()
.then(() => {
// optimizely is ready to use
console.log("Client is ready");
})
.catch((err) => {
console.error("Error initializing Optimizely client:", err);
});
import { createInstance } from '@optimizely/optimizely-sdk';
const optimizely = createInstance({
sdkKey: '<YOUR_SDK_KEY>'
});
optimizely.onReady().then(({ success }) => {
if (success) {
// Use the client
}
});
import {
createInstance,
createPollingProjectConfigManager
} from '@optimizely/optimizely-sdk';
const projectConfigManager = createPollingProjectConfigManager({
sdkKey: '<YOUR_SDK_KEY>'
});
const optimizely = createInstance({
projectConfigManager
});
optimizely
.onReady()
.then(() => {
// Use the client
})
.catch(err => {
console.error(err);
});
import { createInstance, LogLevel } from '@optimizely/optimizely-sdk';
const optimizely = createInstance({
sdkKey: '<YOUR_SDK_KEY>',
datafileOptions: {
autoUpdate: true,
updateInterval: 60000 // 1 minute
},
eventBatchSize: 3,
eventFlushInterval: 10000, // 10 seconds
logLevel: LogLevel.DEBUG,
odpOptions: {
segmentsCacheSize: 10,
segmentsCacheTimeout: 60000 // 1 minute
}
});
optimizely.notificationCenter.addNotificationListener(
enums.NOTIFICATION_TYPES.TRACK,
(payload) => {
console.log("Track event", payload);
}
);
import {
createInstance,
createPollingProjectConfigManager,
createBatchEventProcessor,
createOdpManager,
createLogger,
DEBUG,
NOTIFICATION_TYPES
} from '@optimizely/optimizely-sdk';
const projectConfigManager = createPollingProjectConfigManager({
sdkKey: '<YOUR_SDK_KEY>',
autoUpdate: true,
updateInterval: 60000 // 1 minute
});
const batchEventProcessor = createBatchEventProcessor({
batchSize: 3,
flushInterval: 10000, // 10 seconds
});
const odpManager = createOdpManager({
segmentsCacheSize: 10,
segmentsCacheTimeout: 60000 // 1 minute
});
const logger = createLogger({
level: DEBUG
});
const optimizely = createInstance({
projectConfigManager,
eventProcessor: batchEventProcessor,
odpManager,
logger
});
optimizely.notificationCenter.addNotificationListener(
NOTIFICATION_TYPES.TRACK,
(payload) => {
console.log("Track event", payload);
}
);
For complete implementation examples, refer to the Optimizely JavaScript SDK documentation.