Skip to content

Commit 8d244c5

Browse files
committed
add weighting
1 parent 40eee56 commit 8d244c5

3 files changed

Lines changed: 93 additions & 14 deletions

File tree

README.md

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ Once the user has successfully completed the experiment, say paid and navigated
6666

6767
<script>
6868
Abba('Checkout')
69-
.control()
69+
.control('Control')
7070
.variant('Text: Complete Purchase', function(){
7171
$('form button').text('Complete Purchase');
7272
})
@@ -85,6 +85,38 @@ If set the `persist` option to `true`, then the experiment won't be reset once i
8585
<script>
8686
Abba('Pricing', {persist: true}).complete();
8787
</script>
88+
89+
You can set a variant weight, so some variants are used more than others:
90+
91+
Abba('My Checkout')
92+
.control('Control', {weight: 20})
93+
.variant('Variant 1', {weight: 3}, function(){
94+
$('#test').text('Variant 1 was chosen!');
95+
})
96+
.variant('Variant 2', {weight: 3}, function(){
97+
$('#test').text('Variant 2 was chosen!');
98+
})
99+
.start();
100+
101+
In the case above, the Control will be invoked 20 times more often than the other variants.
102+
103+
You can continue a previously started test using `continue()`.
104+
105+
Abba('My Checkout')
106+
.control()
107+
.variant('Variant 1', function(){
108+
$('#test').text('Variant 1 was chosen!');
109+
})
110+
.variant('Variant 2', function(){
111+
$('#test').text('Variant 2 was chosen!');
112+
})
113+
.continue();
114+
115+
Nothing will be recorded if you call `continue()` instead of `start()`. If a variant hasn't been chosen previously, nothing will be executed.
116+
117+
You can reset tests using `reset()`.
118+
119+
Abba('My Checkout').reset();
88120

89121
## Credits
90122

app/assets/javascripts/client/index.coffee

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -70,21 +70,45 @@ class @Abba
7070

7171
@endpoint = @options.endpoint or @constructor.endpoint
7272

73-
variant: (name, callback) ->
73+
variant: (name, options, callback) ->
7474
if typeof name isnt 'string'
7575
throw new Error('Variant name required')
7676

77-
@variants.push(name: name, callback: callback)
77+
if typeof options isnt 'object'
78+
callback = options
79+
options = {}
80+
81+
options.name = name
82+
options.callback = callback
83+
84+
@variants.push(options)
7885
this
7986

80-
control: (name = 'Control', callback) =>
81-
@variants.push(name: name, callback: callback, control: true)
87+
control: (name, options, callback) =>
88+
if typeof name isnt 'string'
89+
throw new Error('Variant name required')
90+
91+
if typeof options isnt 'object'
92+
callback = options
93+
options = {}
94+
95+
options.name = name
96+
options.callback = callback
97+
options.control = true
98+
99+
@variants.push(options)
100+
this
101+
102+
continue: =>
103+
# Use the same variant as before, don't record anything
104+
if variant = @getPreviousVariant()
105+
@useVariant(variant)
82106
this
83107

84108
start: (name, options = {}) =>
85109
if variant = @getPreviousVariant()
86110
# Use the same variant as before, don't record anything
87-
@chooseVariant(variant)
111+
@useVariant(variant)
88112
return this
89113

90114
if name?
@@ -95,13 +119,19 @@ class @Abba
95119
control: options.control
96120

97121
else
98-
# Or choose a random one
99-
random = Math.floor(Math.random() * @variants.length)
100-
variant = @variants[random]
122+
# Or choose a weighted random variant
123+
totalWeight = 0
124+
totalWeight += (v.weight ? 1) for v in @variants
125+
randomWeight = Math.floor(Math.random() * totalWeight)
126+
variantWeight = 0
127+
128+
for variant in @variants
129+
variantWeight += variant.weight or 0
130+
break if variantWeight >= randomWeight
101131

102132
throw new Error('No variants added') unless variant
103133
@recordStart(variant)
104-
@chooseVariant(variant)
134+
@useVariant(variant)
105135
this
106136

107137
complete: (name) =>
@@ -132,7 +162,7 @@ class @Abba
132162
getVariantForName: (name) =>
133163
(v for v in @variants when v.name is name)[0]
134164

135-
chooseVariant: (variant) =>
165+
useVariant: (variant) =>
136166
variant?.callback?()
137167
@chosen = variant
138168

public/test/start.html

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,31 @@ <h1 id="test">The control was chosen!</h1>
55

66
<script type="text/javascript" charset="utf-8">
77
Abba('My Checkout')
8-
.control()
9-
.variant('Variant 1', function(){
8+
.control('Control', {weight: 20})
9+
.variant('Variant 1', {weight: 3}, function(){
1010
$('#test').text('Variant 1 was chosen!');
1111
})
12-
.variant('Variant 2', function(){
12+
.variant('Variant 2', {weight: 3}, function(){
1313
$('#test').text('Variant 2 was chosen!');
1414
})
1515
.start();
16+
17+
// Reset test
18+
// Abba('My Checkout').reset();
19+
20+
// Continue a previously started test
21+
// Abba('My Checkout')
22+
// .control()
23+
// .variant('Variant 1', function(){
24+
// $('#test').text('Variant 1 was chosen!');
25+
// })
26+
// .variant('Variant 2', function(){
27+
// $('#test').text('Variant 2 was chosen!');
28+
// })
29+
// .continue();
30+
31+
// Chose a specific variant
32+
// Abba('My Checkout').start('Another var');
1633
</script>
1734

1835
<p>

0 commit comments

Comments
 (0)