---
title: Handle user IDs
slug: feature-experimentation/docs/handle-user-ids
docTags: 
createdAt: 2026-08-05T20:40:03.000Z
---

Feature Experimentation identifies users with user IDs and determines which variation they see in an experiment ([A/B test](docId:8pnfCv-sR37goLcxTtCPv) or [multi-armed bandit](docId\:F5-ZUIoxCu2_XRy26tO-b)) or a [flag delivery (targeted delivery)](docId:_BjMxuGwwlVrhkNcx2kzm). 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](docId\:Nyit5zVe8xXGGZu4qJao4) in the user documentation for 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](docId\:IsU8ejnD3mrkAia2mtIOA).

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.

```kotlin
// Initialize 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)
```

```java
// Initialize 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);
```

```csharp
// 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);
```

```dart
// 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);
```

```go
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)
```

```java
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);
```

```javascript
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);
```

```php
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);
```

```python
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()
```

```javascript
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'}}>
     <YourComponent />
   </OptimizelyProvider>
 );
}

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

```javascript
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'}}>
     <YourComponent />
   </OptimizelyProvider>
 );
}

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

```ruby
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)
```

```swift
// 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.

- [Android](docId\:gR9wq-XMrQQOtGcWhpyqQ)
- [C#](docId\:NMLEiJmrOW1XL9kGEplxb)
- [Flutter](docId:5k27nwFPeEn1-v7XWz1HT)
- [Go](docId\:UnFDhdqan0QQo54R4_7a3)
- [Java](docId\:AdphTGCbC7b8i3krPoZIc)
- [JavaScript](docId\:OExtupzmm3AyVp8uWgIoC) – SDK versions 6.0.0 and later.
- [JavaScript (Browser)](docId\:MXN8iOzOMT-fcdpbgwg8C) – SDK versions 5.3.5 and earlier.
- [JavaScript (Node)](docId:7WZjge5drvVl3_iYhV4IQ) – SDK versions 5.3.5 and earlier.
- [PHP](docId:6QxzVc8cTzURcLkeCt_sf)
- [Python](docId\:IQktksuBns7WFb6Xv_OVE)
- [React](docId\:jhRg84MqBcOq1Il6NaBfB)
- [React Native](docId\:BLdP069a7qBZZgxuc1lvP)
- [Ruby](docId\:EZ82PrPXF05kJvmd7OoxE)
- [Swift](docId\:MbsuKcGHantE-rEn9zRfw)

### Recommended approach for handling multiple user IDs

:::hint{type="warning"}
**Important**
See [Handle user IDs in Feature Experimentation](docId\:Nyit5zVe8xXGGZu4qJao4) 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.

```javascript
// 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 user sees and lead to inaccurate results. 

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

// Use the Optimizely user 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');
```

```python
# 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 user 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 user 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')
```
