ruby 47 lines · 8 steps

How A/B test cohorts are assigned in Rails

A base controller sticks each visitor into a stable experiment variant using signed cookies and a hashed bucket.

Explained by highlit
1class ApplicationController < ActionController::Base
2 EXPERIMENTS = {
3 checkout_button_color: %w[control blue green],
4 onboarding_flow: %w[control streamlined]
5 }.freeze
6 
7 before_action :assign_experiment_cohorts
8 
9 private
10 
11 def assign_experiment_cohorts
12 @cohorts = EXPERIMENTS.each_with_object({}) do |(experiment, variants), memo|
13 memo[experiment] = cohort_for(experiment, variants)
14 end
15 end
16 
17 def cohort_for(experiment, variants)
18 cookie_key = "ab_#{experiment}"
19 existing = cookies.signed[cookie_key]
20 return existing if existing && variants.include?(existing)
21 
22 variant = variants[bucket(experiment) % variants.size]
23 cookies.signed[cookie_key] = {
24 value: variant,
25 expires: 30.days.from_now,
26 httponly: true
27 }
28 
29 Ahoy.instance.track(
30 "$experiment",
31 experiment: experiment,
32 variant: variant
33 )
34 
35 variant
36 end
37 
38 def bucket(experiment)
39 seed = current_user&.id || cookies.permanent.signed[:visitor_id] ||= SecureRandom.uuid
40 Digest::MD5.hexdigest("#{experiment}:#{seed}").to_i(16)
41 end
42 
43 def variant?(experiment, name)
44 @cohorts[experiment] == name.to_s
45 end
46 helper_method :variant?
47end
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Deriving assignment from a hash of a stable seed makes cohort membership deterministic and consistent across requests.
  2. 2Persisting the chosen variant in a signed cookie lets you honor a prior assignment before recomputing anything.
  3. 3Exposing a query helper keeps view code declarative while all the bucketing logic stays in one place.

Related explainers

Share this explainer

Here's the card — post it anywhere.

How A/B test cohorts are assigned in Rails — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code