前端框架选型是企业提升开发效率与用户体验的关键因素
510
2022-10-23
Vanity - 一个Rails的A/B测试框架
Vanity
Vanity is an A/B testing framework for Rails that is datastore agnostic.
All about Vanity: http://vanity.labnotes.orgOn Github: http://github.com/assaf/vanity
InstallationSetupDatastoreRedis SetupMongoDB SetupSQL Database SetupForking servers and reconnecting InitializationUser identificationRailsOther Define a A/B testPresent the different options to your usersMeasure conversionCheck the reportRails report dashboard Registering participants with JavascriptCompatibilityTestingUpdating documentationContributingCredits/License
Installation
Add to your Gemfile:
gem "vanity"
(For support for older versions of Rails and Ruby 1.8, please see the 1.9.x branch.)
Setup
Datastore
Choose a datastore that best fits your needs and preferences for storing experiment results. Choose one of: Redis, MongoDB or an SQL database. While Redis is usually faster, it may add additional complexity to your stack. Datastores should be configured using a config/vanity.yml.
Redis Setup
Add to your Gemfile:
gem "redis", ">= 3.2"gem "redis-namespace", ">= 1.1.0"
By default Vanity is configured to use Redis on localhost port 6379 with database 0.
A sample config/vanity.yml might look like:
test: collecting: falseproduction: adapter: redis url: redis://<%= ENV["REDIS_USER"] %>:<%= ENV["REDIS_PASSWORD"] %>@<%= ENV["REDIS_HOST"] %>:<%= ENV["REDIS_PORT"] %>/0
If you want to use your test environment with RSpec you will need to add an adapter to test:
test: adapter: redis collecting: false
To re-use an existing redis connection, you can call Vanity.connect! explicitly, for example:
Vanity.connect!( adapter: :redis, redis: $redis)
MongoDB Setup
Add to your Gemfile:
gem "mongo", "~> 2.0" # For Mongo 1.x support see Vanity versions 2.1 and below.
A sample config/vanity.yml might look like:
development: adapter: mongodb database: analyticstest: collecting: falseproduction: adapter: mongodb database: analytics
SQL Database Setup
Vanity supports multiple SQL stores (like MySQL, MariaDB, Postgres, Sqlite, etc.) using ActiveRecord, which is built into Rails. If you're using DataMapper, Sequel or another persistence framework, add to your Gemfile:
gem "active_record"
A sample config/vanity.yml might look like:
development: adapter: active_record active_record_adapter: sqlite3 database: db/development.sqlite3test: adapter: active_record active_record_adapter: default collecting: falseproduction: adapter: active_record active_record_adapter: postgresql <% uri = URI.parse(ENV['DATABASE_URL']) %> host: <%= uri.host %> username: <%= uri.user%> password: <%= uri.password %> port: <%= uri.port %> database: <%= uri.path.sub('/', '') %>
If you're going to store data in the database, run the generator and migrations to create the database schema:
$ rails generate vanity$ rake db:migrate
Forking servers and reconnecting
If you're using a forking server (like Passenger or Unicorn), you should reconnect after a new worker is created:
# unicorn.rbafter_fork do |server, worker| defined?(Vanity) && Vanity.reconnect!end# an initializerif defined?(PhusionPassenger) PhusionPassenger.on_event(:starting_worker_process) do |forked| # We're in smart spawning mode. if forked defined?(Vanity) && Vanity.reconnect! end endend
If you're using explicit options with Vanity.connect!, you should call disconnect! first, for example:
Vanity.disconnect!Vanity.connect!( adapter: 'redis', redis: $redis)
Initialization
If you're using Rails, this is done automagically. Otherwise, some manual setup is required, for example on an app's booting:
$redis = Redis.new # or from elsewhereVanity.configure do |config| # ... any configendVanity.connect!( adapter: :redis, redis: $redis)Vanity.load!
User identification
Rails
Turn Vanity on, and pass a reference to a method that identifies a user. For example:
class ApplicationController < ActionController::Base use_vanity :current_userend
For more information, please see the identity documentation.
Other
Vanity pulls the identity from a "context" object that responds to vanity_identity, so we need to define a Vanity.context (this is how the ActionMailer integration works):
class AVanityContext def vanity_identity "123" endendVanity.context = AVanityContext.new() # Any object that responds to `#vanity_identity`
If you're using plain ruby objects, you could also alias something in your identity model to respond similarly and then set that as the vanity context:
class User alias_method :vanity_identity, :idend
Define a A/B test
This experiment goes in the file experiments/price_options.rb:
ab_test "Price options" do description "Mirror, mirror on the wall, who's the better price of all?" alternatives 19, 25, 29 metrics :signupsend
If the experiment uses a metric as above ("signups"), there needs to be a corresponding ruby file for that metric, experiments/metrics/signups.rb.
metric "Signup (Activation)" do description "Measures how many people signed up for our awesome service."end
Present the different options to your users
In Rails' templates, this is straightforward:
Outside of templates:
Vanity.ab_test(:invite_subject)
Measure conversion
Conversions are created via the Vanity.track! method. A user should already be added to an experiment, via ab_test before this is called - otherwise, the conversion will be tracked, but the user will not be added to the experiment.
For example, in Rails:
class SignupController < ApplicationController def signup @account = Account.new(params[:account]) if @account.save Vanity.track!(:signups) redirect_to @acccount else render action: :offer end endend
Outside of an Rails controller, for example in a Rack handler:
identity_object = Identity.new(env['rack.session'])Vanity.track!(:click, { # can be any object that responds to `to_s` with a string # that contains the unique identifier or the string identifier itself :identity=>identity_object, :values=>[1] # optional})
Check the report
vanity report --output vanity.html
Rails report dashboard
To view metrics and experiment results with the dashboard in Rails 3 & Rails 4:
rails generate controller Vanity --helper=false
In config/routes.rb, add:
get '/vanity' =>'vanity#index'get '/vanity/participant/:id' => 'vanity#participant'post '/vanity/complete'post '/vanity/chooses'post '/vanity/reset'post '/vanity/enable'post '/vanity/disable'post '/vanity/add_participant'get '/vanity/image'
The controller should look like:
class VanityController < ApplicationController include Vanity::Rails::Dashboard layout false # exclude this if you want to use your application layoutend
Registering participants with Javascript
If robots or spiders make up a significant portion of your sites traffic they can affect your conversion rate. Vanity can optionally add participants to the experiments using asynchronous javascript callbacks, which will keep many robots out. For those robots that do execute Javascript and are well-behaved (like Googlebot), Vanity filters out requests based on their user-agent string.
In Rails, add the following to application.rb:
Vanity.configure do |config| config.use_js = true # Optionally configure the add_participant route that is added with Vanity::Rails::Dashboard, # make sure that this action does not require authentication # config.add_participant_route = '/vanity/add_participant'end
Then add <%= vanity_js %> to any page that calls an A/B test after calling ab_test. vanity_js needs to be included after your call to ab_test so that it knows which version of the experiment the participant is a member of. The helper will render nothing if the there are no ab_tests running on the current page, so adding vanity_js to the bottom of your layouts is a good option. Keep in mind that if you set use_js and don't include vanity_js in your view no participants will be recorded.
Compatibility
Here's what's tested and known to work:
Ruby 2.3 Persistence: Redis (redis-rb >= 3.2.1), Mongo, ActiveRecord Rails: 4.1, 4.2, 5Ruby 2.4 Persistence: Redis (redis-rb >= 3.2.1), Mongo, ActiveRecord Rails: 4.1, 4.2, 5JRuby 9.1 Persistence: Redis (redis-rb >= 3.2.1), Mongo, ActiveRecord Rails: 4.1, 4.2
Testing
For view tests/specs or integration testing, it's handy to set the outcome of an experiment. This may be done using the chooses method. For example:
Vanity.playground.experiment(:price_options).chooses(19)
See the docs on testing for more.
Updating documentation
Documenation is written in the textile format in the docs directory, and is hosted on Github Pages. To update the docs commit changes to the master branch in this repository, then:
bundle exec rake docs # output HTML files into html/git checkout gh-pagesmv html/* . # Move generated html to the top of the repogit commit # Add, commit and push any changes!
Go ahead and target a pull request against the gh-pages branch.
Contributing
Fork the projectPlease use a feature branch to make your changes, it's easier to test them that wayTo set up the test suite run bundle, then run appraisal install to prepare the test suite to run against multiple versions of RailsFix, patch, enhance, document, improve, sprinkle pixie dustTests. Please. Run appraisal rake test, of if you can, rake test:all. (This project uses Travis CI where the test suite is run against multiple versions of ruby, rails and backends.)Send a pull request on GitHub
Credits/License
Original code, copyright of Assaf Arkin, released under the MIT license.
Documentation available under the Creative Commons Attribution license.
For full list of credits and licenses: http://vanity.labnotes.org/credits.html.
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~