trailguide 0.2.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +191 -293
  3. data/app/views/trail_guide/admin/experiments/_btn_join.html.erb +1 -1
  4. data/app/views/trail_guide/admin/experiments/_header.html.erb +3 -3
  5. data/config/initializers/admin.rb +19 -0
  6. data/config/initializers/experiment.rb +261 -0
  7. data/config/initializers/trailguide.rb +6 -279
  8. data/lib/trail_guide/adapters.rb +2 -0
  9. data/lib/trail_guide/adapters/experiments.rb +8 -0
  10. data/lib/trail_guide/adapters/experiments/redis.rb +48 -0
  11. data/lib/trail_guide/adapters/participants/cookie.rb +1 -0
  12. data/lib/trail_guide/adapters/participants/unity.rb +9 -1
  13. data/lib/trail_guide/adapters/variants.rb +8 -0
  14. data/lib/trail_guide/adapters/variants/redis.rb +52 -0
  15. data/lib/trail_guide/admin/engine.rb +1 -0
  16. data/lib/trail_guide/algorithms.rb +4 -0
  17. data/lib/trail_guide/algorithms/algorithm.rb +29 -0
  18. data/lib/trail_guide/algorithms/bandit.rb +9 -18
  19. data/lib/trail_guide/algorithms/distributed.rb +8 -15
  20. data/lib/trail_guide/algorithms/random.rb +2 -12
  21. data/lib/trail_guide/algorithms/static.rb +34 -0
  22. data/lib/trail_guide/algorithms/weighted.rb +5 -17
  23. data/lib/trail_guide/catalog.rb +79 -35
  24. data/lib/trail_guide/config.rb +2 -4
  25. data/lib/trail_guide/engine.rb +2 -1
  26. data/lib/trail_guide/experiments/base.rb +41 -24
  27. data/lib/trail_guide/experiments/combined_config.rb +4 -0
  28. data/lib/trail_guide/experiments/config.rb +59 -30
  29. data/lib/trail_guide/experiments/participant.rb +4 -2
  30. data/lib/trail_guide/helper.rb +4 -216
  31. data/lib/trail_guide/helper/experiment_proxy.rb +160 -0
  32. data/lib/trail_guide/helper/helper_proxy.rb +62 -0
  33. data/lib/trail_guide/metrics/config.rb +2 -0
  34. data/lib/trail_guide/metrics/goal.rb +17 -15
  35. data/lib/trail_guide/participant.rb +10 -2
  36. data/lib/trail_guide/unity.rb +17 -8
  37. data/lib/trail_guide/variant.rb +15 -11
  38. data/lib/trail_guide/version.rb +2 -2
  39. metadata +13 -3
@@ -3,7 +3,7 @@
3
3
  <%= link_to trail_guide_admin.leave_experiment_path(experiment.experiment_name), class: "btn btn-sm btn-outline-secondary", method: :put, data: {toggle: :tooltip}, title: 'leave this cohort' do %>
4
4
  <span class="fas fa-sign-out-alt fa-flip-horizontal" />
5
5
  <% end %>
6
- <% elsif !experiment.calibrating? && !experiment.winner? && experiment.configuration.store_participation? && (!experiment.is_combined? || (!participant.participating?(experiment.parent) || participant.variant(experiment.parent).name == variant.name)) %>
6
+ <% elsif !experiment.calibrating? && !experiment.winner? && experiment.configuration.sticky_assignment? && (!experiment.is_combined? || (!participant.participating?(experiment.parent) || participant.variant(experiment.parent).name == variant.name)) %>
7
7
  <%= link_to trail_guide_admin.join_experiment_path(experiment.experiment_name, variant.name), class: "btn btn-sm btn-secondary", method: :put, data: {toggle: :tooltip}, title: 'join this cohort' do %>
8
8
  <span class="fas fa-sign-in-alt" />
9
9
  <% end %>
@@ -31,9 +31,9 @@
31
31
  <% if experiment.groups.count > 0 %>
32
32
  <p class="text-muted" style="padding: 0; margin: 0;">
33
33
  <span class="fas fa-th-large" data-toggle="tooltip" title="experiment groups"></span>
34
- <% experiment.groups.each do |group| %>
35
- <%= link_to group.to_s.humanize.titleize, trail_guide_admin.group_path(group), class: "text-muted" %>
36
- <% end %>
34
+ <%= raw(experiment.groups.map do |group| %>
35
+ <% link_to group.to_s.humanize.titleize, trail_guide_admin.group_path(group), class: "text-muted" %>
36
+ <% end.join(', ')) %>
37
37
  </p>
38
38
  <% end %>
39
39
  </div>
@@ -0,0 +1,19 @@
1
+ # admin ui configuration
2
+ #
3
+ TrailGuide::Admin.configure do |config|
4
+ # display title for admin UI
5
+ #
6
+ config.title = 'TrailGuide'
7
+
8
+ # display subtitle for admin UI
9
+ #
10
+ config.subtitle = 'Experiments and A/B Tests'
11
+
12
+ # request parameter can be used to "peek" at results even before an
13
+ # experiment's target_sample_size has been hit if one is configured
14
+ #
15
+ # if you set this to nil, admins will not be able to peek at experiment
16
+ # results until the target sample size is hit or the experiment is stopped
17
+ #
18
+ config.peek_parameter = nil
19
+ end
@@ -0,0 +1,261 @@
1
+ # base experiment configuration
2
+ #
3
+ TrailGuide::Experiment.configure do |config|
4
+ # the default algorithm to use for new experiments
5
+ config.algorithm = :distributed
6
+
7
+ # whether or not experiments must be started manually
8
+ #
9
+ # true experiments must be started manually via the admin UI or console
10
+ # false experiments will start the first time they're encountered by a user
11
+ config.start_manually = true
12
+
13
+ # whether or not participants will be reset upon conversion
14
+ #
15
+ # true participants will only be entered into the experiment once, and the
16
+ # variant group they belong to is sticky for the duration
17
+ # false participants will be reset upon conversion and be able to re-enter
18
+ # the experiment if they encounter it again
19
+ config.reset_manually = true
20
+
21
+ # whether or not individual assignment is sticky when returning a variant
22
+ #
23
+ # this can be useful if you are using a custom, content-based algorithm where
24
+ # the variant is determined by content rather than user bucketing, and you
25
+ # want to treat participation more like impressions (i.e. for seo experiments)
26
+ #
27
+ # when this option is set to false, conversions will always be tracked against
28
+ # the last variant that the participant was served
29
+ #
30
+ # true participation is incremented the first time a participant is
31
+ # enrolled, and the participant is assigned their selection for future
32
+ # reference, stored via the configured participant adapter
33
+ # false participation will be incremented every time a variant is selected,
34
+ # and the participant will not be forced into a bucket
35
+ config.sticky_assignment = true
36
+
37
+ # whether or not to enter participants into a variant when using the override
38
+ # parameter to preview variants
39
+ #
40
+ # true using overrides to preview experiments will enter participants into
41
+ # that variant group
42
+ # false using overrides to preview experiments will not enter participants
43
+ # into the experment (won't persist their variant group)
44
+ config.store_override = false
45
+
46
+ # whether or not we track participants when using the override parameter to
47
+ # preview variants
48
+ #
49
+ # true using overrides to preview experiments will increment the
50
+ # participant count for the override variant
51
+ # false using overrides to preview experiments will not increment the
52
+ # participant count for the override variant
53
+ config.track_override = false
54
+
55
+ # whether or not to continue tracking conversions after a winner has been
56
+ # selected in order to continue monitoring performance of the variant
57
+ #
58
+ # true continues to track conversions after a winner has been selected (as
59
+ # long as the experiment is still running)
60
+ # false all conversion and participation tracking stops once a winner has
61
+ # been selected
62
+ config.track_winner_conversions = false
63
+
64
+ # whether or not to allow multiple conversions of the same goal, or default
65
+ # conversion if no goals are defined
66
+ #
67
+ # true tracks multiple participant conversions for the same goal as long
68
+ # as they haven't been reset (see config.reset_manually)
69
+ # false prevents tracking multiple conversions for a single participant
70
+ config.allow_multiple_conversions = false
71
+
72
+ # whether or not to allow participants to convert for multiple defined goals
73
+ #
74
+ # true allows participants to convert more than one goal as long as they
75
+ # haven't been reset (see config.reset_manually)
76
+ # false prevents converting to multiple goals for a single participant
77
+ config.allow_multiple_goals = false
78
+
79
+ # whether or not to enable calibration before an experiment is started - the
80
+ # participants and conversions will be tracked for your control group while
81
+ # an experiment remains unstarted, which can be useful for gathering a
82
+ # baseline conversion rate if you don't already have one
83
+ #
84
+ # control is always returned for unstarted experiments by default, and this
85
+ # configuration only affects whether or not to track metrics
86
+ #
87
+ # this setting only applies when start_manually is also true
88
+ #
89
+ # true metrics for participation and conversion will be tracked for the
90
+ # control group until the experiment is started
91
+ # false metrics will not be tracked while the experiment remains unstarted
92
+ config.enable_calibration = false
93
+
94
+ # whether or not to skip the request filtering for this experiment - can be
95
+ # useful when defining content-based experiments with custom algorithms which
96
+ # bucket participants strictly based on additional content metadata and you
97
+ # want to expose those variants to crawlers and bots
98
+ #
99
+ # true requests that would otherwise be filtered based on your
100
+ # TrailGuide.configuration.request_filter config will instead be
101
+ # allowed through to this experiment
102
+ # false default behavior, requests will be filtered based on your config
103
+ config.skip_request_filter = false
104
+
105
+ # whether or not this experiment can be resumed after it's stopped - allows
106
+ # temporarily "pausing" an experiment then resuming it without losing metrics
107
+ #
108
+ # true this experiment can be paused and resumed
109
+ # false this experiment can only be stopped and reset/restarted
110
+ config.can_resume = false
111
+
112
+ # set a default target sample size for all experiments - this will prevent
113
+ # metrics and stats from being displayed in the admin UI until the sample size
114
+ # is reached or the experiment is stopped
115
+ #
116
+ # config.target_sample_size = nil
117
+
118
+ # callback when connecting to redis fails and trailguide falls back to always
119
+ # returning control variants
120
+ config.on_redis_failover = -> (experiment, error) do
121
+ TrailGuide.logger.error error
122
+ end
123
+
124
+ # callback on experiment start, either manually via UI/console or
125
+ # automatically depending on config.start_manually, can be used for logging,
126
+ # tracking, etc.
127
+ #
128
+ # context may or may not be present depending on how you're triggering the
129
+ # action - if you're using the admin, this will be the admin controller
130
+ # context, if you're in a console you have the option to pass a context to
131
+ # `experiment.start!` or not
132
+ #
133
+ # config.on_start = -> (experiment, context) { ... }
134
+
135
+ # callback on experiment schedule manually via UI/console, can be used for logging,
136
+ # tracking, etc.
137
+ #
138
+ # experiments can only be scheduled if config.start_manually is true
139
+ #
140
+ # context may or may not be present depending on how you're triggering the
141
+ # action - if you're using the admin, this will be the admin controller
142
+ # context, if you're in a console you have the option to pass a context to
143
+ # `experiment.schedule!` or not
144
+ #
145
+ # config.on_schedule = -> (experiment, start_at, stop_at, context) { ... }
146
+
147
+ # callback on experiment stop manually via UI/console, can be used for
148
+ # logging, tracking, etc.
149
+ #
150
+ # context may or may not be present depending on how you're triggering the
151
+ # action - if you're using the admin, this will be the admin controller
152
+ # context, if you're in a console you have the option to pass a context to
153
+ # `experiment.stop!` or not
154
+ #
155
+ # config.on_stop = -> (experiment, context) { ... }
156
+
157
+ # callback on experiment pause manually via UI/console, can be used for
158
+ # logging, tracking, etc.
159
+ #
160
+ # context may or may not be present depending on how you're triggering the
161
+ # action - if you're using the admin, this will be the admin controller
162
+ # context, if you're in a console you have the option to pass a context to
163
+ # `experiment.pause!` or not
164
+ #
165
+ # config.on_pause = -> (experiment, context) { ... }
166
+
167
+ # callback on experiment resume manually via UI/console, can be used for
168
+ # logging, tracking, etc.
169
+ #
170
+ # context may or may not be present depending on how you're triggering the
171
+ # action - if you're using the admin, this will be the admin controller
172
+ # context, if you're in a console you have the option to pass a context to
173
+ # `experiment.resume!` or not
174
+ #
175
+ # config.on_resume = -> (experiment, context) { ... }
176
+
177
+ # callback on experiment delete manually via UI/console, can be used for
178
+ # logging, tracking, etc. - will also be triggered by a reset
179
+ #
180
+ # context may or may not be present depending on how you're triggering the
181
+ # action - if you're using the admin, this will be the admin controller
182
+ # context, if you're in a console you have the option to pass a context to
183
+ # `experiment.delete!` or not
184
+ #
185
+ # config.on_delete = -> (experiment, context) { ... }
186
+
187
+ # callback on experiment reset manually via UI/console, can be used for
188
+ # logging, tracking, etc. - will also trigger any on_delete callbacks
189
+ #
190
+ # context may or may not be present depending on how you're triggering the
191
+ # action - if you're using the admin, this will be the admin controller
192
+ # context, if you're in a console you have the option to pass a context to
193
+ # `experiment.reset!` or not
194
+ #
195
+ # config.on_reset = -> (experiment, context) { ... }
196
+
197
+ # callback when a winner is selected manually via UI/console, can be used for
198
+ # logging, tracking, etc.
199
+ #
200
+ # context may or may not be present depending on how you're triggering the
201
+ # action - if you're using the admin, this will be the admin controller
202
+ # context, if you're in a console you have the option to pass a context to
203
+ # `experiment.declare_winner!` or not
204
+ #
205
+ # config.on_winner = -> (experiment, winner, context) { ... }
206
+
207
+
208
+ # callback when a participant is entered into a variant for the first time,
209
+ # can be used for logging, tracking, etc.
210
+ #
211
+ # config.on_choose = -> (experiment, variant, participant, metadata) { ... }
212
+
213
+ # callback every time a participant is returned a variant in the experiment,
214
+ # can be used for logging, tracking, etc.
215
+ #
216
+ # config.on_use = -> (experiment, variant, participant, metadata) { ... }
217
+
218
+ # callback when a participant converts for a variant in the experiment, can be
219
+ # used for logging, tracking, etc.
220
+ #
221
+ # config.on_convert = -> (experiment, checkpoint, variant, participant, metadata) { ... }
222
+
223
+
224
+ # callback that can short-circuit participation based on your own logic, which
225
+ # gets called *after* all the core engine checks (i.e. that the user is
226
+ # not excluded or already participating, etc.)
227
+ #
228
+ # `allowed` will be the value returned by any previous callbacks in the chain
229
+ #
230
+ # should return true or false
231
+ #
232
+ # config.allow_participation = -> (experiment, allowed, participant, metadata) { ... return true }
233
+
234
+
235
+ # callback that can short-circuit conversion based on your own logic, which
236
+ # gets called *after* all the core engine checks (i.e. that the user is
237
+ # participating in the experiment, is within the bounds of the experiment
238
+ # configuration for allow_multiple_*, etc.)
239
+ #
240
+ # `allowed` will be the value returned by any previous callbacks in the chain
241
+ #
242
+ # should return true or false
243
+ #
244
+ # config.allow_conversion = -> (experiment, allowed, checkpoint, variant, participant, metadata) { ... return true }
245
+
246
+
247
+ # callback that can be used to modify the rollout of a selected winner - for
248
+ # example you could use a custom algorithm or even something like the flipper
249
+ # gem to do a "feature rollout" from your control variant to your winner for
250
+ # all users
251
+ #
252
+ # be aware that when using this alongside track_winner_conversions, whatever
253
+ # variant is returned from this callback chain is what will be tracked for
254
+ # participation and conversion as long as the experiment is still running
255
+ #
256
+ # `winner` will be the variant returned by any previous callbacks in the chain
257
+ #
258
+ # must return an experiment variant
259
+ #
260
+ # config.rollout_winner = -> (experiment, winner, participant) { return winner }
261
+ end
@@ -4,6 +4,12 @@ TrailGuide.configure do |config|
4
4
  # logger object
5
5
  config.logger = Rails.logger
6
6
 
7
+ # paths where trailguide will look for experiment configs and classes, each
8
+ # can be configured with multiple paths
9
+ config.paths.configs << 'config/experiments.*'
10
+ config.paths.configs << 'config/experiments/**/*'
11
+ config.paths.classes << 'app/experiments/**/*.rb'
12
+
7
13
  # url string or initialized Redis object
8
14
  config.redis = ENV['REDIS_URL']
9
15
 
@@ -117,282 +123,3 @@ TrailGuide.configure do |config|
117
123
  is_filtered_ip_address?
118
124
  end
119
125
  end
120
-
121
- # base experiment configuration
122
- #
123
- TrailGuide::Experiment.configure do |config|
124
- # the default algorithm to use for new experiments
125
- config.algorithm = :weighted
126
-
127
- # whether or not experiments must be started manually
128
- #
129
- # true experiments must be started manually via the admin UI or console
130
- # false experiments will start the first time they're encountered by a user
131
- config.start_manually = true
132
-
133
- # whether or not participants will be reset upon conversion
134
- #
135
- # true participants will only be entered into the experiment once, and the
136
- # variant group they belong to is sticky for the duration
137
- # false participants will be reset upon conversion and be able to re-enter
138
- # the experiment if they encounter it again
139
- config.reset_manually = true
140
-
141
- # whether or not to store individual participation when returning a variant
142
- #
143
- # this can be useful if you are using a custom, content-based algorithm where
144
- # the variant is determined by content rather than user bucketing, and you
145
- # want to treat participation more like impressions (i.e. for seo experiments)
146
- #
147
- # true participation is incremented the first time a participant is
148
- # enrolled, and the participant is assigned their selection for future
149
- # reference, stored via the configured participant adapter
150
- # false participation will be incremented every time a variant is returned,
151
- # and the participant will not have their assignment stored
152
- config.store_participation = true
153
-
154
- # whether or not to enter participants into a variant when using the override
155
- # parameter to preview variants
156
- #
157
- # true using overrides to preview experiments will enter participants into
158
- # that variant group
159
- # false using overrides to preview experiments will not enter participants
160
- # into the experment (won't persist their variant group)
161
- config.store_override = false
162
-
163
- # whether or not we track participants when using the override parameter to
164
- # preview variants
165
- #
166
- # true using overrides to preview experiments will increment the
167
- # participant count for the override variant
168
- # false using overrides to preview experiments will not increment the
169
- # participant count for the override variant
170
- config.track_override = false
171
-
172
- # whether or not to continue tracking conversions after a winner has been
173
- # selected in order to continue monitoring performance of the variant
174
- #
175
- # true continues to track conversions after a winner has been selected (as
176
- # long as the experiment is still running)
177
- # false all conversion and participation tracking stops once a winner has
178
- # been selected
179
- config.track_winner_conversions = false
180
-
181
- # whether or not to allow multiple conversions of the same goal, or default
182
- # conversion if no goals are defined
183
- #
184
- # true tracks multiple participant conversions for the same goal as long
185
- # as they haven't been reset (see config.reset_manually)
186
- # false prevents tracking multiple conversions for a single participant
187
- config.allow_multiple_conversions = false
188
-
189
- # whether or not to allow participants to convert for multiple defined goals
190
- #
191
- # true allows participants to convert more than one goal as long as they
192
- # haven't been reset (see config.reset_manually)
193
- # false prevents converting to multiple goals for a single participant
194
- config.allow_multiple_goals = false
195
-
196
- # whether or not to enable calibration before an experiment is started - the
197
- # participants and conversions will be tracked for your control group while
198
- # an experiment remains unstarted, which can be useful for gathering a
199
- # baseline conversion rate if you don't already have one
200
- #
201
- # control is always returned for unstarted experiments by default, and this
202
- # configuration only affects whether or not to track metrics
203
- #
204
- # this setting only applies when start_manually is also true
205
- #
206
- # true metrics for participation and conversion will be tracked for the
207
- # control group until the experiment is started
208
- # false metrics will not be tracked while the experiment remains unstarted
209
- config.enable_calibration = false
210
-
211
- # whether or not to skip the request filtering for this experiment - can be
212
- # useful when defining content-based experiments with custom algorithms which
213
- # bucket participants strictly based on additional content metadata and you
214
- # want to expose those variants to crawlers and bots
215
- #
216
- # true requests that would otherwise be filtered based on your
217
- # TrailGuide.configuration.request_filter config will instead be
218
- # allowed through to this experiment
219
- # false default behavior, requests will be filtered based on your config
220
- config.skip_request_filter = false
221
-
222
- # whether or not this experiment can be resumed after it's stopped - allows
223
- # temporarily "pausing" an experiment then resuming it without losing metrics
224
- #
225
- # true this experiment can be paused and resumed
226
- # false this experiment can only be stopped and reset/restarted
227
- config.can_resume = false
228
-
229
- # set a default target sample size for all experiments - this will prevent
230
- # metrics and stats from being displayed in the admin UI until the sample size
231
- # is reached or the experiment is stopped
232
- #
233
- # config.target_sample_size = nil
234
-
235
- # callback when connecting to redis fails and trailguide falls back to always
236
- # returning control variants
237
- config.on_redis_failover = -> (experiment, error) do
238
- TrailGuide.logger.error error
239
- end
240
-
241
- # callback on experiment start, either manually via UI/console or
242
- # automatically depending on config.start_manually, can be used for logging,
243
- # tracking, etc.
244
- #
245
- # context may or may not be present depending on how you're triggering the
246
- # action - if you're using the admin, this will be the admin controller
247
- # context, if you're in a console you have the option to pass a context to
248
- # `experiment.start!` or not
249
- #
250
- # config.on_start = -> (experiment, context) { ... }
251
-
252
- # callback on experiment schedule manually via UI/console, can be used for logging,
253
- # tracking, etc.
254
- #
255
- # experiments can only be scheduled if config.start_manually is true
256
- #
257
- # context may or may not be present depending on how you're triggering the
258
- # action - if you're using the admin, this will be the admin controller
259
- # context, if you're in a console you have the option to pass a context to
260
- # `experiment.schedule!` or not
261
- #
262
- # config.on_schedule = -> (experiment, start_at, stop_at, context) { ... }
263
-
264
- # callback on experiment stop manually via UI/console, can be used for
265
- # logging, tracking, etc.
266
- #
267
- # context may or may not be present depending on how you're triggering the
268
- # action - if you're using the admin, this will be the admin controller
269
- # context, if you're in a console you have the option to pass a context to
270
- # `experiment.stop!` or not
271
- #
272
- # config.on_stop = -> (experiment, context) { ... }
273
-
274
- # callback on experiment pause manually via UI/console, can be used for
275
- # logging, tracking, etc.
276
- #
277
- # context may or may not be present depending on how you're triggering the
278
- # action - if you're using the admin, this will be the admin controller
279
- # context, if you're in a console you have the option to pass a context to
280
- # `experiment.pause!` or not
281
- #
282
- # config.on_pause = -> (experiment, context) { ... }
283
-
284
- # callback on experiment resume manually via UI/console, can be used for
285
- # logging, tracking, etc.
286
- #
287
- # context may or may not be present depending on how you're triggering the
288
- # action - if you're using the admin, this will be the admin controller
289
- # context, if you're in a console you have the option to pass a context to
290
- # `experiment.resume!` or not
291
- #
292
- # config.on_resume = -> (experiment, context) { ... }
293
-
294
- # callback on experiment delete manually via UI/console, can be used for
295
- # logging, tracking, etc. - will also be triggered by a reset
296
- #
297
- # context may or may not be present depending on how you're triggering the
298
- # action - if you're using the admin, this will be the admin controller
299
- # context, if you're in a console you have the option to pass a context to
300
- # `experiment.delete!` or not
301
- #
302
- # config.on_delete = -> (experiment, context) { ... }
303
-
304
- # callback on experiment reset manually via UI/console, can be used for
305
- # logging, tracking, etc. - will also trigger any on_delete callbacks
306
- #
307
- # context may or may not be present depending on how you're triggering the
308
- # action - if you're using the admin, this will be the admin controller
309
- # context, if you're in a console you have the option to pass a context to
310
- # `experiment.reset!` or not
311
- #
312
- # config.on_reset = -> (experiment, context) { ... }
313
-
314
- # callback when a winner is selected manually via UI/console, can be used for
315
- # logging, tracking, etc.
316
- #
317
- # context may or may not be present depending on how you're triggering the
318
- # action - if you're using the admin, this will be the admin controller
319
- # context, if you're in a console you have the option to pass a context to
320
- # `experiment.declare_winner!` or not
321
- #
322
- # config.on_winner = -> (experiment, winner, context) { ... }
323
-
324
-
325
- # callback when a participant is entered into a variant for the first time,
326
- # can be used for logging, tracking, etc.
327
- #
328
- # config.on_choose = -> (experiment, variant, participant, metadata) { ... }
329
-
330
- # callback every time a participant is returned a variant in the experiment,
331
- # can be used for logging, tracking, etc.
332
- #
333
- # config.on_use = -> (experiment, variant, participant, metadata) { ... }
334
-
335
- # callback when a participant converts for a variant in the experiment, can be
336
- # used for logging, tracking, etc.
337
- #
338
- # config.on_convert = -> (experiment, checkpoint, variant, participant, metadata) { ... }
339
-
340
-
341
- # callback that can short-circuit participation based on your own logic, which
342
- # gets called *after* all the core engine checks (i.e. that the user is
343
- # not excluded or already participating, etc.)
344
- #
345
- # `allowed` will be the value returned by any previous callbacks in the chain
346
- #
347
- # should return true or false
348
- #
349
- # config.allow_participation = -> (experiment, allowed, participant, metadata) { ... return true }
350
-
351
-
352
- # callback that can short-circuit conversion based on your own logic, which
353
- # gets called *after* all the core engine checks (i.e. that the user is
354
- # participating in the experiment, is within the bounds of the experiment
355
- # configuration for allow_multiple_*, etc.)
356
- #
357
- # `allowed` will be the value returned by any previous callbacks in the chain
358
- #
359
- # should return true or false
360
- #
361
- # config.allow_conversion = -> (experiment, allowed, checkpoint, variant, participant, metadata) { ... return true }
362
-
363
-
364
- # callback that can be used to modify the rollout of a selected winner - for
365
- # example you could use a custom algorithm or even something like the flipper
366
- # gem to do a "feature rollout" from your control variant to your winner for
367
- # all users
368
- #
369
- # be aware that when using this alongside track_winner_conversions, whatever
370
- # variant is returned from this callback chain is what will be tracked for
371
- # participation and conversion as long as the experiment is still running
372
- #
373
- # `winner` will be the variant returned by any previous callbacks in the chain
374
- #
375
- # must return an experiment variant
376
- #
377
- # config.rollout_winner = -> (experiment, winner, participant) { ... return variant }
378
- end
379
-
380
- # admin ui configuration
381
- #
382
- TrailGuide::Admin.configure do |config|
383
- # display title for admin UI
384
- #
385
- config.title = 'TrailGuide'
386
-
387
- # display subtitle for admin UI
388
- #
389
- config.subtitle = 'Experiments and A/B Tests'
390
-
391
- # request parameter can be used to "peek" at results even before an
392
- # experiment's target_sample_size has been hit if one is configured
393
- #
394
- # if you set this to nil, admins will not be able to peek at experiment
395
- # results until the target sample size is hit or the experiment is stopped
396
- #
397
- config.peek_parameter = nil
398
- end