field_test 0.2.4 → 0.4.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 91cef396b68f0ed43abcce42c80290ba216fe77105a947f0317925f7abb4d0fc
4
- data.tar.gz: d2119a7219f278d182bf5484f959f788b03f40c129f23a58211ff8c9bfcfaeb5
3
+ metadata.gz: 25a516eac00c5ded25aa203d9e3feb89196c7641868e5575938bf223ee8d20d2
4
+ data.tar.gz: 89dc335addf645088c5251ccd7a99b0d5348857a210c520350a3d39a9244fc3f
5
5
  SHA512:
6
- metadata.gz: fce4404e2f2c90215f14414bc9cd5e8c8cb3fb023e1adaea5a116e63e096ad52f25b1a74130cbebbd2d97e80c294b41289249172ca0c02ffb44a6d0ccaddcfe5
7
- data.tar.gz: 8dcd8402e676d67c15552b93277007f4cc2fc5210a4c7beef72a5b0a0acd9e6c1f4c171cc65d8300e810acb5fd524d19f67eabef4da3b1cb86aa83e4d0c5c943
6
+ metadata.gz: 97c5900ff54996e5b31250b882300104c991e93ab4582b30e1a2ada4fb0c8f191ddbac9240941fce9d2160bf01a66ca1ed73cd3e4a5a734de99e487b9c0c3772
7
+ data.tar.gz: 765b5fbb1928889ff40b576b710b93ffe14adc38d6153715b89d806cbcfa46021fb4d0cc780754a1e794d3ad2ccbcb8f939dff72a148392ae95a0b968cb7d443
@@ -1,33 +1,71 @@
1
- ## 0.2.4
1
+ ## 0.4.1 (2020-09-07)
2
+
3
+ - Use `datetime` type in migration
4
+
5
+ ## 0.4.0 (2020-08-04)
6
+
7
+ - Fixed CSRF vulnerability with non-session based authentication - [more info](https://github.com/ankane/field_test/issues/28)
8
+ - Fixed cache key for requests
9
+
10
+ ## 0.3.2 (2020-04-16)
11
+
12
+ - Added support for excluding IP addresses
13
+
14
+ ## 0.3.1 (2019-07-01)
15
+
16
+ - Added `closed` and `keep_variant`
17
+ - Added `field_test_upgrade_memberships` method
18
+ - Fixed API controller error
19
+ - Fixed bug where conversions were recorded after winner
20
+
21
+ Security
22
+
23
+ - Fixed arbitrary variants via query parameters - [more info](https://github.com/ankane/field_test/issues/17)
24
+
25
+ ## 0.3.0 (2019-06-02)
26
+
27
+ - Added support for native apps
28
+ - Added `cookies` option
29
+ - Added `precision` option
30
+ - Fixed bug in results with multiple goals
31
+ - Fixed issue where metrics disappeared from dashboard when moving to multiple goals
32
+ - Dropped support for Rails < 5
33
+
34
+ Breaking changes
35
+
36
+ - Split out participant id and type
37
+ - Changed participant logic for emails
38
+
39
+ ## 0.2.4 (2019-01-03)
2
40
 
3
41
  - Fixed `PG::AmbiguousColumn` error
4
42
 
5
- ## 0.2.3
43
+ ## 0.2.3 (2018-01-28)
6
44
 
7
45
  - Fixed participant reporting for multiple goals
8
46
 
9
- ## 0.2.2
47
+ ## 0.2.2 (2017-05-01)
10
48
 
11
49
  - Added support for Rails 5.1
12
50
 
13
- ## 0.2.1
51
+ ## 0.2.1 (2016-12-18)
14
52
 
15
53
  - Added support for multiple goals
16
54
 
17
- ## 0.2.0
55
+ ## 0.2.0 (2016-12-17)
18
56
 
19
57
  - Better web UI
20
58
  - Removed `cookie:` prefix for unknown participants
21
59
 
22
- ## 0.1.2
60
+ ## 0.1.2 (2016-12-17)
23
61
 
24
62
  - Exclude bots
25
63
  - Mailer improvements
26
64
 
27
- ## 0.1.1
65
+ ## 0.1.1 (2016-12-15)
28
66
 
29
67
  - Added basic web UI
30
68
 
31
- ## 0.1.0
69
+ ## 0.1.0 (2016-12-14)
32
70
 
33
71
  - First release
@@ -1,4 +1,4 @@
1
- Copyright (c) 2016 Andrew Kane
1
+ Copyright (c) 2016-2019 Andrew Kane
2
2
 
3
3
  MIT License
4
4
 
data/README.md CHANGED
@@ -3,11 +3,14 @@
3
3
  :maple_leaf: A/B testing for Rails
4
4
 
5
5
  - Designed for web and email
6
- - Comes with a [handy dashboard](https://fieldtest.dokkuapp.com/)
6
+ - Comes with a [dashboard](https://fieldtest.dokkuapp.com/) to view results and update variants
7
+ - Uses your database for storage
7
8
  - Seamlessly handles the transition from anonymous visitor to logged in user
8
9
 
9
10
  Uses [Bayesian statistics](https://www.evanmiller.org/bayesian-ab-testing.html) to evaluate results so you don’t need to choose a sample size ahead of time.
10
11
 
12
+ [![Build Status](https://travis-ci.org/ankane/field_test.svg?branch=master)](https://travis-ci.org/ankane/field_test)
13
+
11
14
  ## Installation
12
15
 
13
16
  Add this line to your application’s Gemfile:
@@ -19,7 +22,8 @@ gem "field_test"
19
22
  Run:
20
23
 
21
24
  ```sh
22
- rails g field_test:install
25
+ rails generate field_test:install
26
+ rails db:migrate
23
27
  ```
24
28
 
25
29
  And mount the dashboard in your `config/routes.rb`:
@@ -28,7 +32,7 @@ And mount the dashboard in your `config/routes.rb`:
28
32
  mount FieldTest::Engine, at: "field_test"
29
33
  ```
30
34
 
31
- Be sure to [secure the dashboard](#security) in production.
35
+ Be sure to [secure the dashboard](#dashboard-security) in production.
32
36
 
33
37
  ![Screenshot](https://ankane.github.io/field_test/screenshot6.png)
34
38
 
@@ -45,12 +49,18 @@ experiments:
45
49
  - blue
46
50
  ```
47
51
 
48
- Refer to it in views, controllers, and mailers.
52
+ Refer to it in controllers, views, and mailers.
49
53
 
50
54
  ```ruby
51
55
  button_color = field_test(:button_color)
52
56
  ```
53
57
 
58
+ To make testing easier, you can specify a variant with query parameters
59
+
60
+ ```
61
+ http://localhost:3000/?field_test[button_color]=green
62
+ ```
63
+
54
64
  When someone converts, record it with:
55
65
 
56
66
  ```ruby
@@ -67,24 +77,90 @@ experiments:
67
77
 
68
78
  All calls to `field_test` will now return the winner, and metrics will stop being recorded.
69
79
 
70
- ## Features
80
+ You can keep returning the variant for existing participants after a winner is declared:
71
81
 
72
- You can specify a variant with query parameters to make testing easier
82
+ ```yml
83
+ experiments:
84
+ button_color:
85
+ winner: green
86
+ keep_variant: true
87
+ ```
88
+
89
+ You can also close an experiment to new participants without declaring a winner while still recording metrics for existing participants:
73
90
 
91
+ ```yml
92
+ experiments:
93
+ button_color:
94
+ closed: true
74
95
  ```
75
- ?field_test[button_color]=green
96
+
97
+ Calls to `field_test` for new participants will return the control, and they won’t be added to the experiment.
98
+
99
+ You can get the list of experiments and variants for a user with:
100
+
101
+ ```ruby
102
+ field_test_experiments
76
103
  ```
77
104
 
78
- Assign a specific variant to a user with:
105
+ ## JavaScript and Native Apps
106
+
107
+ For JavaScript and native apps, add calls to your normal endpoints.
79
108
 
80
109
  ```ruby
81
- experiment = FieldTest::Experiment.find(:button_color)
82
- experiment.variant(participant, variant: "green")
110
+ class CheckoutController < ActionController::API
111
+ def start
112
+ render json: {button_color: field_test(:button_color)}
113
+ end
114
+
115
+ def finish
116
+ field_test_converted(:button_color)
117
+ # ...
118
+ end
119
+ end
83
120
  ```
84
121
 
85
- You can also change a user’s variant from the dashboard.
122
+ For anonymous visitors in native apps, pass a `Field-Test-Visitor` header with a unique identifier.
86
123
 
87
- ## Config
124
+ ## Participants
125
+
126
+ Any model or string can be a participant in an experiment.
127
+
128
+ For web requests, it uses `current_user` (if it exists) and an anonymous visitor id to determine the participant. Set your own with:
129
+
130
+ ```ruby
131
+ class ApplicationController < ActionController::Base
132
+ def field_test_participant
133
+ current_company
134
+ end
135
+ end
136
+ ```
137
+
138
+ For mailers, it tries `@user` then `params[:user]` to determine the participant. Set your own with:
139
+
140
+ ```ruby
141
+ class ApplicationMailer < ActionMailer::Base
142
+ def field_test_participant
143
+ @company
144
+ end
145
+ end
146
+ ```
147
+
148
+ You can also manually pass a participant with:
149
+
150
+ ```ruby
151
+ field_test(:button_color, participant: company)
152
+ ```
153
+
154
+ ## Jobs
155
+
156
+ To get variants in jobs, models, and other contexts, use:
157
+
158
+ ```ruby
159
+ experiment = FieldTest::Experiment.find(:button_color)
160
+ button_color = experiment.variant(user)
161
+ ```
162
+
163
+ ## Exclusions
88
164
 
89
165
  By default, bots are returned the first variant and excluded from metrics. Change this with:
90
166
 
@@ -93,6 +169,23 @@ exclude:
93
169
  bots: false
94
170
  ```
95
171
 
172
+ Exclude certain IP addresses with:
173
+
174
+ ```yml
175
+ exclude:
176
+ ips:
177
+ - 127.0.0.1
178
+ - 10.0.0.0/8
179
+ ```
180
+
181
+ You can also use custom logic:
182
+
183
+ ```ruby
184
+ field_test(:button_color, exclude: request.user_agent == "Test")
185
+ ```
186
+
187
+ ## Config
188
+
96
189
  Keep track of when experiments started and ended. Use any format `Time.parse` accepts. Variants assigned outside this window are not included in metrics.
97
190
 
98
191
  ```yml
@@ -126,6 +219,14 @@ experiments:
126
219
  - 15
127
220
  ```
128
221
 
222
+ To help with GDPR compliance, you can switch from cookies to [anonymity sets](https://privacypatterns.org/patterns/Anonymity-set) for anonymous visitors. Visitors with the same IP mask and user agent are grouped together.
223
+
224
+ ```yml
225
+ cookies: false
226
+ ```
227
+
228
+ ## Dashboard Config
229
+
129
230
  If the dashboard gets slow, you can make it faster with:
130
231
 
131
232
  ```yml
@@ -134,12 +235,19 @@ cache: true
134
235
 
135
236
  This will use the Rails cache to speed up winning probability calculations.
136
237
 
137
- ## Funnels
238
+ If you need more precision, set:
239
+
240
+ ```yml
241
+ precision: 1
242
+ ```
243
+
244
+ ## Multiple Goals
138
245
 
139
246
  You can set multiple goals for an experiment to track conversions at different parts of the funnel. First, run:
140
247
 
141
248
  ```sh
142
- rails g field_test:events
249
+ rails generate field_test:events
250
+ rails db:migrate
143
251
  ```
144
252
 
145
253
  And add to your config:
@@ -162,20 +270,30 @@ The results for all goals will appear on the dashboard.
162
270
 
163
271
  ## Analytics Platforms
164
272
 
165
- You can also send experiment data to analytics platforms like [Google Analytics](https://www.google.com/analytics/), [Mixpanel](https://mixpanel.com/), and [Ahoy](https://github.com/ankane/ahoy). Use:
273
+ You may also want to send experiment data as properties to other analytics platforms like [Segment](https://segment.com), [Amplitude](https://amplitude.com), and [Ahoy](https://github.com/ankane/ahoy). Get the list of experiments and variants with:
166
274
 
167
275
  ```ruby
168
276
  field_test_experiments
169
277
  ```
170
278
 
171
- to get all experiments and variants for a participant and pass them as properties.
279
+ ### Ahoy
280
+
281
+ You can configure Field Test to use Ahoy’s visitor token instead of creating its own:
282
+
283
+ ```ruby
284
+ class ApplicationController < ActionController::Base
285
+ def field_test_participant
286
+ [ahoy.user, ahoy.visitor_token]
287
+ end
288
+ end
289
+ ```
172
290
 
173
- ## Security
291
+ ## Dashboard Security
174
292
 
175
293
  #### Devise
176
294
 
177
295
  ```ruby
178
- authenticate :user, -> (user) { user.admin? } do
296
+ authenticate :user, ->(user) { user.admin? } do
179
297
  mount FieldTest::Engine, at: "field_test"
180
298
  end
181
299
  ```
@@ -189,13 +307,106 @@ ENV["FIELD_TEST_USERNAME"] = "moonrise"
189
307
  ENV["FIELD_TEST_PASSWORD"] = "kingdom"
190
308
  ```
191
309
 
192
- ## Credits
310
+ ## Updating Variants
193
311
 
194
- A huge thanks to [Evan Miller](https://www.evanmiller.org/) for deriving the Bayesian formulas.
312
+ Assign a specific variant to a user with:
313
+
314
+ ```ruby
315
+ experiment = FieldTest::Experiment.find(:button_color)
316
+ experiment.variant(participant, variant: "green")
317
+ ```
318
+
319
+ You can also change a user’s variant from the dashboard.
320
+
321
+ ## Associations
322
+
323
+ To associate models with field test memberships, use:
324
+
325
+ ```ruby
326
+ class User < ApplicationRecord
327
+ has_many :field_test_memberships, class_name: "FieldTest::Membership", as: :participant
328
+ end
329
+ ```
330
+
331
+ Now you can do:
332
+
333
+ ```ruby
334
+ user.field_test_memberships
335
+ ```
336
+
337
+ ## Upgrading
338
+
339
+ ### 0.3.0
340
+
341
+ Upgrade the gem and add to `config/field_test.yml`:
342
+
343
+ ```yml
344
+ legacy_participants: true
345
+ ```
346
+
347
+ Also, if you use Field Test in emails, know that the default way participants are determined has changed. Restore the previous way with:
348
+
349
+ ```ruby
350
+ class ApplicationMailer < ActionMailer::Base
351
+ def field_test_participant
352
+ message.to.first
353
+ end
354
+ end
355
+ ```
356
+
357
+ We also recommend upgrading participants when you have time.
358
+
359
+ #### Upgrading Participants
360
+
361
+ Field Test 0.3.0 splits the `field_test_memberships.participant` column into `participant_type` and `participant_id`.
362
+
363
+ To upgrade without downtime, create a migration:
364
+
365
+ ```sh
366
+ rails generate migration upgrade_field_test_participants
367
+ ```
368
+
369
+ with:
370
+
371
+ ```ruby
372
+ class UpgradeFieldTestParticipants < ActiveRecord::Migration[6.0]
373
+ def change
374
+ add_column :field_test_memberships, :participant_type, :string
375
+ add_column :field_test_memberships, :participant_id, :string
376
+
377
+ add_index :field_test_memberships, [:participant_type, :participant_id, :experiment],
378
+ unique: true, name: "index_field_test_memberships_on_participant_and_experiment"
379
+ end
380
+ end
381
+ ```
382
+
383
+ After you run it, writes will go to both the old and new sets of columns.
384
+
385
+ Next, backfill data:
386
+
387
+ ```ruby
388
+ FieldTest::Membership.where(participant_id: nil).find_each do |membership|
389
+ participant = membership.participant
390
+
391
+ if participant.include?(":")
392
+ participant_type, _, participant_id = participant.rpartition(":")
393
+ participant_type = nil if participant_type == "cookie" # legacy
394
+ else
395
+ participant_id = participant
396
+ end
397
+
398
+ membership.update!(
399
+ participant_type: participant_type,
400
+ participant_id: participant_id
401
+ )
402
+ end
403
+ ```
404
+
405
+ Finally, remove `legacy_participants: true` from the config file. Once you confirm it’s working, you can drop the `participant` column (you can rename it first just to be extra safe).
195
406
 
196
- ## TODO
407
+ ## Credits
197
408
 
198
- - Code samples for analytics platforms
409
+ A huge thanks to [Evan Miller](https://www.evanmiller.org/) for deriving the Bayesian formulas.
199
410
 
200
411
  ## History
201
412
 
@@ -209,3 +420,12 @@ Everyone is encouraged to help improve this project. Here are a few ways you can
209
420
  - Fix bugs and [submit pull requests](https://github.com/ankane/field_test/pulls)
210
421
  - Write, clarify, or fix documentation
211
422
  - Suggest or add new features
423
+
424
+ To get started with development:
425
+
426
+ ```sh
427
+ git clone https://github.com/ankane/field_test.git
428
+ cd field_test
429
+ bundle install
430
+ bundle exec rake test
431
+ ```