RailsAbTest
Perform A/B Testing in your Rails app with ease.
The idea is a combination of
- minimal Code to support A/B Test versioning, is provided by this gem.
- A simple Pattern to organize the code in views into separated versions for each A/B Test version.
Installation
Add this line to your application's Gemfile:
gem 'rails_ab_test'
And then execute:
$ bundle
Or install it yourself as:
$ gem install rails_ab_test
Usage
Let's start with the simplest usage case:
The Code
Configure your controllers by including the module, normally ApplicationController
is a good candidate for this:
include RailsAbTest::Controller
Then for the action (index
in the example) that will be A/B Tested set a before_filter
:
# a controller
before_filter :choose_ab_test, only: :index
The method choose_ab_test
will randomly (with 50% probability) choose A or B as the A/B Test version.
From here the version chosen will be accessible in your views and helpers in the variable @ab_test
.
Then inside the action you need to replace render
with render_ab
# a controller
def index
render_ab
end
render_ab
will infer the template to render from the action name, and prepend it with @ab_test
to fully
determine the template name. i.e. if the A/B Version is A it will render the template index_A
.
The Pattern
Now you need to make 2 copies of your index
view template, and name it index_A
for the A/B Test version A, and
index_B
for B.
Make sure you set up different tracking for each version and you are good to go. Your controller's index
action is ready to be A/B Tested.
QA and Test support
For testing and QA purposes the A/B Test version can be selected by appending ?ab_test=A
to the url of the page,
that will make sure the version A is selected.
More complex usage
More versions that just A and B
Then instead of a before_filter
you can call the method choose_ab_test
directly:
# a controller
def show
choose_ab_test ['A', 'B', 'C'] # this action calls the method directly instead
render_ab
end
Again the 3 versions will have the same probability of being chosen.
NOTE: in the current version the gem only supports versions with equal probabilities each.
2 actions 1 template
Imagine that the actions index
and archive
are both A/B versioned and they share the same template. The action index
will not change, but archive
needs to explicitly render the index
template like this:
# a controller
before_filter :choose_ab_test, only: :index, :archive
def archive
render_ab template: 'index'
end
Versioned partials
If instead of a full page template only a partial is going to be A/B Tested, you can achieve like this:
# index.haml.html template
= render_ab partial: 'menu', variable_for_the_partial: @variable
The pattern again here is to make 2 copies of the _menu
partial and name them, i.e. _menu_A
and _menu_B
.
Versioned html snippets and partials
Based on the variable @ab_test
you can also make conditions in views and helpers:
# index.haml.html template
- if @ab_test == 'A'
version A is rendered
- else
hello B
# a view helper
def helper_method_AB_versioned
if @ab_test == 'A'
'version A is rendered'
else
'Hello B'
end
end
Several pages sharing the same A/B version
Now imagine that the index
actions of 2 controllers (e.g. posts
and authors
) are A/B versioned,
and that you want that when an user sees version A of posts#index
she should also see version A of authors#index
.
This can be achieved by overriding the method choose_ab_test
in both controllers, and using a cookie:
# posts controller
before_filter :choose_ab_test, only: :index
...
def choose_ab_test
@ab_test = cookies['shared-version-posts-authors'] || super
cookies['shared-version-posts-authors'] = @ab_test
end
# authors controller should have the same code as above
Of course you can extract the common code to a central place. Also name the cookie with a name that makes sense for you, and expire it, sign it or encrypt it as needed.
Cookies to persist versions
If an user should always see the same A/B version of a page, the same method above and a cookie work perfectly:
# a controller
before_filter :choose_ab_test, only: :index
...
def choose_ab_test
@ab_test = cookies['shared-version-posts-authors'] || super
cookies['shared-version-posts-authors'] = @ab_test
end
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/joahking/rails_ab_test.
TODOs
- write tests
License
The gem is available as open source under the terms of the MIT License.