moviepilot-gwo 0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +20 -0
- data/README.markdown +120 -0
- data/lib/gwo.rb +203 -0
- data/rails/init.rb +2 -0
- data/spec/lib/gwo_spec.rb +203 -0
- data/spec/spec_helper.rb +4 -0
- metadata +63 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Made by Many
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.markdown
ADDED
@@ -0,0 +1,120 @@
|
|
1
|
+
This is a Ruby on Rails plugin (gem) which simplifies Server-Side Dynamic Section Variations with
|
2
|
+
[Google Website Optimizer](http://www.google.com/websiteoptimizer) as described in the article
|
3
|
+
[Server-Side Dynamic Section Variations on gwotricks.com](http://www.gwotricks.com/2009/05/server-side-dynamic-section-variations.html)
|
4
|
+
|
5
|
+
== Features:
|
6
|
+
------------
|
7
|
+
|
8
|
+
* very good Ruby on Rails integration
|
9
|
+
* very simple to use
|
10
|
+
* support for several sections that should have different variants
|
11
|
+
* support for named and numbered sections
|
12
|
+
* include part of a page in more than one variant
|
13
|
+
* support for google analytics tracking
|
14
|
+
* kill-switch
|
15
|
+
* well tested
|
16
|
+
|
17
|
+
|
18
|
+
The 'Usage' may look long - but it's fairly straightforward and shouldn't take 5 mins.
|
19
|
+
|
20
|
+
Daniel Bornkessel gwo@bornkessel.com & Alex MacCaw - alex@madebymany.co.uk (original author)
|
21
|
+
|
22
|
+
== Usage
|
23
|
+
--------
|
24
|
+
|
25
|
+
To use GWO, you need two pages:
|
26
|
+
* A test page containing the multi variant sections
|
27
|
+
* A page that signifies conversion (i.e. account creation page)
|
28
|
+
|
29
|
+
[Signup for Google Website Optimizer and](http://www.google.com/websiteoptimizer):
|
30
|
+
1. Click create another experiment
|
31
|
+
2. Click multivariate experiment
|
32
|
+
3. Name it and enter the test/conversion urls
|
33
|
+
4. Select 'You will install and validate the JavaScript tags'
|
34
|
+
5. Ignore the scripts that are offered, but strip out your account id (uacct) and test id (both to be found in the Tracking Script).
|
35
|
+
They look like as follows:
|
36
|
+
var pageTracker=_gat._getTracker("UI-6882082-1");
|
37
|
+
pageTracker._trackPageview("/1662461989/test");
|
38
|
+
So, in this example the uacct is 'UA-6882082-1' and the test id is 1662461989.
|
39
|
+
6. Leave google and prepare your source code
|
40
|
+
7. Add the gwo_experiment tag around the code that is supposed to contain the variants (see the gwo_experiment documentation for
|
41
|
+
possible options)
|
42
|
+
8. in the gwo_experiment you can specify one or more sections your side can contain. Each section can have several
|
43
|
+
variants. So if you have for example 2 sections with each having 3 variants you would have 6 different possible
|
44
|
+
combinations on your page.
|
45
|
+
9. Create your gwo_sections, as in the example. The first parameter is the name of the section,
|
46
|
+
the second the name of the variant(s) in which the following code should be shown (see example code).
|
47
|
+
You can mix variants by just passing in more than one identifier. The
|
48
|
+
original variant has the reserved identifier :original (or 0 if you use numbers)
|
49
|
+
10. The variants can either be identified by numbers (starting at 0 for the original variant) or be named (see below how to
|
50
|
+
assign the names in the google web interface).
|
51
|
+
11. Add a gwo_conversion helper tag on your conversion page passing in your uacct and test id.
|
52
|
+
12. In order to validate the pages in the goole web interface, start rails, surf to the pages (variant and conversion page) you
|
53
|
+
just created and save each one locally.
|
54
|
+
13. back in the google web interface, validate your pages by using the 'offline validation' link and upload the two
|
55
|
+
pages you just saved
|
56
|
+
14. as a next step, define the sections. If you used named identifiers in you rails source code, put the the identifiers
|
57
|
+
name as the content of the variations in the web interface (i.e. the example below would have two variants (+ the original
|
58
|
+
variant); one variation would have the CONTENT (subject & name of the variants are not important) 'minimalistic' and the other
|
59
|
+
'with_sidebar_and_top_signup_box' (without the quotes)). If you use numbered identifiers, just create new variations and leave the
|
60
|
+
content empty.
|
61
|
+
15. finish up and start the experiment
|
62
|
+
16. lean back and let google collect data for you for the next few days ... go back an be shocked about the little number of
|
63
|
+
conversions you will probably get ;)
|
64
|
+
|
65
|
+
|
66
|
+
== Example
|
67
|
+
----------
|
68
|
+
... in haml:
|
69
|
+
|
70
|
+
= gwo_experiment("1662461989", "UA-6882082-1", :signup_box_test, :conditions => (signed_up? && country == "de")) do
|
71
|
+
= gwo_section(:signup_box_test, [:with_sidebar_and_top_signup_box, :minimalistic], :ga_tracking => true, :conditions => (signed_up? && country == "de")) do
|
72
|
+
= render :partial => 'gossib/signup'
|
73
|
+
%span I am only visible in the variants :with_sidebar_and_top_signup_box and :minimalistic
|
74
|
+
|
75
|
+
= gwo_section(:signup_box_test, [:original, :with_sidebar_and_top_signup_box], :conditions => (signed_up? && country == "de")) do
|
76
|
+
= render :partial => 'gossib/bookmark_menu'
|
77
|
+
= render :partial => 'gossip/pics', :locals => {:images => @article.images}
|
78
|
+
.box#
|
79
|
+
%span Hi hi ... I am not visible in :minimalistic
|
80
|
+
|
81
|
+
%span I am visible in every variation
|
82
|
+
|
83
|
+
= gwo_section(:signup_box_test, :original, :conditions => (signed_up? && country == "de")) do
|
84
|
+
%span I am only in the original page
|
85
|
+
|
86
|
+
... or in erb:
|
87
|
+
|
88
|
+
<% gwo_experiment("1662461989", "UA-6882082-1", :signup_box_test, :conditions => (signed_up? && country == "de")) do %>
|
89
|
+
<% render :partial => 'gossip/article.html.haml', :object => @article %>
|
90
|
+
|
91
|
+
<% gwo_section(:signup_box_test, [:with_sidebar_and_top_signup_box, :minimalistic], :conditions => (signed_up? && country == "de")) do %>
|
92
|
+
<%= render :partial => 'gossib/signup' %>
|
93
|
+
<span> I am only visible in the variants :with_sidebar_and_top_signup_box and :minimalistic</span>
|
94
|
+
<% end %>
|
95
|
+
|
96
|
+
<% gwo_section(:signup_box_test, [:original, :with_sidebar_and_top_signup_box], :conditions => (signed_up? && country == "de")) do %>
|
97
|
+
<%= render :partial => 'gossib/bookmark_menu' %>
|
98
|
+
<%= render :partial => 'gossip/pics', :locals => {:images => @article.images} %>
|
99
|
+
<div class="box">
|
100
|
+
<span> Hi hi ... I am not visible in :minimalistic</span>
|
101
|
+
<% end %>
|
102
|
+
|
103
|
+
<span> I am visible in every variation</span>
|
104
|
+
|
105
|
+
<% gwo_section(:signup_box_test, :original, :conditions => (signed_up? && country == "de")) do %>
|
106
|
+
<span> I am only in the original page</span>
|
107
|
+
<% end %>
|
108
|
+
<% end %>
|
109
|
+
|
110
|
+
|
111
|
+
== Conversion page:
|
112
|
+
------------------
|
113
|
+
... haml:
|
114
|
+
= gwo_conversion('UA-23902382-1', '1909920434')
|
115
|
+
|
116
|
+
... erb:
|
117
|
+
<%= gwo_conversion('UA-23902382-1', '1909920434') %>
|
118
|
+
|
119
|
+
|
120
|
+
Copyright (c) 2009 Made by Many, released under the MIT license
|
data/lib/gwo.rb
ADDED
@@ -0,0 +1,203 @@
|
|
1
|
+
# Author:: Alex MacCaw - alex AT madebymany DOT co DOT uk (original), Daniel Bornkessel - daniel AT bornkessel DOT com
|
2
|
+
# License:: MIT
|
3
|
+
# :include:README.markdown
|
4
|
+
#
|
5
|
+
#
|
6
|
+
|
7
|
+
require 'action_view/helpers/capture_helper'
|
8
|
+
module GWO
|
9
|
+
module Helper
|
10
|
+
|
11
|
+
include ::ActionView::Helpers::CaptureHelper
|
12
|
+
|
13
|
+
# start a gwo_experiment
|
14
|
+
#
|
15
|
+
# Params:
|
16
|
+
# * <b>id</b> the id of the experiment (in the google Tracking Script look for something like <tt>pageTracker._trackPageview("/<ID>/test");</tt> )
|
17
|
+
# * <b>uacct</b> account number (in the google Tracking Script look for something like <tt>var pageTracker=_gat._getTracker("<UACCT>");</tt> )
|
18
|
+
# * <b>sections</b> name of the section(s) your page will include; pass in one symbol/string or an array of symbols/strings here
|
19
|
+
# * <b>options</b> hash of possible options:
|
20
|
+
# * <b>:conditions</b> if set to false, the experiment won't be executed -- only the source code of the :original (or 0) variants would be shown. No JavaScript code will be produced. It serves as a kill switch for the gwo experiment. If, for example, you only want to execute an experiment for users that are not logged in, you could pass <tt>:conditions => !logged_in?</tt> here.
|
21
|
+
# * <b>:ga_tracking</b> executes a <tt>trackPageView(...)</tt> for google analytics tracking. It adds parameters to the URL, so you can identify which variant (or combination) the user saw (handy if you want to check on the exit rate with GA)
|
22
|
+
# * <b>:ga_base_url</b> set a static base URL for google analytics: Say your variant is in a 'show' view, GA would track a lot of different URLs (as the show view url contains the ID). If you are just interested about the variants in GA, set a static URL here (i.e. hbp://<your domain>/ab-testing ) and GA tracking will always be that static domain + parameters with information about the variant the user saw.
|
23
|
+
def gwo_experiment(id, uacct, sections = [], options = {}, &block)
|
24
|
+
options = {
|
25
|
+
:conditions => true,
|
26
|
+
:ga_tracking => false,
|
27
|
+
:ga_base_url => nil
|
28
|
+
}.update(options)
|
29
|
+
|
30
|
+
src = gwo_start(id, sections, options)
|
31
|
+
src += capture(&block)
|
32
|
+
src += gwo_end(id, uacct, options)
|
33
|
+
src
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
# to be included on the conversion page.
|
38
|
+
#
|
39
|
+
# Params:
|
40
|
+
# * <b>id</b> & <b>uacct</b> see gwo_experiment
|
41
|
+
# * <b>options</b>
|
42
|
+
# * :conditions as in gwo_experiment
|
43
|
+
def gwo_conversion(id, uacct, options = {})
|
44
|
+
options = {
|
45
|
+
:conditions => true
|
46
|
+
}.update(options)
|
47
|
+
|
48
|
+
return js_logger("skipping conversion snippet: a/b variation test switched off", true) if options[:conditions] == false
|
49
|
+
|
50
|
+
%{
|
51
|
+
<script type="text/javascript">
|
52
|
+
#{ js_logger("'conversion for test with id #{id} and uacct #{uacct}'") }
|
53
|
+
if(typeof(_gat)!='object')document.write('<sc'+'ript src="http'+
|
54
|
+
(document.location.protocol=='https:'?'s://ssl':'://www')+
|
55
|
+
'.google-analytics.com/ga.js"></sc'+'ript>')</script>
|
56
|
+
<script type="text/javascript">
|
57
|
+
try {
|
58
|
+
var pageTracker=_gat._getTracker("#{uacct}");
|
59
|
+
pageTracker._trackPageview("/#{id}/goal");
|
60
|
+
}catch(err){}</script>
|
61
|
+
}
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
# identify a section which is only visible in certain variants
|
67
|
+
#
|
68
|
+
# Params:
|
69
|
+
# * <b>section</b> name of the section
|
70
|
+
# * <b>variation_ids</b> identifiers of the variants in which this content is to be shown. Can be either a name of the variant (== the <b><i>content</i></b> of a variant in the GWO web interface) or a number. The original content has the reserved name <tt>:original</tt> or the number <tt>0</tt> respectivly. If the content should be shown in more than one variant, pass in an array of identifiers. Mixing numbered and named variant ids will result in an exception.
|
71
|
+
# * <b>options</b>
|
72
|
+
# * :conditions as in gwo_experiment
|
73
|
+
def gwo_section(section = "gwo_section", variation_ids = nil, options = {}, &block)
|
74
|
+
options = {
|
75
|
+
:conditions => true
|
76
|
+
}.update(options)
|
77
|
+
|
78
|
+
variation_ids = [*variation_ids].compact
|
79
|
+
src = ""
|
80
|
+
if is_default_section?(variation_ids)
|
81
|
+
if options[:conditions] == false
|
82
|
+
src += capture(&block)
|
83
|
+
else
|
84
|
+
conditions = (named_variations?(variation_ids) ? variation_ids.map{|x| "GWO_#{section}_name != \"#{x}\""} : variation_ids.map{|x| "GWO_#{section}_number != #{x}"}).join(" && ")
|
85
|
+
|
86
|
+
src += %{ <script>
|
87
|
+
if ( #{ conditions } ) document.write('<no' + 'script>');
|
88
|
+
</script>
|
89
|
+
#{capture(&block) if block_given?}
|
90
|
+
</noscript>
|
91
|
+
}
|
92
|
+
end
|
93
|
+
elsif options[:conditions] == true
|
94
|
+
if !variation_ids.empty?
|
95
|
+
conditions = (named_variations?(variation_ids) ? variation_ids.map{|x| "GWO_#{section}_name == \"#{x}\""} : variation_ids.map{|x| "GWO_#{section}_number == #{x}"}).join(" || ")
|
96
|
+
|
97
|
+
src += %{<script>
|
98
|
+
if ( #{ conditions } ) document.write('</noscript a="');
|
99
|
+
</script><!--">
|
100
|
+
#{capture(&block) if block_given?}
|
101
|
+
<script>document.write('<'+'!'+'-'+'-')</script>-->
|
102
|
+
}
|
103
|
+
end
|
104
|
+
else
|
105
|
+
src = js_logger("skipping snippet for #{variation_ids.join(", ")} variations: a/b variation test switched off", true)
|
106
|
+
end
|
107
|
+
src
|
108
|
+
end
|
109
|
+
|
110
|
+
private
|
111
|
+
def js_logger(text, with_js_tag = false)
|
112
|
+
return "if(typeof(console.log) == 'function') console.log(#{text});" if RAILS_ENV != "test" && RAILS_ENV != "production" && !with_js_tag
|
113
|
+
return "<script type='text/javascript'>if(typeof(console.log) == 'function') console.log(\"#{text}\");</script>" if RAILS_ENV != "test" && RAILS_ENV != "production" && with_js_tag
|
114
|
+
return ""
|
115
|
+
end
|
116
|
+
|
117
|
+
def gwo_start(id, sections = [], options = {})
|
118
|
+
|
119
|
+
return js_logger("skipping start snippet: a/b variation test switched off", true) if options[:conditions] == false
|
120
|
+
|
121
|
+
|
122
|
+
sections = [*sections].compact.empty? ? ["gwo_section"] : [*sections]
|
123
|
+
src = %{
|
124
|
+
<script type='text/javascript'>
|
125
|
+
function utmx_section(){}function utmx(){}
|
126
|
+
(function(){var k='#{id}',d=document,l=d.location,c=d.cookie;function f(n){
|
127
|
+
if(c){var i=c.indexOf(n+'=');if(i>-1){var j=c.indexOf(';',i);return c.substring(i+n.
|
128
|
+
length+1,j<0?c.length:j)}}}var x=f('__utmx'),xx=f('__utmxx'),h=l.hash;
|
129
|
+
d.write('<sc'+'ript src="'+
|
130
|
+
'http'+(l.protocol=='https:'?'s://ssl':'://www')+'.google-analytics.com'
|
131
|
+
+'/siteopt.js?v=1&utmxkey='+k+'&utmx='+(x?x:'')+'&utmxx='+(xx?xx:'')+'&utmxtime='
|
132
|
+
+new Date().valueOf()+(h?'&utmxhash='+escape(h.substr(1)):'')+
|
133
|
+
'" type="text/javascript" charset="utf-8"></sc'+'ript>')})();
|
134
|
+
</script>
|
135
|
+
}
|
136
|
+
|
137
|
+
google_analytics_info = "";
|
138
|
+
section_definitions = "";
|
139
|
+
variable_assignments = "";
|
140
|
+
|
141
|
+
sections.each do |section|
|
142
|
+
section_definitions += "<!-- utmx section name='#{section}' -->\n"
|
143
|
+
|
144
|
+
variable_assignments += %{\
|
145
|
+
var GWO_#{section}_name = utmx("variation_content", "#{section}");\
|
146
|
+
if( GWO_#{section}_name == undefined) GWO_#{section}_name = 'original';\
|
147
|
+
\
|
148
|
+
var GWO_#{section}_number = utmx("variation_number", "#{section}");\
|
149
|
+
if( GWO_#{section}_number == undefined) GWO_#{section}_number = 0;\
|
150
|
+
\
|
151
|
+
#{ js_logger("'variant: ' + GWO_#{section}_name") }\
|
152
|
+
}
|
153
|
+
google_analytics_info += "google_analytics_info += \"&GWO_#{section}_name=\" + GWO_#{section}_name;" if options[:ga_tracking]
|
154
|
+
end
|
155
|
+
|
156
|
+
if options[:ga_tracking]
|
157
|
+
base_url = options[:ga_base_url] ? "\"#{options[:ga_base_url]}\"" : "document.location"
|
158
|
+
variable_assignments += %{\
|
159
|
+
window.onload = function(){ \
|
160
|
+
var google_analytics_info = ''; #{google_analytics_info}; if(typeof(trackPageView) == 'function') {\
|
161
|
+
trackPageView(#{base_url} + "?ab_test=true" + google_analytics_info);\
|
162
|
+
#{js_logger("#{base_url} + \"?ab_test=true\" + google_analytics_info")}\
|
163
|
+
}\
|
164
|
+
}\
|
165
|
+
}
|
166
|
+
end
|
167
|
+
|
168
|
+
variable_assignments = "<script type='text/javascript'>#{variable_assignments}</script>";
|
169
|
+
|
170
|
+
"#{src}#{section_definitions}#{variable_assignments}"
|
171
|
+
end
|
172
|
+
|
173
|
+
def gwo_end(id, uacct, options)
|
174
|
+
return js_logger("skipping end snippet: a/b variation test switched off", true) if options[:conditions] == false
|
175
|
+
|
176
|
+
%{<script type="text/javascript">
|
177
|
+
if(typeof(_gat)!='object')document.write('<sc'+'ript src="http'+
|
178
|
+
(document.location.protocol=='https:'?'s://ssl':'://www')+
|
179
|
+
'.google-analytics.com/ga.js"></sc'+'ript>')</script>
|
180
|
+
<script type="text/javascript">
|
181
|
+
try {
|
182
|
+
var pageTracker=_gat._getTracker("#{uacct}");
|
183
|
+
pageTracker._trackPageview("/#{id}/test");
|
184
|
+
}catch(err){}</script>
|
185
|
+
}
|
186
|
+
|
187
|
+
end
|
188
|
+
|
189
|
+
def is_default_section?(variation_ids)
|
190
|
+
variation_ids.include?(:original) || variation_ids.include?(0)
|
191
|
+
end
|
192
|
+
|
193
|
+
def named_variations?(variation_ids)
|
194
|
+
raise RuntimeError.new("variation ids can only be either string, symbols or numbers") if [*variation_ids].compact.empty? # catch empty hashes and nil
|
195
|
+
|
196
|
+
return false if [1, *variation_ids].map(&:class).uniq.length == 1 # all variation_ids are FixNums
|
197
|
+
return true if ["string", :symbol, *variation_ids].map(&:class).uniq.length == 2 # all variation_ids are either string or symbol
|
198
|
+
|
199
|
+
raise RuntimeError.new("variation ids can only be either string, symbols or numbers")
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
end
|
data/rails/init.rb
ADDED
@@ -0,0 +1,203 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
require 'lib/gwo'
|
3
|
+
|
4
|
+
describe GWO do
|
5
|
+
include GWO::Helper
|
6
|
+
|
7
|
+
describe "google analytics stuff" do
|
8
|
+
it "should not create any google analytics stuff by default" do
|
9
|
+
gwo_start("gwo_id", "section_name").should_not =~ /google_analytics_info \+= \"&GWO_section_name_name=\" \+ GWO_section_name_name;/
|
10
|
+
gwo_start("gwo_id", "section_name").should_not =~ /trackPageView\(document.location \+ \"\?ab_test=true\" \+ google_analytics_info\)/
|
11
|
+
end
|
12
|
+
it "should not create google analytics stuff if option is disabled" do
|
13
|
+
gwo_start("gwo_id", "section_name", :ga_tracking => false).should_not =~ /google_analytics_info \+= \"&GWO_section_name_name=\" \+ GWO_section_name_name;/
|
14
|
+
gwo_start("gwo_id", "section_name", :ga_tracking => false).should_not =~ /trackPageView\(document.location \+ \"\?ab_test=true\" \+ google_analytics_info\)/
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should create correct google analytics stuff for default urls" do
|
18
|
+
gwo_start("gwo_id", "section_name", :ga_tracking => true).should =~ /google_analytics_info \+= \"&GWO_section_name_name=\" \+ GWO_section_name_name;/
|
19
|
+
gwo_start("gwo_id", "section_name", :ga_tracking => true).should =~ /trackPageView\(document.location \+ \"\?ab_test=true\" \+ google_analytics_info\)/
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should create correct google analytics stuff for static urls" do
|
23
|
+
gwo_start("gwo_id", "section_name", :ga_tracking => true, :ga_base_url => "http://example.com").should =~ /google_analytics_info \+= \"&GWO_section_name_name=\" \+ GWO_section_name_name;/
|
24
|
+
gwo_start("gwo_id", "section_name", :ga_tracking => true, :ga_base_url => "http://example.com").should =~ /trackPageView\(\"http:\/\/example\.com\" \+ \"\?ab_test=true\" \+ google_analytics_info\)/
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should create correct google analytics stuff for several sections" do
|
28
|
+
gwo_start("gwo_id", ["section_name1", "section_name2", "section_name3"], :ga_tracking => true).should =~ /google_analytics_info \+= \"&GWO_section_name1_name=\" \+ GWO_section_name1_name;/
|
29
|
+
gwo_start("gwo_id", ["section_name1", "section_name2", "section_name3"], :ga_tracking => true).should =~ /google_analytics_info \+= \"&GWO_section_name2_name=\" \+ GWO_section_name2_name;/
|
30
|
+
gwo_start("gwo_id", ["section_name1", "section_name2", "section_name3"], :ga_tracking => true).should =~ /google_analytics_info \+= \"&GWO_section_name3_name=\" \+ GWO_section_name3_name;/
|
31
|
+
gwo_start("gwo_id", ["section_name1", "section_name2", "section_name3"], :ga_tracking => true).should =~ /trackPageView\(document.location \+ \"\?ab_test=true\" \+ google_analytics_info\)/
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "named_variations? method" do
|
37
|
+
it "should return false if one numbered variation is passed in" do
|
38
|
+
named_variations?(1).should == false
|
39
|
+
end
|
40
|
+
it "should return false if variations are numbered" do
|
41
|
+
named_variations?([1,2,3]).should == false
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should return true if one string is passed in" do
|
45
|
+
named_variations?("string").should == true
|
46
|
+
end
|
47
|
+
it "should return true if one symbol is passed in" do
|
48
|
+
named_variations?(:symbol).should == true
|
49
|
+
end
|
50
|
+
it "should return true if symbols and strings are mixed" do
|
51
|
+
named_variations?([:symbol, "string", :symbol2]).should == true
|
52
|
+
end
|
53
|
+
it "should throw an exception if numbers and strings are mixed" do
|
54
|
+
lambda {named_variations?([1, :symbol])}.should raise_error(RuntimeError)
|
55
|
+
lambda {named_variations?([1, "string"])}.should raise_error(RuntimeError)
|
56
|
+
lambda {named_variations?([1, "string", :symbol])}.should raise_error(RuntimeError)
|
57
|
+
end
|
58
|
+
it "should throw an exception if one obscure object is passed in" do
|
59
|
+
lambda {named_variations?(Hash.new)}.should raise_error(RuntimeError)
|
60
|
+
lambda {named_variations?(RuntimeError.new)}.should raise_error(RuntimeError)
|
61
|
+
end
|
62
|
+
it "should throw an exception if an array of obscure object is passed in" do
|
63
|
+
lambda {named_variations?([{}, {}])}.should raise_error(RuntimeError)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe "gwo_start method" do
|
68
|
+
it "should produce correct output" do
|
69
|
+
gwo_start("gwo_id", "section_name").should =~ /utmx section name='section_name'/
|
70
|
+
gwo_start("gwo_id", "section_name").should =~ /utmx\(\"variation_content\", \"section_name\"\)/
|
71
|
+
gwo_start("gwo_id", "section_name").should =~ /utmx\(\"variation_number\", \"section_name\"\)/
|
72
|
+
gwo_start("gwo_id", "section_name").should =~ /k='gwo_id'/
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should work with just the id parameter set" do
|
76
|
+
gwo_start("gwo_id").should =~ /k='gwo_id'/
|
77
|
+
gwo_start("gwo_id").should =~ /utmx section name='gwo_section'/
|
78
|
+
gwo_start("gwo_id").should =~ /utmx\(\"variation_content\", \"gwo_section\"\)/
|
79
|
+
gwo_start("gwo_id").should =~ /utmx\(\"variation_number\", \"gwo_section\"\)/
|
80
|
+
gwo_start("gwo_id", nil).should =~ /utmx section name='gwo_section'/
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should work with one single section ... section is a symbol" do
|
84
|
+
gwo_start("gwo_id", :section_name).should =~ /utmx section name='section_name'/
|
85
|
+
gwo_start("gwo_id", :section_name).should =~ /utmx\(\"variation_content\", \"section_name\"\)/
|
86
|
+
gwo_start("gwo_id", :section_name).should =~ /utmx\(\"variation_number\", \"section_name\"\)/
|
87
|
+
gwo_start("gwo_id", :section_name).should =~ /k='gwo_id'/
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should work with an array of section" do
|
91
|
+
gwo_start("gwo_id", ["body",:content,"footer"]).should =~ /utmx section name='body'/
|
92
|
+
gwo_start("gwo_id", ["body",:content,"footer"]).should =~ /utmx section name='content'/
|
93
|
+
gwo_start("gwo_id", ["body",:content,"footer"]).should =~ /utmx section name='footer'/
|
94
|
+
|
95
|
+
gwo_start("gwo_id", ["body",:content,"footer"]).should =~ /utmx\(\"variation_content\", \"body\"\)/
|
96
|
+
gwo_start("gwo_id", ["body",:content,"footer"]).should =~ /utmx\(\"variation_content\", \"content\"\)/
|
97
|
+
gwo_start("gwo_id", ["body",:content,"footer"]).should =~ /utmx\(\"variation_content\", \"footer\"\)/
|
98
|
+
|
99
|
+
gwo_start("gwo_id", ["body",:content,"footer"]).should =~ /utmx\(\"variation_number\", \"body\"\)/
|
100
|
+
gwo_start("gwo_id", ["body",:content,"footer"]).should =~ /utmx\(\"variation_number\", \"content\"\)/
|
101
|
+
gwo_start("gwo_id", ["body",:content,"footer"]).should =~ /utmx\(\"variation_number\", \"footer\"\)/
|
102
|
+
end
|
103
|
+
|
104
|
+
it "should return nothing when conditions return false" do
|
105
|
+
gwo_start("id", [], {:conditions => false}).should == ""
|
106
|
+
gwo_start("gwo_id", ["body",:content,"footer"], :conditions => false).should == ""
|
107
|
+
|
108
|
+
gwo_start("gwo_id", ["body",:content,"footer"], {:conditions => false}).should_not =~ /utmx\(\"variation_content\", \"body\"\)/
|
109
|
+
gwo_start("gwo_id", ["body",:content,"footer"], {:conditions => false}).should_not =~ /utmx\(\"variation_content\", \"content\"\)/
|
110
|
+
gwo_start("gwo_id", ["body",:content,"footer"], {:conditions => false}).should_not =~ /utmx\(\"variation_content\", \"footer\"\)/
|
111
|
+
|
112
|
+
gwo_start("gwo_id", ["body",:content,"footer"], :conditions => false).should_not =~ /utmx\(\"variation_number\", \"body\"\)/
|
113
|
+
gwo_start("gwo_id", ["body",:content,"footer"], :conditions => false).should_not =~ /utmx\(\"variation_number\", \"content\"\)/
|
114
|
+
gwo_start("gwo_id", ["body",:content,"footer"], :conditions => false).should_not =~ /utmx\(\"variation_number\", \"footer\"\)/
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
describe "gwo_end method" do
|
119
|
+
it "should produce correct output" do
|
120
|
+
gwo_end("gwo_id", "gwo_uacct", :conditions => true).should =~ /getTracker\(\"gwo_uacct\"\)/
|
121
|
+
gwo_end("gwo_id", "gwo_uacct", :conditions => true).should =~ /trackPageview\(\"\/gwo_id\/test\"\)/
|
122
|
+
end
|
123
|
+
|
124
|
+
it "should return nothing if conditions are not met" do
|
125
|
+
gwo_end("gwo_id", "gwo_uacct", {:conditions => false}).should_not =~ /getTracker\(\"gwo_uacct\"\)/
|
126
|
+
gwo_end("gwo_id", "gwo_uacct", :conditions => false).should == ""
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
describe "gw_conversion method" do
|
131
|
+
it "should produce correct output" do
|
132
|
+
gwo_conversion("gwo_id", "gwo_uacct").should =~ /getTracker\(\"gwo_uacct\"\)/
|
133
|
+
gwo_conversion("gwo_id", "gwo_uacct").should =~ /trackPageview\(\"\/gwo_id\/goal\"\)/
|
134
|
+
end
|
135
|
+
|
136
|
+
it "should return nothing when conditions are not met" do
|
137
|
+
gwo_conversion("gwo_id", "gwo_uacct", {:conditions => false}).should == ""
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
describe "gwo_section method with named sections" do
|
142
|
+
|
143
|
+
it "should return nothing when conditions are not met and the variation is not the original" do
|
144
|
+
gwo_section("gwo_section", ["foo","bar"], {:conditions => false}).should == ""
|
145
|
+
end
|
146
|
+
|
147
|
+
it "should return original output without javascript if conditions are not met and original is the variation " do
|
148
|
+
gwo_section("gwo_section", :original, {:conditions => false}) { "this is the content" }.should == "this is the content"
|
149
|
+
end
|
150
|
+
|
151
|
+
it "should return original output with javascript if ignore is unset and original is the variation " do
|
152
|
+
gwo_section("gwo_section", :original) { "this is the content" }.should =~ /this is the content/
|
153
|
+
gwo_section("gwo_section", :original) { "this is the content" }.should =~ /( GWO_gwo_section_name != \"original\" )/
|
154
|
+
end
|
155
|
+
|
156
|
+
it "should only write one javascript block if the section is used for original and variations" do
|
157
|
+
gwo_section("section", [:original, :variation1, :variation2]) { "this is the content" }.should =~ /this is the content/
|
158
|
+
gwo_section("section", [:original, :variation1, :variation2]) { "this is the content" }.should =~ /( GWO_section_name != \"original\" && GWO_section_name != \"variation1\" && GWO_section_name != \"variation2\" )/
|
159
|
+
end
|
160
|
+
|
161
|
+
it "should write block for one variant" do
|
162
|
+
gwo_section("section",:testing) { "this is the content" }.should =~ /this is the content/
|
163
|
+
gwo_section("section",:testing) { "this is the content" }.should =~ /( GWO_section_name == \"testing\" )/
|
164
|
+
end
|
165
|
+
|
166
|
+
it "should write one block but enabled for all given variants " do
|
167
|
+
gwo_section("section",[:testing, :still_testing]) { "this is the content" }.should =~ /this is the content/
|
168
|
+
gwo_section("section",[:testing, :still_testing]) { "this is the content" }.should =~ /( GWO_section_name == \"testing\" || GWO_section_name == \"still_testing\" )/
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
describe "gwo_section method with numbered sections" do
|
173
|
+
|
174
|
+
it "should return nothing when conditions are not met and the variation is not the original" do
|
175
|
+
gwo_section("gwo_section", [1, 2], {:conditions => false}).should == ""
|
176
|
+
end
|
177
|
+
|
178
|
+
it "should return original output without javascript if conditions are not met and original is the variation " do
|
179
|
+
gwo_section("gwo_section", 0, {:conditions => false}) { "this is the content" }.should == "this is the content"
|
180
|
+
end
|
181
|
+
|
182
|
+
it "should return original output with javascript if ignore is unset and original is the variation " do
|
183
|
+
gwo_section("gwo_section", 0) { "this is the content" }.should =~ /this is the content/
|
184
|
+
gwo_section("gwo_section", 0) { "this is the content" }.should =~ /( GWO_gwo_section_number != 0 )/
|
185
|
+
end
|
186
|
+
|
187
|
+
it "should only write one javascript block if the section is used for original and variations" do
|
188
|
+
gwo_section("section", [0, 1, 2]) { "this is the content" }.should =~ /this is the content/
|
189
|
+
gwo_section("section", [0, 1, 2]) { "this is the content" }.should =~ /( GWO_section_number != 0 && GWO_section_number != 1 && GWO_section_number != 2 )/
|
190
|
+
end
|
191
|
+
|
192
|
+
it "should write block for one variant" do
|
193
|
+
gwo_section("section",1) { "this is the content" }.should =~ /this is the content/
|
194
|
+
gwo_section("section",1) { "this is the content" }.should =~ /( GWO_section_number == 1 )/
|
195
|
+
end
|
196
|
+
|
197
|
+
it "should write one block but enabled for all given variants " do
|
198
|
+
gwo_section("section",[1, 2]) { "this is the content" }.should =~ /this is the content/
|
199
|
+
gwo_section("section",[1, 2]) { "this is the content" }.should =~ /( GWO_section_number == 1 || GWO_section_number == 2 )/
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: moviepilot-gwo
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: "0.1"
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Alex MacCaw
|
8
|
+
- Daniel Bornkessel
|
9
|
+
- Johannes Mentz
|
10
|
+
- Yan Minagawa
|
11
|
+
autorequire:
|
12
|
+
bindir: bin
|
13
|
+
cert_chain: []
|
14
|
+
|
15
|
+
date: 2009-09-11 00:00:00 -07:00
|
16
|
+
default_executable:
|
17
|
+
dependencies: []
|
18
|
+
|
19
|
+
description:
|
20
|
+
email: daniel@bornkessel.com
|
21
|
+
executables: []
|
22
|
+
|
23
|
+
extensions: []
|
24
|
+
|
25
|
+
extra_rdoc_files:
|
26
|
+
- README.markdown
|
27
|
+
files:
|
28
|
+
- lib/gwo.rb
|
29
|
+
- MIT-LICENSE
|
30
|
+
- README.markdown
|
31
|
+
- spec/lib/gwo_spec.rb
|
32
|
+
- spec/spec_helper.rb
|
33
|
+
- rails/init.rb
|
34
|
+
has_rdoc: true
|
35
|
+
homepage: http://github.com/kesselborn/gwo
|
36
|
+
licenses:
|
37
|
+
post_install_message:
|
38
|
+
rdoc_options:
|
39
|
+
- --line-numbers
|
40
|
+
- --inline-source
|
41
|
+
require_paths:
|
42
|
+
- lib
|
43
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: "0"
|
48
|
+
version:
|
49
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: "0"
|
54
|
+
version:
|
55
|
+
requirements: []
|
56
|
+
|
57
|
+
rubyforge_project:
|
58
|
+
rubygems_version: 1.3.5
|
59
|
+
signing_key:
|
60
|
+
specification_version: 2
|
61
|
+
summary: Plugin to easily make use of Server-Side Dynamic Section Variations with Google Web Optimizer
|
62
|
+
test_files: []
|
63
|
+
|