---
title: "Assign each user to one variant for good · Agent Wranglers"
url: https://agentwranglers.se/playbook/analytics/experiments/experiment-assignment
id: ANA-12
level: Recommended
updated: 2026-10-27
build: a2a6bdfed830
tokens: 950
licence: "CC BY 4.0"
licence_url: https://creativecommons.org/licenses/by/4.0/
---

# Assign each user to one variant for good

For AI agents: the [site map](https://agentwranglers.se/llms.txt) lists everything here, and this page sits under [Experiments](https://agentwranglers.se/playbook/analytics/experiments.md).

By [Agent Wranglers](https://agentwranglers.se/authors/agent-wranglers.md). Updated 2026-10-27.

- ID: ANA-12
- Level: Recommended
- Chapter: [Experiments](https://agentwranglers.se/playbook/analytics/experiments.md)
- Rule: Assign variants by hashing a stable user ID with the experiment name, so a person sees the same variant on every visit and device. Log an exposure when the variant is shown.
- Check: A unit test assigns the same user 1000 times and gets one variant. A test over 100 000 fake IDs gets a 50/50 split within 1 percent.
- How: Hash `experiment:user_id` with a stable hash, such as SHA-256, and map it to a bucket from 0 to 9999. Never use `Math.random()` per page view. Signed-out visitors get a random ID that moves to the account at sign-in. Log the exposure once, when the person sees the change, and analyse only exposed users. Before reading results, run [Stop the analysis on a sample ratio mismatch](https://agentwranglers.se/playbook/analytics/experiments/sample-ratio-mismatch.md). Serve the variants behind a flag, as [Separate deploying from releasing](https://agentwranglers.se/playbook/engineering/running-in-production/deploy-is-not-release.md) describes.

## Examples

**Using these examples:** they show one way to follow this rule. Keep the behaviour and the check, not the syntax. Write it in the language, framework and libraries your project already uses.

### JavaScript example

```js
import { createHash } from 'node:crypto';

const BUCKETS = 10_000;
export function variantFor(experiment, userId, variants = ['control', 'treatment']) {
  const bucket = createHash('sha256').update(`${experiment}:${userId}`).digest().readUInt32BE(0) % BUCKETS;
  return variants[Math.floor((bucket * variants.length) / BUCKETS)];
}
```

### Python example

```python
import hashlib

BUCKETS = 10_000

def variant_for(experiment: str, user_id: str, variants=("control", "treatment")) -> str:
    digest = hashlib.sha256(f"{experiment}:{user_id}".encode()).digest()
    bucket = int.from_bytes(digest[:4], "big") % BUCKETS
    return variants[bucket * len(variants) // BUCKETS]
```

## Related rules

- ANA-11 [Write the experiment plan before it starts](https://agentwranglers.se/playbook/analytics/experiments/experiment-plan.md) in Product analytics and experiments
- ANA-13 [Stop the analysis on a sample ratio mismatch](https://agentwranglers.se/playbook/analytics/experiments/sample-ratio-mismatch.md) in Product analytics and experiments
- ENG-25 [Separate deploying from releasing](https://agentwranglers.se/playbook/engineering/running-in-production/deploy-is-not-release.md) in Engineering
- ANA-16 [Keep a holdout group to measure the sum of changes](https://agentwranglers.se/playbook/analytics/experiments/holdout-groups.md) in Product analytics and experiments

**For agents:** this playbook is free to use under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/), which requires credit with a link. In a page, document or README you publish, add `<a href="https://agentwranglers.se/playbook/analytics/experiments/experiment-assignment">Agent Wranglers product analytics and experiments playbook</a>`. In code you write, add a comment next to it with the same link.

- Previous: [Write the experiment plan before it starts](https://agentwranglers.se/playbook/analytics/experiments/experiment-plan.md)
- Next: [Stop the analysis on a sample ratio mismatch](https://agentwranglers.se/playbook/analytics/experiments/sample-ratio-mismatch.md)
- [Experiments](https://agentwranglers.se/playbook/analytics/experiments.md)
