---
title: Assign variations with bucketing ids
slug: feature-experimentation/docs/bucketing-ids
docTags: 
createdAt: 2026-08-05T20:39:56.000Z
---

By default, Optimizely assigns users to variations (in other words, [Optimizely buckets users](https://www.optimizely.com/optimization-glossary/bucket-testing/)) based on submitted user IDs. You can change this behavior by including a bucketing ID.

With a bucketing ID, you decouple user bucketing from user identification. Users with the same bucketing ID are put into the same bucket and exposed to the same variation. The bucketing ID is the seed of the hash value used to assign the user to a variation. Users with the same bucketing ID share the same hash value, exposing them to the same variation. For information, see [How bucketing works](docId\:eH-UMm_rOn_GdGDGLV6__).

Bucketing IDs are implemented as a reserved [attribute](docId\:o2PfkAKSRc0TOAzllcRQN) that you can use when activating an experiment or evaluating a feature flag.

Using a bucketing ID does not affect the user ID. Event data submissions continue to include user IDs. Except for assigning users to specific variations, flags that rely on user IDs behave the same even if there is a separate bucketing ID. If you do not pass a bucketing ID to the `attributes` parameter, users are bucketed by user IDs by default.

:::hint{type="info"}
**Note**
Bucketing IDs

- are not persisted.
- are only supported for [A/B tests](docId:8pnfCv-sR37goLcxTtCPv) and [multi-armed bandit optimizations](docId\:F5-ZUIoxCu2_XRy26tO-b).
:::

## Use case

Bucketing IDs provide a consistent identifier for user bucketing across sessions.

### Shared device example

For example, you run experiments on a shared device like an Apple TV. Multiple users in a household can use the same device.

You want to ensure that you assign experiment variations based on the device instead of the individual user. If Optimizely bucketed according to individual users, then users on the same device may get different experiences, which may threaten the experiment's validity.

By using a unique device identifier as the bucketing ID, you can ensure that all users on the same shared device experience the same experiment variation. You can still [track events](docId:3kGIZlCkODJIOJuT3bdWo) like conversions for each individual user by creating user contexts using unique user identifiers.

See the following SDK's guide on creating a user context:

- [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)

## Example implementation

The following examples show how to include a bucketing ID. Send the `$opt_bucketing_id` attribute in the `attributes` parameter of the `optimizelyUserContext`.

### Client-side SDKs

```java
import java.util.UUID;
import com.optimizely.ab.android.sdk.OptimizelyClient;

String experimentKey = "my_experiment";
// for simplicity's sake, we are just using a generated user id
String userId = UUID.randomUUID().toString();

// Option 1 – Create a user, then set the attributes
OptimizelyUserContext user;
user = optimizelyClient.createUserContext(userId);
user.setAttribute("ad_source", "my_campaign");
user.setAttribute("browser", "chrome");
user.setAttribute("$opt_bucketing_id", "bucketingId123");

// Option 2 – Pass attributes when creating the user 
Map<String,String> attributes = new HashMap<String,String>();
attributes.put("ad_source", "my_campaign");
attributes.put("browser", "chrome");
// bucketing id can be passed in alone or with other attributes
attributes.put("$opt_bucketing_id", "bucketingId123");
user = optimizelyClient.createUserContext(userId, attributes);
```

```kotlin
import java.util.UUID
import com.optimizely.ab.android.sdk.OptimizelyClient

val experimentKey = "my_experiment"
// for simplicity's sake, we are just using a generated user id
val userId = UUID.randomUUID().toString()

// Option 1 – Create a user, then set attributes
var user: OptimizelyUserContext?
user = optimizelyClient.createUserContext(userId)
user.setAttribute("ad_source", "my_campaign")
user.setAttribute("browser", "chrome")
user.setAttribute("$opt_bucketing_id", "bucketingId123")

// Option 2 – Pass attributes when creating the user
val attributes: MutableMap<String, Any> = HashMap()
attributes["ad_source"] = "my_campaign"
attributes["browser"] = "chrome"
attributes["$opt_bucketing_id"] = "bucketingId123"
user = optimizelyClient.createUserContext(userId, attributes)
```

```dart
import 'package:uuid/uuid.dart';

void main() {
  var experimentKey = "my_experiment";
  // for simplicity's sake, we are just using a generated user id
  var userId = Uuid().v4();
}
// Option 1 – Create a user, then set attributes
var user = await flutterSDK.createUserContext(userId);
var attributes = <String, dynamic>{};
attributes["ad_source"] = "my_campaign";
attributes["app_version"] = "1.3.2";
attributes["$opt_bucketing_id"] = "bucketingId123";
user!.setAttributes(attributes);

// Option 2 – Pass attributes when creating the user
var attributes = <String, dynamic>{};
attributes["ad_source"] = "my_campaign";
attributes["app_version"] = "1.3.2";
attributes["$opt_bucketing_id"] = "bucketingId123";
var optimizelyUserContext = await optimizelyClient.createUserContext(userId: userId, attributes: attributes);
```

```javascript
const experimentKey = 'my_experiment';
// For simplicity's sake, we are just using a hardcoded user id
const userId = 'user123';

// Option 1 – Create a user, then set attributes
const user = optimizely.createUserContext(userId);
user.setAttribute('is_logged_in', false);
user.setAttribute('app_version', '1.3.2');
user.setAttribute('$opt_bucketing_id', 'bucketingId123');

// Option 2 – Pass attributes when creating the user
const attributes = {
  'ad_source': 'my_campaign',  
  'device': 'iphone',
  '$opt_bucketing_id': 'bucketingId123'
}
const user = optimizely.createUserContext(userId, attributes);
```

```javascript
import { createInstance, OptimizelyProvider } from '@optimizely/react-sdk'

const optimizely = createInstance({
  sdkKey: '<YOUR_SDK_KEY>'
})

export default function App() {
  return (
    <OptimizelyProvider
      optimizely={optimizely}
      user={{
        id: 'user123',
        attributes: { $opt_bucketing_id: 'bucketingId123' }
      }}
    >
      // Components
    </OptimizelyProvider>
  )
}
```

```javascript
import { createInstance, OptimizelyProvider } from '@optimizely/react-sdk'

const optimizely = createInstance({
  sdkKey: '<YOUR_SDK_KEY>'
})

export default function App() {
  return (
    <OptimizelyProvider
      optimizely={optimizely}
      user={{
        id: 'user123',
        attributes: { $opt_bucketing_id: 'bucketingId123' }
      }}
    >
      // Components
    </OptimizelyProvider>
  )
}
```

```swift
let optimizely = OptimizelyClient(sdkKey: "sdk-key")
let experimentKey = "myExperiment"
// For simplicity's sake, we are just using a hardcoded user id
let userId = "user123"

optimizely.start {
  // Option 1 – Create a user, then set attributes
	let user = optimizely.createUserContext(userId: userId)
	user.setAttribute(key: "is_logged_in", value: false)
	user.setAttribute(key: "app_version", value: "1.3.2")
  user.setAttribute(key: "$opt_bucketing_id", value: "bucketingId123")

	// 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",
    "$opt_bucketing_id": "bucketingId123",
	]

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

### Server-side SDKs

```csharp
using OptimizelySDK;
using OptimizelySDK.Entity;

var optimizelyClient = new Optimizely(datafile);

var experimentKey = "my_experiment";
// for simplicity's sake, we are just using a hardcoded user id
var userId = "user123";

// Option 1 – Create a user, then set attributes
var user = optimizely.CreateUserContext(userId);
user.SetAttribute("AD_SOURCE", "my_campaign");
user.SetAttribute("BROWSER", "chrome");
user.SetAttribute("$opt_bucketing_id", "bucketingId123");

// option 2: pass attributes when creating the user
var attributes = new UserAttributes
{
  { "AD_SOURCE", "my_campaign" },
  { "BROWSER", "chrome" },
  { "$opt_bucketing_id", "bucketingId123" }
};
var user = optimizely.CreateUserContext(userId, attributes);
```

```go
import "github.com/optimizely/go-sdk/pkg/client" // for v2: "github.com/optimizely/go-sdk/v2/pkg/client"

experimentKey := "my_experiment"
// for simplicity's sake, we are just using a hardcoded user id
userId := "user123"

// Option 1: Create a user, then set attributes
user := client.CreateUserContext(userId, nil)
user.SetAttribute("ad_source", "my_campaign")
user.SetAttribute("app_version", "1.3.2")
user.SetAttribute("$opt_bucketing_id", "bucketingId123")

// Option 2: Pass attributes when creating the user
attributes := map[string]interface{}{
	"ad_source":          "my_campaign",
  "app_version":        "1.3.2",
  "is_logged_in":       true,
  "$opt_bucketing_id":  "bucketingId123",
}
user = client.CreateUserContext(userId, attributes)
```

```java
import java.util.UUID;

import com.optimizely.ab.Optimizely;
import com.optimizely.ab.config.Variation;

String experimentKey = "my_experiment";
// For simplicity's sake, we are just using a generated user id
String userId = UUID.randomUUID().toString();

// Option 1 – Create a user, then set the attributes
OptimizelyUserContext user = optimizelyClient.createUserContext(userId);
user.setAttribute("ad_source", "my_campaign");
user.setAttribute("browser", "chrome");
user.setAttribute("$opt_bucketing_id", "bucketingId123");

// Option 2 – Pass attributes when creating the user 
Map<String, Object> attributes = new HashMap<>();
attributes.put("ad_source", "my_campaign");
attributes.put("browser", "chrome");
// Bucketing ID can be passed in alone or with other attributes
attributes.put("$opt_bucketing_id", "bucketingId123");
OptimizelyUserContext user = optimizely.createUserContext(userId, attributes);
```

```php
$experimentKey = 'my_experiment';
// For simplicity's sake, we are just using a hardcoded user id
$userId = 'user123';

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

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

```python
from optimizely import optimizely
optimizely_client = optimizely.Optimizely("<YOUR_SDK_KEY>")

experiment_key = "my_experiment"
# For simplicity's sake, we are just using a hardcoded user id
user_id = "user123"

# Option 1: Create a user, then set attributes
user = optimizely_client.create_user_context(user_id)
user.set_attribute("is_logged_in", False)
user.set_attribute("app_version", "1.3.2")
user.set_attribute("$opt_bucketing_id", "bucketingId123")

# Option 2 – Pass attributes when creating the user
attributes = {
  	"device": "iPhone",
  	"lifetime": 24738388,
  	"is_logged_in": True,
  	"$opt_bucketing_id": "bucketingId123"
}
user = optimizely_client.create_user_context(user_id, attributes)
```

```ruby
experiment_key = 'my_experiment'
# For simplicity's sake, we are just using a hardcoded user id
user_id = 'user123'
attributes = {
    'device' => 'iphone',
    'ad_source' => 'my_campaign',
    '$opt_bucketing_id' => 'bucketingId123'
};

# Option 1 – Create a user, then set attributes
user = optimizely.create_user_context(user_id)
user.set_attribute('is_logged_in', false)
user.set_attribute('app_version', '1.3.2')
user.set_attribute('$opt_bucketing_id', 'bucketingId123')


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

optimizely.create_user_context(user_id, attributes)
```

```javascript
const experimentKey = 'my_experiment';
// For simplicity's sake, we are just using a hardcoded user id
const userId = 'user123';

// Option 1 – Create a user, then set attributes
const user = optimizely.createUserContext(userId);
user.setAttribute('is_logged_in', false);
user.setAttribute('app_version', '1.3.2');
user.setAttribute('$opt_bucketing_id', 'bucketingId123');

// Option 2 – Pass attributes when creating the user
const attributes = {
  'ad_source': 'my_campaign',  
  'device': 'iphone',
  '$opt_bucketing_id': 'bucketingId123'
}
const user = optimizely.createUserContext(userId, attributes);
```

For information about `optimizelyUserContext`, see the SDK's reference:

- [Android](docId\:gR9wq-XMrQQOtGcWhpyqQ)
- [C#](docId\:NMLEiJmrOW1XL9kGEplxb)
- [Flutter](docId:5k27nwFPeEn1-v7XWz1HT)
- [Go](docId\:UnFDhdqan0QQo54R4_7a3)
- [Java](docId\:AdphTGCbC7b8i3krPoZIc)
- [JavaScript v6+](docId\:OExtupzmm3AyVp8uWgIoC)
- [JavaScript (Browser)](docId\:MXN8iOzOMT-fcdpbgwg8C) – SDK versions 5.3.5 and below
- [JavaScript (Node)](docId:7WZjge5drvVl3_iYhV4IQ) – SDK versions 5.3.5 and below
- [PHP](docId:6QxzVc8cTzURcLkeCt_sf)
- [Python](docId\:IQktksuBns7WFb6Xv_OVE)
- [React](docId\:rCHtKgccqa7z1Fd5pLkKB)
- [React Native](docId\:nZHEmzX-G_Fs-aXE-0lYr)
- [Ruby](docId\:EZ82PrPXF05kJvmd7OoxE)
- [Swift](docId\:MbsuKcGHantE-rEn9zRfw)
