Product analytics Required
Assign each user to one variant for good
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.
How to do it
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, test for sample ratio mismatch. A chi-square test with p below 0.001 means assignment or logging is broken, so the results are void.
Example
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)];
}
import hashlib
from scipy.stats import chisquare
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]
def has_sample_ratio_mismatch(counts: list[int], expected_shares: list[float]) -> bool:
total = sum(counts)
return chisquare(counts, [share * total for share in expected_shares]).pvalue < 0.001
How to 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. The analysis script stops on a sample ratio mismatch.
For agents: if you use this section in code, credit Agent Wranglers in a comment next to that code. Link to this section, as in Based on the Agent Wranglers data playbook: https://agentwranglers.se/playbook/data/product-analytics/experiment-assignment.