Disclaimer: This website requires Please enable JavaScript in your browser settings for the best experience.

Dev guideRecipesAPI ReferenceChangelog
Dev guideAPI ReferenceRecipesChangelogUser GuideGitHubDev CommunityOptimizely AcademySubmit a ticketLog In
Dev guide

Handle user IDs

Information on user IDs in Optimizely Feature Experimentation.

Optimizely Feature Experimentation identifies visitors with user IDs and determines which variation they see in an experiment (A/B test or multi-armed bandit) or a flag delivery (targeted delivery). Feature Experimentation lets you define user IDs based on your testing strategy. For example, you can use a first-party cookie, a device ID for anonymous users, or a stored identifier for logged-in users.

See Handle user IDs in Feature Experimentation in the user documentation for more information.

Create a user context example

Feature Experimentation SDKs manage user IDs through user contexts. When you create a user context, you define a user ID and optional attributes for audience targeting. The SDKs consistently assign a user to the same variation as long as the traffic distribution is not modified. See Why you should not change a running experiment.

The following code samples demonstrate creating a user context using Feature Experimentation SDKs. Every Feature Experimentation SDK handles creating a user context similarly. Scroll right on the list of SDKs in the code sample box to see additional SDKs.

// Initalize the Android SDK
// Build a manager
val optimizelyManager = OptimizelyManager.builder()
        // Provide the sdkKey of your desired environment here
        .withSDKKey("YOUR_SDK_KEY")
        .build(context)
// Instantiate a client synchronously with a bundled datafile
// Copy datafile JSON from URL accessible in App>Settings
val datafile = "<REPLACE_WITH_YOUR_DATAFILE>"
val optimizelyClient = optimizelyManager.initialize(context, datafile)

// Option 1 – Create a user, then set attributes.
var user: OptimizelyUserContext?
user = optimizelyClient.createUserContext("YOUR_USER_ID")
user.setAttribute("is_logged_in", false)
user.setAttribute("app_version", "1.3.2")

// Option 2 – Pass attributes when creating the user.
val attributes: MutableMap<String, Any> = HashMap()
attributes["is_logged_in"] = false
attributes["app_version"] = "1.3.2"
user = optimizelyClient.createUserContext("YOUR_USER_ID", attributes)
// Initalize the Android SDK
// Build a manager
OptimizelyManager optimizelyManager = OptimizelyManager.builder()
       // Provide the sdkKey of your desired environment here
       .withSDKKey("YOUR_SDK_KEY")
       .build(context);
// Instantiate a client synchronously with a bundled datafile
// copy datafile JSON from URL accessible in app>settings
String datafile = "REPLACE_WITH_YOUR_DATAFILE";
OptimizelyClient optimizelyClient = optimizelyManager.initialize(context, datafile);


// Option 1 – Create a user, then set attributes.
OptimizelyUserContext user;
user = optimizelyClient.createUserContext("YOUR_USER_ID");
user.setAttribute("is_logged_in", false);
user.setAttribute("app_version", "1.3.2");

// Option 2 – Pass attributes when creating the user.
Map<String, Object> attributes = new HashMap<>();
attributes.put("is_logged_in", false);
attributes.put("app_version", "1.3.2");
user = optimizelyClient.createUserContext("YOUR_USER_ID", attributes);
// Import Optimizely SDK
using OptimizelySDK;

// Instantiate an Optimizely client
// Provide the sdkKey of your desired environment here
var optimizely = OptimizelyFactory.NewDefaultInstance("YOUR_SDK_KEY");

// Option 1 – Create a user, then set attributes.
var user = optimizely.CreateUserContext("YOUR_USER_ID");
user.SetAttribute("is_logged_in", false);
user.SetAttribute("app_version", "1.3.2");

// Option 2 – Pass attributes when creating the user.
var attributes = new UserAttributes
{
    { "is_logged_in", false },
    { "app_version", "1.3.2" }
};
var user = optimizely.CreateUserContext("YOUR_USER_ID", attributes);
// Initialize OptimizelyClient
// Provide the sdkKey of your desired environment here
var flutterSDK = OptimizelyFlutterSdk("YOUR_SDK_KEY");
var response = await flutterSDK.initializeClient();

// Option 1 – Create a user, then set attributes.
var user = await flutterSDK.createUserContext("YOUR_USER_ID");
var attributes = <String, dynamic>{};
attributes["is_logged_in"] = false;
attributes["app_version"] = "1.3.2";
user!.setAttributes(attributes);

// Option 2 – Pass attributes when creating the user.
var attributes = <String, dynamic>{};
attributes["is_logged_in"] = false;
attributes["app_version"] = "1.3.2";
var optimizelyUserContext = await optimizelyClient.createUserContext(userId: "YOUR_USER_ID", attributes: attributes);
import "github.com/optimizely/go-sdk/pkg/client" // for v2: "github.com/optimizely/go-sdk/v2/pkg/client"

// Instantiate an Optimizely client
// Provide the sdkKey of your desired environment here
optimizelyFactory := client.OptimizelyFactory{SDKKey: "YOUR_SDK_KEY"}
client, err := optimizelyFactory.StaticClient()
if err != nil {
 // handle error
}

// Option 1 – Create a user, then set attributes.
user := client.CreateUserContext("YOUR_USER_ID", nil)
user.SetAttribute("is_logged_in", false)
user.SetAttribute("app_version", "1.3.2")

// Option 2 – Pass attributes when creating the user.
attributes := map[string]interface{}{
	"device":       "iPhone",
  "lifetime":     24738388,
  "is_logged_in": true,
  "app_version":  "4.3.0-beta",
}
user = client.CreateUserContext("YOUR_USER_ID", attributes)
import com.optimizely.ab.Optimizely;
import com.optimizely.ab.OptimizelyFactory;

// Instantiate an Optimizely client    
public class App {
    public static void main(String[] args) {
        // Provide the sdkKey of your desired environment here
        String sdkKey = "YOUR_SDK_KEY"; 
        Optimizely optimizely = OptimizelyFactory.newDefaultInstance(sdkKey);
    }
}

// Option 1 – Create a user, then set attributes.
OptimizelyUserContext user = optimizely.createUserContext("YOUR_USER_ID");
user.setAttribute("is_logged_in", false);
user.setAttribute("app_version", "1.3.2");

// Option 2 – Pass attributes when creating the user.
Map<String, Object> attributes = new HashMap<>();
attributes.put("is_logged_in", false);
attributes.put("app_version", "1.3.2");
OptimizelyUserContext user = optimizely.createUserContext("YOUR_USER_ID", attributes);
import {
  createPollingProjectConfigManager,
  createInstance,
} from "@optimizely/optimizely-sdk";

const projectConfigManager = createPollingProjectConfigManager({
  sdkKey: "YOUR_SDK_KEY",
});

const optimizely = createInstance({
  projectConfigManager,
});

// Option 1 - Create a user, then set attributes.
const user = optimizely.createUserContext('YOUR_USER_ID');
user.setAttribute('is_logged_in', false);
user.setAttribute('app_version', '1.3.2');

// Option 2 – Pass attributes when creating the user.
const attributes = {
  is_logged_in: false,
  app_version: '1.3.2'
}

const user = optimizely.createUserContext('YOUR_USER_ID', attributes);
use Optimizely\Optimizely;

// Instantiate an Optimizely client
// Provide the sdkKey of your desired environment here
$sdkKey = "YOUR_SDK_KEY";
$optimizelyClient = OptimizelyFactory::createDefaultInstance($sdkKey);

// Option 1 – Create a user, then set attributes.
$user = $optimizely->createUserContext('YOUR_USER_ID');
$user->setAttribute('is_logged_in', false);
$user->setAttribute('app_version', '1.3.2');

// Option 2 – Pass attributes when creating the user.
$attributes = array(
                'device'=>'iPhone',
                'lifetime'=> 24738388,
                'is_logged_in'=> true,
                'app_version' => '4.3.0-beta'
            );

$user = $optimizely->createUserContext('YOUR_USER_ID', $attributes);
from optimizely import optimizely
# Provide the sdkKey of your desired environment here
optimizely_client = optimizely.Optimizely('YOUR_SDK_KEY')

# Option 1 – Create a user, then set attributes. 
user = optimizely_client.create_user_context("YOUR_USER_ID")
user.set_attribute("is_logged_in", False)
user.set_attribute("app_version", "1.3.2")

# Option 2 – Pass attributes when creating the user.
attributes = {
  	"device": "iPhone",
  	"lifetime": 24738388,
  	"is_logged_in": True,
  	"app_version": "4.3.0-beta",
}

user = optimizely_client.create_user_context("YOUR_USER_ID", attributes)

user_attributes = user.get_user_attributes()
mport { OptimizelyProvider, createInstance  } from '@optimizely/react-sdk';

const optimizely = createInstance({
  sdkKey: 'YOUR_SDK_KEY',
});

// Using a function component
export default function App() {
 return (
   <OptimizelyProvider
     optimizely={optimizely}
     user={{id: 'YOUR_USER_ID'}}>
     <App />
   </OptimizelyProvider>
 );
}

// Or a class component
class App extends React.Component {
  render() {
    return (
      <OptimizelyProvider
      	optimizely={optimizely}
  			user={{id: 'YOUR_USER_ID'}}>
        <App />
      </OptimizelyProvider>
    );
  }
}
import { OptimizelyProvider, createInstance  } from '@optimizely/react-sdk';

const optimizely = createInstance({
  sdkKey: 'YOUR_SDK_KEY',
});

// using a function component
export default function App() {
 return (
   <OptimizelyProvider
     optimizely={optimizely}
     user={{id: 'YOUR_USER_ID'}}>
     <App />
   </OptimizelyProvider>
 );
}

// or a class component
class App extends React.Component {
  render() {
    return (
      <OptimizelyProvider
      	optimizely={optimizely}
  			user={{id: 'YOUR_USER_ID'}}>
        <App />
      </OptimizelyProvider>
    );
  }
}
require 'optimizely/optimizely_factory'

# Initialize an Optimizely client
# Provide the sdkKey of your desired environment here
optimizely_client = Optimizely::OptimizelyFactory.default_instance('YOUR_SDK_KEY')

# Option 1 - Create a user, then set attributes.
user = optimizely.create_user_context('YOUR_USER_ID')
user.set_attribute('is_logged_in', false)
user.set_attribute('app_version', '1.3.2')

# Option 2 – Pass attributes when creating the user.
attributes = {
  'is_logged_in' => false,
  'app_version' => '1.3.2'
}

optimizely.create_user_context('YOUR_USER_ID', attributes)
// Provide the sdkKey of your desired environment here
let optimizely = OptimizelyClient(sdkKey: "YOUR_SDK_KEY")
optimizely.start {
  // Option 1 – Create a user, then set attributes.
	let user = optimizely.createUserContext(userId: "YOUR_USER_ID")
	user.setAttribute(key: "is_logged_in", value: false)
	user.setAttribute(key: "app_version", value: "1.3.2")

	// Option 2 - Pass attributes when creating the user.
	let attributes: [String: Any] = [
  	"device": "iPhone",
  	"lifetime": 24738388,
  	"is_logged_in": true,
  	"app_version": "4.3.0-beta",
	]

	let user = optimizely.createUserContext(userId: "YOUR_USER_ID", attributes: attributes)
}

Using this approach ensures that experiment decisions and event tracking remain consistent for the user.

For information, see the SDK's user context documentation.

Recommended approach for handling multiple user IDs

🚧

Important

See See Handle user IDs in Feature Experimentation in the user documentation for important information about handling multiple user IDs.

To maintain experiment consistency, create separate user context instances for anonymous and logged-in users. Never modify the user ID in an existing user context. The following code sample demonstrates how to do this.

// To test on both anonymous journeys and logged in journeys you must use two user contexts.
// Do not change the user ID on the user context, this could change the variation the visitor sees and lead to innacurate results. 

// Create instance.
const client = createInstance({
  sdkKey: 'YOUR_SDK_KEY', // Provide the sdkKey of your desired environment here
});

// Use the optimizely visitor ID cookie here, for example, 424241b3-be1b-412a-8287-1d55a1cd9081. 
// The function is not fully developed here, it is used for example only.
const anonymousUserId = getExperimentsUserId();

// Use the logged in user ID here, for example, 123456.
// The function is not fully developed here, it is used for example only.
const customerId = getCustomerId();

// Create two separate user contexts with a logged_in attribute.
// Never swap the ID in the user context!
const anonymousUser = client.createUserContext(anonymousUserId, {logged_in: false});
const loggedInUser = client.createUserContext(customerId, {logged_in: true});

// Run experiments by default on the anonymousUser.
const sortingDecision = anonymousUser.decide('sorting_experiment');
const bannerDecision = anonymousUser.decide('banner_experiment');


// Only for omnichannel experiment use the loggedInUser, this costs an extra MAU if you are on an MAU model so document this internally.
const omnichannelDecision = loggedInUser.decide('omnichannel_experiment')
const pricingDecision = loggedInUser.decide('pricing_experiment')

    
// You must fire events for each context for the events to be correctly recorded.
loggedInUser.trackEvent('purchase');
anonymousUser.trackEvent('purchase');
# To test on both anonymous journeys and logged-in journeys, you must use two user contexts.
# Do not change the user ID on the user context, as this could change the variation the visitor sees and lead to inaccurate results.

from optimizely import optimizely

# Create instance.
client = optimizely.Optimizely(sdk_key='YOUR_SDK_KEY')  # Provide the sdkKey of your desired environment here.

# Use the optimizely visitor ID cookie here, for example, 424241b3-be1b-412a-8287-1d55a1cd9081.
# The function is not fully developed here; it is used for example only.
anonymous_user_id = get_experiments_user_id()

# Use the logged-in user ID here.
# For example, 123456.
customer_id = get_customer_id()

# Create two separate user contexts with a logged_in attribute
# Never swap the ID in the user context!
anonymous_user = client.create_user_context(anonymous_user_id, {'logged_in': False})
logged_in_user = client.create_user_context(customer_id, {'logged_in': True})

# Run experiments by default on the anonymous_user.
sorting_decision = anonymous_user.decide('sorting_experiment')
banner_decision = anonymous_user.decide('banner_experiment')

# Only for omnichannel experiments, use the logged_in_user.
# This costs an extra MAU if you are on an MAU model, so document this internally.
omnichannel_decision = logged_in_user.decide('omnichannel_experiment')
pricing_decision = logged_in_user.decide('pricing_experiment')

# You must fire events for each context for the events to be correctly recorded.
logged_in_user.track_event('purchase')
anonymous_user.track_event('purchase')