mountain-goat 0.0.17 → 0.0.18

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -2,88 +2,122 @@
2
2
 
3
3
  Embed a high-quality analytics platform in your application in minutes. Gain important A/B test business insights, and view the results and analytics in real time.
4
4
 
5
+ Add simple hooks in your code to display a/b metrics
6
+
7
+ <%= metric_variant(:homescreen_text, :user_signup, "Welcome here") %>
8
+
9
+ This creates a database entry to a/b test "homescreen_text" against a goal "user signup". Visit "http://yourdomain.com/mg" and you can add / adjust options (variants) for this text. When a user converts on this goal, you run the following code.
10
+
11
+ def create
12
+ record_conversion(:user_signup)
13
+ ...
14
+ end
15
+
16
+ This will track a conversion not only for the goal, but for the variant of "homescreen_text" (and any other associated metrics) that the user was served when he came to the home-page.
17
+
18
+ The best part? The mountain-goat admin console is located on your server and you can view and analyze your data in real time.
19
+
20
+ - See which metric variants are working and not working ("Cowabunga!" did 120% better than "Enter here", but 10% worse than "Do it rockapella!")
21
+ - Visually analyze the your metric variants; change them on the fly, adding new ones.
22
+ - Watch goal conversions in real-time with live-action console (grab the popcorn and watch how your users "sign up" and "view items" and ...)
23
+ - You can do more than change text, "switch variants" let you enter arbitrary ruby code, change the control of your site ("Do my users have to sign-in before commenting? Let's test!")
24
+ - Track goals with meta data (record_conversion(:user_signup, :referrer => request.env['HTTP_REFERER']))
25
+ * Mountain goat tracks as much arbitrary meta data as you want
26
+ * You are presented with charts for each goal, broken down by meta
27
+ * See what referrers are driving goals, or which of your blog posts are drawing an audience
28
+ - Much, much more, e.g. deliver views of this data to your consumers, streamline your site, customize it by user, it's all up to you.
29
+
5
30
  ## Install
6
31
 
7
32
  ### Mountain Goat gem
8
33
 
9
- gem install mountain-goat
10
-
11
- #Note, you'll need to install the proper migrations (currently in the migrations folder, task coming shortly)
34
+ gem install mountain-goat
35
+
36
+ ### Mountain Goat configration
37
+
38
+ Next run generator to create config file and necessary database migration (optionally pass in --password=my_mg_password)
39
+
40
+ ./script/generate mg
41
+
42
+ This will generate
43
+
44
+ /config/mountain-goat.yml (for storing a password to access mountain-goat)
45
+ /db/migrate/xxx_create_mountain_goat_tables.rb (necessary databae migrations to store mg data)
12
46
 
13
47
  ## Usage
14
48
 
15
- Mountain Goat hinges around three core concepts:
16
-
17
- *) Conversions are what you want E.g. "user purchases coffee"
18
- *) Metrics are how you draw people to convert E.g. "a banner on the store-front"
19
- *) Metric variants are A/B tests for metrics E.g. "free coffee" "chuck norris is inside"
49
+ Mountain Goat hinges around three core concepts:
20
50
 
21
- After you set up your database with some mountain-goat tables, the code will handle populating these tables for you. In your code, you can start A/B testing immediately.
51
+ - Conversions are what you want E.g. "user purchases coffee"
52
+ - Metrics are how you draw people to convert E.g. "a banner on the store-front"
53
+ - Metric variants are A/B tests for metrics E.g. "free coffee" "chuck norris is inside"
22
54
 
23
- <h2><%= metric_variant(:banner_on_store_front, :user_purchases_coffee, "Now arsenic and gluten-free") %></h2>
55
+ After you set up your database with some mountain-goat tables, the code will handle populating these tables for you. In your code, you can start A/B testing immediately.
24
56
 
25
- The metric_variant function (or mv for short) takes three parameters:
57
+ <h2><%= metric_variant(:banner_on_store_front, :user_purchases_coffee, "Now arsenic and gluten-free") %></h2>
26
58
 
27
- mv(metric_name, convert_name, default)
59
+ The metric_variant function (or, mv for short) takes three parameters:
28
60
 
29
- This will automatically create a metric and conversion and populate a metric variant with the default value. Easy, eh?
61
+ mv(metric_name, convert_name, default)
30
62
 
31
- From here, you can go into the mountain-goat admin center and add new metric variants to fit your need.
63
+ This will automatically create a metric and conversion and populate a metric variant with the default value. Easy, eh?
32
64
 
33
- The other important code you'll need to implement is when a goal is achieved.
65
+ From here, you can go into the mountain-goat admin center and add new metric variants to fit your need. The other important code you'll need to implement is when a goal is achieved.
34
66
 
35
- def purchase #coffees_controller.rb
36
- record_conversion(:user_purchases_coffee)
37
- ...
38
- end
67
+ def purchase #coffees_controller.rb
68
+ record_conversion(:user_purchases_coffee)
69
+ ...
70
+ end
39
71
 
40
- This will go in and record a conversion ("rally") for a user purchasing coffee. Further, it will track a hit for any metric-variants served to that user that relate to this goal. For example "Chuck Norris works here" might get a point.
72
+ This will go in and record a conversion ("rally") for a user purchasing coffee. Further, it will track a hit for any metric-variants served to that user that relate to this goal. For example "Chuck Norris works here" might get a point.
41
73
 
42
74
  ## Mountain Goat admin suite
43
75
 
44
- Navigate to /mg in your application to reach the mountain-goat admin center. Here, you can analyze / adjust your A/B tests.
76
+ Navigate to /mg in your application to reach the mountain-goat admin center. Here, you can analyze / adjust your A/B tests.
45
77
 
46
- The front page gives you a breakdown of each of your Goals, and the efficacy of each metric and metric-variant. Select a given metric to drill into its variants. Once you are in a specific metric, you'll be able to add new metric-variants and see what works best for your clients.
78
+ The front page gives you a breakdown of each of your Goals, and the efficacy of each metric and metric-variant. Select a given metric to drill into its variants. Once you are in a specific metric, you'll be able to add new metric-variants and see what works best for your clients.
47
79
 
48
80
  ## Advanced Features
49
81
 
50
- ### Meta data
82
+ ### Meta data
51
83
 
52
- You can track meta-data with any conversion. E.g.
84
+ You can track meta-data with any conversion. E.g.
53
85
 
54
- rc(:user_visit, :referring_domain => request.env['HTTP_REFERER'], :user_id => session[:user_id])
86
+ rc(:user_visit, :referring_domain => request.env['HTTP_REFERER'], :user_id => session[:user_id])
55
87
 
56
- These will be stored with the rally for the conversion and can get used for complex analytics down the line. (see Converts.meta)
88
+ These will be stored with the rally for the conversion and can get used for complex analytics down the line. (see Converts.meta)
57
89
 
58
- ### Switch variants
90
+ ### Switch variants
59
91
 
60
- Instead of just serving text, you can also serve flow control in Mountain Goat, like so:
92
+ Instead of just serving text, you can also serve flow control in Mountain Goat, like so:
61
93
 
62
- sv(:user_discount, :purchase_coffee) do |variant|
63
- variant.ten_percent do
64
- discount = 0.10
65
- end
94
+ sv(:user_discount, :purchase_coffee) do |variant|
66
95
 
67
- variant.big_winner do
68
- discount = 0.90
69
- end
96
+ variant.ten_percent do # "ten_percent" is the variant-name
97
+ discount = 0.10
98
+ end
99
+
100
+ variant.big_winner do
101
+ discount = 0.90
102
+ end
70
103
 
71
- variant.whomp_whomp do
72
- discount = 0.0
104
+ variant.whomp_whomp(0.5) do #reduce priority to 0.5 (default 1.0)
105
+ discount = 0.0
106
+ end
73
107
  end
74
- end
75
108
 
76
- Mountain goat will automatically break those down into three cases (:ten_percent, :big_winner, :whomp_whomp) and serve them out at random to the user.
109
+ Mountain goat will automatically break those down into three cases (:ten_percent, :big_winner, :whomp_whomp) and serve them out at random to the user (with whomp_whomp half as likely to be served as the others).
77
110
 
78
- ### Priorities
111
+ ### Priorities
79
112
 
80
- You may want to test certain items with a lower serve rate (bold new slogans). You can assign priorities to any metric variant. The change of a given metric variant being shown is
113
+ You may want to test certain items with a lower serve rate (bold new slogans). You can assign priorities to any metric variant. The change of a given metric variant being shown is
81
114
 
82
- my priority / sum(all priorities for this metric)
115
+ my priority / sum(all priorities for this metric)
83
116
 
84
117
  ## TODO
85
- - work on getting migrations better
118
+ - Better documentation (rdocs)
119
+ - Add namespacing to avoid conflicts
86
120
 
87
121
  ## Copyright
88
122
 
89
- Copyright (c) 2011 Geoffrey Hayes, drawn.to. See LICENSE for details.
123
+ Copyright (c) 2011 Geoffrey Hayes, drawn.to. Contact me, Geoff, <geoff@drawn.to> with any questions / ideas / enhacements. See LICENSE for details.
@@ -26,6 +26,7 @@ class MountainGoatController < ActionController::Base
26
26
 
27
27
  def verify_access
28
28
  return if session.has_key?(:mg_access) && session[:mg_access] == true
29
+ store_location
29
30
  redirect_to '/mg/login' and return
30
31
  end
31
32
 
@@ -15,4 +15,24 @@ class MountainGoatRalliesController < MountainGoatController
15
15
  format.html { }
16
16
  end
17
17
  end
18
+
19
+ def new_rallies
20
+ recent_rally = params[:recent_rally].to_i
21
+ convert = Convert.find(params[:convert_id].to_i) unless params[:convert_id].blank?
22
+
23
+ if convert
24
+ @rallies = convert.rallies.find(:all, :conditions => [ 'id > ?', recent_rally ], :order => "created_at DESC" )
25
+ else
26
+ @rallies = Rally.find(:all, :conditions => [ 'id > ?', recent_rally ], :order => "created_at DESC" )
27
+ end
28
+
29
+ if @rallies.count > 0
30
+ render :json => { :success => true,
31
+ :result => render_to_string(:partial => 'mountain_goat_rallies/rallies', :locals => { :rallies => @rallies } ),
32
+ :recent_rally_id => @rallies.first.id }
33
+ else
34
+ render :json => { :success => false }
35
+ end
36
+
37
+ end
18
38
  end
@@ -17,6 +17,7 @@ module MetricTracking
17
17
  map.resources :mountain_goat_converts, :has_many => [ :mountain_goat_metrics, :mountain_goat_rallies ]
18
18
  map.resources :mountain_goat_metrics, :has_many => :mountain_goat_metric_variants
19
19
  map.resources :mountain_goat_rallies
20
+ map.new_rallies '/mg/rallies/new', :controller => :mountain_goat_rallies, :action => :new_rallies
20
21
  map.fresh_metrics '/fresh-metrics', :controller => :mountain_goat_metrics, :action => :fresh_metrics
21
22
  map.connect '/mg/public/:file', :controller => :mountain_goat, :action => :fetch
22
23
  end
@@ -11,5 +11,38 @@
11
11
  $($(this).data('slider')).slideUp();
12
12
  }
13
13
  }).change();
14
+
15
+ if ($('.recent-rally[data-reload="true"]').size() > 0) {
16
+ setTimeout(function() { reloadRallies(); }, 3000);
17
+ }
18
+
19
+ $('.reload').click(function() { reloadRallies(); });
20
+
21
+ var reloadRallies = function() {
22
+ var rally_id = parseInt($('.recent-rally').data('rally-id'));
23
+ var convert_id = $('.recent-rally').data('convert-id');
24
+ if (rally_id) {
25
+ $.ajax({
26
+ url: '/mg/rallies/new',
27
+ data: { 'recent_rally': rally_id, 'convert_id': convert_id },
28
+ success: function(json) {
29
+ if (!json.success) {
30
+ console.log('No new events');
31
+ } else {
32
+ $('.recent-rally').data('rally-id', json.recent_rally_id);
33
+ $('.rally-list').prepend($(json.result));
34
+
35
+ $('.rally-list li:gt(100)').remove(); //only show 100 elements
36
+ }
37
+
38
+ if ($('.recent-rally[data-reload="true"]').size() > 0) {
39
+ setTimeout(function() { reloadRallies(); }, 3000);
40
+ }
41
+ }
42
+ });
43
+ }
44
+ };
14
45
  });
46
+
47
+
15
48
  })();
@@ -1,3 +1,3 @@
1
1
  class MountainGoat
2
- VERSION = "0.0.17"
2
+ VERSION = "0.0.18"
3
3
  end
@@ -0,0 +1,9 @@
1
+ <%# locals => rally %>
2
+
3
+ <li><%= rally.convert.name %> at <%= rally.created_at.to_s %>
4
+ (
5
+ <% rally.all_metas.each do |k,v| %>
6
+ <%= k %>: <%= v %>
7
+ <% end %>
8
+ )
9
+ </li>
@@ -0,0 +1,9 @@
1
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
2
+ <html>
3
+ <head>
4
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
5
+ <title>Untitled Document</title>
6
+ </head>
7
+ <body>
8
+ </body>
9
+ </html>
@@ -0,0 +1,22 @@
1
+
2
+
3
+ <div id="container-main" class="mt-rallies">
4
+ <div class="mountain-goat-panel">
5
+ <h1>Rallies <% if @convert %>for <%=h @convert.name %><% else %>for all Goals<% end %></h1>
6
+
7
+ <% if @rallies.count > 0 %>
8
+ <ul>
9
+ <% @rallies.each do |rally| %>
10
+ <li><%= rally.convert.name %> at <%= rally.created_at.to_s %></li>
11
+ (
12
+ <% rally.all_metas.each do |k,v| %>
13
+ <%= k %>: <%= v %>
14
+ <% end %>
15
+ )
16
+ <% end %>
17
+ </ul>
18
+ <% else %>
19
+ <h2>No rallies for yet this goal.</h2>
20
+ <% end %>
21
+ </div>
22
+ </div>
@@ -0,0 +1,5 @@
1
+ <%# locals => rallies %>
2
+
3
+ <% rallies.each do |rally| %>
4
+ <%= render :partial => 'mountain_goat_rallies/rally', :locals => { :rally => rally } %>
5
+ <% end %>
@@ -0,0 +1,9 @@
1
+ <%# locals => rally %>
2
+
3
+ <li><%= rally.convert.name %> at <%= rally.created_at.to_s %>
4
+ (
5
+ <% rally.all_metas.each do |k,v| %>
6
+ <%= k %>: <%= v %>
7
+ <% end %>
8
+ )
9
+ </li>
@@ -4,15 +4,13 @@
4
4
  <div class="mountain-goat-panel">
5
5
  <h1>Rallies <% if @convert %>for <%=h @convert.name %><% else %>for all Goals<% end %></h1>
6
6
 
7
+ <div class="recent-rally" data-reload="true" data-rally-id="<%= @rallies.first.id %>" data-convert-id="<%= @convert ? @convert.id : '' %>"></div>
8
+ <a href="javascript:void(0)" class="reload">Reload</a>
9
+
7
10
  <% if @rallies.count > 0 %>
8
- <ul>
11
+ <ul class="rally-list">
9
12
  <% @rallies.each do |rally| %>
10
- <li><%= rally.convert.name %> at <%= rally.created_at.to_s %></li>
11
- (
12
- <% rally.all_metas.each do |k,v| %>
13
- <%= k %>: <%= v %>
14
- <% end %>
15
- )
13
+ <%= render 'rally', :rally => rally %>
16
14
  <% end %>
17
15
  </ul>
18
16
  <% else %>
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mountain-goat
3
3
  version: !ruby/object:Gem::Version
4
- hash: 61
4
+ hash: 59
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 17
10
- version: 0.0.17
9
+ - 18
10
+ version: 0.0.18
11
11
  platform: ruby
12
12
  authors:
13
13
  - Geoffrey Hayes
@@ -118,6 +118,11 @@ files:
118
118
  - lib/mountain-goat/views/mountain_goat/mountain_goat_metrics/index.html.erb
119
119
  - lib/mountain-goat/views/mountain_goat/mountain_goat_metrics/new.html.erb
120
120
  - lib/mountain-goat/views/mountain_goat/mountain_goat_metrics/show.html.erb
121
+ - lib/mountain-goat/views/mountain_goat/mountain_goat_rallies/.tmp__rallies.html.erb.83814~
122
+ - lib/mountain-goat/views/mountain_goat/mountain_goat_rallies/.tmp__rally.html.erb.62757~
123
+ - lib/mountain-goat/views/mountain_goat/mountain_goat_rallies/.tmp_index.html.erb.1823~
124
+ - lib/mountain-goat/views/mountain_goat/mountain_goat_rallies/_rallies.html.erb
125
+ - lib/mountain-goat/views/mountain_goat/mountain_goat_rallies/_rally.html.erb
121
126
  - lib/mountain-goat/views/mountain_goat/mountain_goat_rallies/index.html.erb
122
127
  - mountain-goat.gemspec
123
128
  - test/fixtures/ci_metas.yml