rack-tracker 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +1 -0
- data/CHANGELOG.md +11 -0
- data/README.md +101 -3
- data/lib/rack/tracker.rb +2 -0
- data/lib/rack/tracker/facebook/facebook.rb +1 -1
- data/lib/rack/tracker/go_squared/go_squared.rb +1 -1
- data/lib/rack/tracker/google_adwords_conversion/google_adwords_conversion.rb +15 -0
- data/lib/rack/tracker/google_adwords_conversion/template/google_adwords_conversion.erb +18 -0
- data/lib/rack/tracker/google_analytics/google_analytics.rb +31 -2
- data/lib/rack/tracker/google_analytics/template/google_analytics.erb +11 -17
- data/lib/rack/tracker/google_tag_manager/google_tag_manager.rb +33 -0
- data/lib/rack/tracker/google_tag_manager/template/google_tag_manager.erb +19 -0
- data/lib/rack/tracker/handler.rb +4 -2
- data/lib/rack/tracker/handler_delegator.rb +1 -0
- data/lib/rack/tracker/version.rb +1 -1
- data/spec/fixtures/track_all_the_things.erb +1 -1
- data/spec/handler/facebook_spec.rb +6 -5
- data/spec/handler/go_squared_spec.rb +2 -2
- data/spec/handler/google_adwords_conversion_spec.rb +38 -0
- data/spec/handler/google_analytics_spec.rb +142 -9
- data/spec/handler/google_tag_manager_spec.rb +42 -0
- data/spec/integration/google_adwords_conversion_integration_spec.rb +18 -0
- data/spec/integration/google_analytics_integration_spec.rb +19 -4
- data/spec/integration/google_tag_manager_integration_spec.rb +18 -0
- data/spec/spec_helper.rb +1 -0
- data/spec/support/metal_controller.rb +15 -0
- data/spec/tracker/controller_spec.rb +5 -5
- metadata +38 -26
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 06a5db11fbd86405523dbc25c7be6f8b81f2149d
|
4
|
+
data.tar.gz: 900ce6c698fe6db41c3cf073bf3c523e3056a366
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 300d2b933c171c031439480702b5e64cf824d25fc8d4e2007d6eb2d09d9852447306b5a56621b520367b20bcbafeafc967cd0ac61f04a28faa24b0e02a680202
|
7
|
+
data.tar.gz: 4f2e384af4d3a3da6fd48f2210f11a92c37b31adb156f47cea6f104743720717f8df2a05965c2935cd5456ba59820dd8c4049f4d985b78caa572e06210d8e87d
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,14 @@
|
|
1
|
+
# master
|
2
|
+
|
3
|
+
# 0.4.0
|
4
|
+
|
5
|
+
* [BUGFIX] store event objects as hashes so they can be safely serialized using JSON (default since rails 4.1) #13
|
6
|
+
* added support for Google Analytics User ID feature #15
|
7
|
+
* added support for Google adwords conversion #24
|
8
|
+
* added support for Google Tag Manager feature #29
|
9
|
+
* added support for Google Analytics custom metrics and parameters #31 (thx @mnin)
|
10
|
+
* added support for Google Enhanced Ecommerce #32 (thx @mnin)
|
11
|
+
|
1
12
|
# 0.3.0
|
2
13
|
|
3
14
|
* [ENHANCEMENT] google analytics cookieDomain renamed to cookie_domain
|
data/README.md
CHANGED
@@ -21,6 +21,7 @@ in your application. It's easy to add your own [custom handlers](#custom-handler
|
|
21
21
|
but to get you started we're shipping support for the following services out of the box:
|
22
22
|
|
23
23
|
* [Google Analytics](#google-analytics)
|
24
|
+
* [Google Tag Manager](#google-tag-manager)
|
24
25
|
* [Facebook](#facebook)
|
25
26
|
* [Visual Website Optimizer (VWO)](#visual-website-optimizer-vwo)
|
26
27
|
* [GoSquared](#gosquared)
|
@@ -75,7 +76,7 @@ to inject arbitrary events into the request environment.
|
|
75
76
|
```ruby
|
76
77
|
request.env['tracker'] = {
|
77
78
|
'google_analytics' => [
|
78
|
-
|
79
|
+
{ 'class_name' => 'Send', 'category' => 'Users', 'action' => 'Login', 'label' => 'Standard' }
|
79
80
|
]
|
80
81
|
}
|
81
82
|
```
|
@@ -83,12 +84,14 @@ request.env['tracker'] = {
|
|
83
84
|
### Google Analytics
|
84
85
|
|
85
86
|
* `:anonymize_ip` - sets the tracker to remove the last octet from all IP addresses, see https://developers.google.com/analytics/devguides/collection/gajs/methods/gaJSApi_gat?hl=de#_gat._anonymizeIp for details.
|
86
|
-
* `:cookie_domain` - sets the domain name for the GATC cookies.
|
87
|
+
* `:cookie_domain` - sets the domain name for the [GATC cookies](https://developers.google.com/analytics/devguides/collection/analyticsjs/domains#implementation). If not set its the website domain, with the www. prefix removed.
|
88
|
+
* `:user_id` - defines a proc to set the [userId](https://developers.google.com/analytics/devguides/collection/analyticsjs/user-id). Ex: `user_id: lambda { |env| env['rack.session']['user_id'] }` would return the user_id from the session.
|
87
89
|
* `:site_speed_sample_rate` - Defines a new sample set size for Site Speed data collection, see https://developers.google.com/analytics/devguides/collection/gajs/methods/gaJSApiBasicConfiguration?hl=de#_gat.GA_Tracker_._setSiteSpeedSampleRate
|
88
90
|
* `:adjusted_bounce_rate_timeouts` - An array of times in seconds that the tracker will use to set timeouts for adjusted bounce rate tracking. See http://analytics.blogspot.ca/2012/07/tracking-adjusted-bounce-rate-in-google.html for details.
|
89
91
|
* `:enhanced_link_attribution` - Enables [Enhanced Link Attribution](https://developers.google.com/analytics/devguides/collection/analyticsjs/advanced#enhancedlink).
|
90
92
|
* `:advertising` - Enables [Display Features](https://developers.google.com/analytics/devguides/collection/analyticsjs/display-features).
|
91
93
|
* `:ecommerce` - Enables [Ecommerce Tracking](https://developers.google.com/analytics/devguides/collection/analyticsjs/ecommerce).
|
94
|
+
* `:enhanced_ecommerce` - Enables [Enhanced Ecommerce Tracking](https://developers.google.com/analytics/devguides/collection/analyticsjs/enhanced-ecommerce)
|
92
95
|
|
93
96
|
#### Events
|
94
97
|
|
@@ -108,6 +111,54 @@ It will render the following to the site source:
|
|
108
111
|
ga('send', { 'hitType': 'event', 'eventCategory': 'button', 'eventAction': 'click', 'eventLabel': 'nav-buttons', 'value': 'X' })
|
109
112
|
```
|
110
113
|
|
114
|
+
#### Parameters
|
115
|
+
|
116
|
+
You can set parameters in your controller too:
|
117
|
+
|
118
|
+
```ruby
|
119
|
+
def show
|
120
|
+
tracker do |t|
|
121
|
+
t.google_analytics :parameter, { dimension1: 'pink' }
|
122
|
+
end
|
123
|
+
end
|
124
|
+
```
|
125
|
+
|
126
|
+
Will render this:
|
127
|
+
|
128
|
+
```javascript
|
129
|
+
ga('set', 'dimension1', 'pink');
|
130
|
+
```
|
131
|
+
|
132
|
+
|
133
|
+
|
134
|
+
#### Enhanced Ecommerce
|
135
|
+
|
136
|
+
You can set parameters in your controller:
|
137
|
+
|
138
|
+
```ruby
|
139
|
+
def show
|
140
|
+
tracker do |t|
|
141
|
+
t.google_analytics :enhanced_ecommerce, {
|
142
|
+
type: 'addItem',
|
143
|
+
id: '1234',
|
144
|
+
name: 'Fluffy Pink Bunnies',
|
145
|
+
sku: 'DD23444',
|
146
|
+
category: 'Party Toys',
|
147
|
+
price: '11.99',
|
148
|
+
quantity: '1'
|
149
|
+
}
|
150
|
+
end
|
151
|
+
end
|
152
|
+
```
|
153
|
+
|
154
|
+
Will render this:
|
155
|
+
|
156
|
+
```javascript
|
157
|
+
ga("ec:addItem", {"id": "1234", "name": "Fluffy Pink Bunnies", "sku": "DD23444", "category": "Party Toys", "price": "11.99", "quantity": "1"});
|
158
|
+
```
|
159
|
+
|
160
|
+
|
161
|
+
|
111
162
|
#### Ecommerce
|
112
163
|
|
113
164
|
You can even trigger ecommerce directly from within your controller:
|
@@ -132,11 +183,36 @@ take care of the plugin on your own.
|
|
132
183
|
|
133
184
|
```ruby
|
134
185
|
config.middleware.use(Rack::Tracker) do
|
135
|
-
handler :google_analytics, { tracker: 'U-XXXXX-Y', ecommerce: true}
|
186
|
+
handler :google_analytics, { tracker: 'U-XXXXX-Y', ecommerce: true }
|
136
187
|
end
|
137
188
|
````
|
138
189
|
|
139
190
|
|
191
|
+
### Google Tag Manager
|
192
|
+
|
193
|
+
Google Tag manager code snippet doesn't support any option other than the container id
|
194
|
+
|
195
|
+
```ruby
|
196
|
+
config.middleware.use(Rack::Tracker) do
|
197
|
+
handler :google_tag_manager, { container: 'GTM-XXXXXX' }
|
198
|
+
end
|
199
|
+
````
|
200
|
+
|
201
|
+
#### Data Layer
|
202
|
+
|
203
|
+
GTM supports a [dataLayer](https://developers.google.com/tag-manager/devguide#datalayer) for pushing events as well as variables.
|
204
|
+
|
205
|
+
To add events or variables to the dataLayer from the server side, just call the `tracker` method in your controller.
|
206
|
+
|
207
|
+
```ruby
|
208
|
+
def show
|
209
|
+
tracker do |t|
|
210
|
+
t.google_tag_manager :push, { name: 'price', value: 'X' }
|
211
|
+
end
|
212
|
+
end
|
213
|
+
```
|
214
|
+
|
215
|
+
|
140
216
|
### Facebook
|
141
217
|
|
142
218
|
* `custom_audience` - adds the [Custom audience](https://developers.facebook.com/docs/reference/ads-api/custom-audience-website-faq) segmentation pixel
|
@@ -248,6 +324,28 @@ It will render the following to the site source:
|
|
248
324
|
_gs("set", "visitor", { "age": 35, "favorite_food": "pizza" });
|
249
325
|
```
|
250
326
|
|
327
|
+
### Criteo
|
328
|
+
|
329
|
+
[Criteo](http://www.criteo.com/) retargeting service.
|
330
|
+
|
331
|
+
```
|
332
|
+
config.middleware.use(Rack::Tracker) do
|
333
|
+
handler :criteo, { set_account: '1234' }
|
334
|
+
end
|
335
|
+
```
|
336
|
+
|
337
|
+
Other global criteo handler options are:
|
338
|
+
* `setCustomerId` (value can be a static or a dynamic, e.g. `lambda { |env| env['rack.session']['user_id'] }`)
|
339
|
+
* `setSiteType` (`m`, `t`, `d`)
|
340
|
+
|
341
|
+
```
|
342
|
+
def show
|
343
|
+
tracker do |t|
|
344
|
+
t.criteo :track, { event: 'viewItem', item: 'P0001' }
|
345
|
+
end
|
346
|
+
end
|
347
|
+
```
|
348
|
+
|
251
349
|
### Custom Handlers
|
252
350
|
|
253
351
|
Tough we give you handlers for a few tracking services right out of the box, you might
|
data/lib/rack/tracker.rb
CHANGED
@@ -12,6 +12,8 @@ require "rack/tracker/handler"
|
|
12
12
|
require "rack/tracker/handler_delegator"
|
13
13
|
require "rack/tracker/controller"
|
14
14
|
require "rack/tracker/google_analytics/google_analytics"
|
15
|
+
require "rack/tracker/google_tag_manager/google_tag_manager"
|
16
|
+
require "rack/tracker/google_adwords_conversion/google_adwords_conversion"
|
15
17
|
require "rack/tracker/facebook/facebook"
|
16
18
|
require "rack/tracker/vwo/vwo"
|
17
19
|
require "rack/tracker/go_squared/go_squared"
|
@@ -32,6 +32,6 @@ class Rack::Tracker::GoSquared < Rack::Tracker::Handler
|
|
32
32
|
end
|
33
33
|
|
34
34
|
def self.track(name, *event)
|
35
|
-
{ name.to_s => [
|
35
|
+
{ name.to_s => [event.last.merge('class_name' => event.first.to_s.classify)] }
|
36
36
|
end
|
37
37
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class Rack::Tracker::GoogleAdwordsConversion < Rack::Tracker::Handler
|
2
|
+
|
3
|
+
class Conversion < OpenStruct
|
4
|
+
end
|
5
|
+
|
6
|
+
self.position = :body
|
7
|
+
|
8
|
+
def render
|
9
|
+
Tilt.new( File.join( File.dirname(__FILE__), 'template', 'google_adwords_conversion.erb') ).render(self)
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.track(name, *event)
|
13
|
+
{ name.to_s => [event.last.merge('class_name' => event.first.to_s.capitalize)] }
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
<% events.each do |ev| %>
|
2
|
+
|
3
|
+
<script type="text/javascript">
|
4
|
+
/* <![CDATA[ */
|
5
|
+
<% ev.to_h.each do |attr_name, attr_value| %>
|
6
|
+
var google_conversion_<%= attr_name %> = <%= attr_name == :id ? attr_value : "'#{attr_value}'" %>;
|
7
|
+
<% end %>
|
8
|
+
var google_remarketing_only = false;
|
9
|
+
/* ]]> */
|
10
|
+
</script>
|
11
|
+
<script type="text/javascript" src="//www.googleadservices.com/pagead/conversion.js"></script>
|
12
|
+
<noscript>
|
13
|
+
<div style="display:inline;">
|
14
|
+
<img height="1" width="1" style="border-style:none;" alt="" src="//www.googleadservices.com/pagead/conversion/<%= ev.id %>/?label=<%= URI.escape(ev.label) %>&guid=ON&script=0"/>
|
15
|
+
</div>
|
16
|
+
</noscript>
|
17
|
+
|
18
|
+
<% end %>
|
@@ -1,4 +1,7 @@
|
|
1
1
|
class Rack::Tracker::GoogleAnalytics < Rack::Tracker::Handler
|
2
|
+
|
3
|
+
ALLOWED_TRACKER_OPTIONS = [:cookie_domain, :user_id]
|
4
|
+
|
2
5
|
class Send < OpenStruct
|
3
6
|
def initialize(attrs = {})
|
4
7
|
attrs.reverse_merge!(type: 'event')
|
@@ -18,25 +21,51 @@ class Rack::Tracker::GoogleAnalytics < Rack::Tracker::Handler
|
|
18
21
|
end
|
19
22
|
end
|
20
23
|
|
24
|
+
class EnhancedEcommerce < OpenStruct
|
25
|
+
def write
|
26
|
+
["ec:#{self.type}", self.to_h.except(:type).compact.stringify_values].to_json.gsub(/\[|\]/, '')
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
21
30
|
class Ecommerce < OpenStruct
|
22
31
|
def write
|
23
32
|
["ecommerce:#{self.type}", self.to_h.except(:type).compact.stringify_values].to_json.gsub(/\[|\]/, '')
|
24
33
|
end
|
25
34
|
end
|
26
35
|
|
36
|
+
class Parameter < OpenStruct
|
37
|
+
def write
|
38
|
+
["set", self.to_h.to_a].flatten.map {|s| "'#{s}'" }.join(', ')
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
27
42
|
def tracker
|
28
43
|
options[:tracker].respond_to?(:call) ? options[:tracker].call(env) : options[:tracker]
|
29
44
|
end
|
30
45
|
|
46
|
+
def tracker_options
|
47
|
+
@tracker_options ||= {}.tap do |tracker_options|
|
48
|
+
options.slice(*ALLOWED_TRACKER_OPTIONS).each do |key, value|
|
49
|
+
if option_value = value.respond_to?(:call) ? value.call(env) : value
|
50
|
+
tracker_options[key.to_s.camelize(:lower).to_sym] = option_value.to_s
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
31
56
|
def render
|
32
57
|
Tilt.new( File.join( File.dirname(__FILE__), 'template', 'google_analytics.erb') ).render(self)
|
33
58
|
end
|
34
59
|
|
35
60
|
def ecommerce_events
|
36
|
-
events.select{|e| e.kind_of?(Ecommerce) }
|
61
|
+
events.select {|e| e.kind_of?(Ecommerce) }
|
62
|
+
end
|
63
|
+
|
64
|
+
def enhanced_ecommerce_events
|
65
|
+
events.select {|e| e.kind_of?(EnhancedEcommerce) }
|
37
66
|
end
|
38
67
|
|
39
68
|
def self.track(name, *event)
|
40
|
-
{ name.to_s => [
|
69
|
+
{ name.to_s => [event.last.merge('class_name' => event.first.to_s.classify)] }
|
41
70
|
end
|
42
71
|
end
|
@@ -1,47 +1,41 @@
|
|
1
1
|
<script type="text/javascript">
|
2
|
-
|
3
2
|
<% if tracker %>
|
4
|
-
(
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
3
|
+
if(typeof ga === 'undefined') {
|
4
|
+
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
5
|
+
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
6
|
+
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
7
|
+
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
8
|
+
|
9
|
+
ga('create', '<%= tracker %>', <%= tracker_options.to_json %>);
|
10
|
+
}
|
11
11
|
<% if options[:enhanced_link_attribution] %>
|
12
12
|
ga('require', 'linkid', 'linkid.js');
|
13
13
|
<% end %>
|
14
|
-
|
15
14
|
<% if options[:advertising] %>
|
16
15
|
ga('require', 'displayfeatures');
|
17
16
|
<% end %>
|
18
|
-
|
17
|
+
<% if options[:enhanced_ecommerce] && enhanced_ecommerce_events.any? %>
|
18
|
+
ga('require', 'ec');
|
19
|
+
<% end %>
|
19
20
|
<% if options[:ecommerce] %>
|
20
21
|
ga('require', 'ecommerce', 'ecommerce.js');
|
21
22
|
<% end %>
|
22
|
-
|
23
23
|
<% if options[:anonymize_ip] %>
|
24
24
|
ga('set', 'anonymizeIp', true);
|
25
25
|
<% end %>
|
26
|
-
|
27
26
|
<% if options[:adjusted_bounce_rate_timeouts] %>
|
28
27
|
<% options[:adjusted_bounce_rate_timeouts].each do |timeout| %>
|
29
28
|
setTimeout(ga('send', 'event', '<%= "#{timeout.to_s}_seconds" %>', 'read'),<%= timeout*1000 %>);
|
30
29
|
<% end %>
|
31
30
|
<% end %>
|
32
|
-
|
33
31
|
<% end %>
|
34
|
-
|
35
32
|
<% events.each do |var| %>
|
36
33
|
ga(<%= var.write() %>);
|
37
34
|
<% end %>
|
38
|
-
|
39
35
|
<% if options[:ecommerce] && ecommerce_events.any? %>
|
40
36
|
ga('ecommerce:send');
|
41
37
|
<% end %>
|
42
|
-
|
43
38
|
<% if tracker %>
|
44
39
|
ga('send', 'pageview');
|
45
40
|
<% end %>
|
46
|
-
|
47
41
|
</script>
|
@@ -0,0 +1,33 @@
|
|
1
|
+
class Rack::Tracker::GoogleTagManager < Rack::Tracker::Handler
|
2
|
+
|
3
|
+
class Push < OpenStruct
|
4
|
+
|
5
|
+
def write
|
6
|
+
"'#{event[:name]}': '#{event[:value]}'"
|
7
|
+
end
|
8
|
+
|
9
|
+
def event
|
10
|
+
attributes.stringify_values.compact
|
11
|
+
end
|
12
|
+
|
13
|
+
def attributes
|
14
|
+
to_h.slice(:name, :value)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# It is strongly recommended to put the google_tag_manager snippet only in the body tag
|
19
|
+
# https://developers.google.com/tag-manager/quickstart
|
20
|
+
self.position = :body
|
21
|
+
|
22
|
+
def container
|
23
|
+
options[:container].respond_to?(:call) ? options[:container].call(env) : options[:container]
|
24
|
+
end
|
25
|
+
|
26
|
+
def render
|
27
|
+
Tilt.new( File.join( File.dirname(__FILE__), 'template', 'google_tag_manager.erb') ).render(self)
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.track(name, *event)
|
31
|
+
{ name.to_s => [event.last.merge('class_name' => event.first.to_s.capitalize)] }
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
<% if container %>
|
2
|
+
<script>
|
3
|
+
dataLayer = [];
|
4
|
+
</script>
|
5
|
+
|
6
|
+
<noscript><iframe src="//www.googletagmanager.com/ns.html?id=<%= container %>"
|
7
|
+
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
|
8
|
+
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
|
9
|
+
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
|
10
|
+
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
|
11
|
+
'//www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
|
12
|
+
})(window,document,'script','dataLayer','<%= container %>');</script>
|
13
|
+
|
14
|
+
<script>
|
15
|
+
dataLayer.push({
|
16
|
+
<%= events.map(&:write).join(', ') %>
|
17
|
+
});
|
18
|
+
</script>
|
19
|
+
<% end %>
|
data/lib/rack/tracker/handler.rb
CHANGED
@@ -7,11 +7,13 @@ class Rack::Tracker::Handler
|
|
7
7
|
|
8
8
|
def initialize(env, options = {})
|
9
9
|
self.env = env
|
10
|
-
self.options
|
10
|
+
self.options = options
|
11
|
+
self.position = options[:position] if options.has_key?(:position)
|
11
12
|
end
|
12
13
|
|
13
14
|
def events
|
14
|
-
env.fetch('tracker', {})[self.class.to_s.demodulize.underscore] || []
|
15
|
+
events = env.fetch('tracker', {})[self.class.to_s.demodulize.underscore] || []
|
16
|
+
events.map{ |ev| "#{self.class}::#{ev['class_name']}".constantize.new(ev.except('class_name')) }
|
15
17
|
end
|
16
18
|
|
17
19
|
def render
|
@@ -20,6 +20,7 @@ class Rack::Tracker::HandlerDelegator
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def write_event(event)
|
23
|
+
event.deep_stringify_keys! # for consistent hash access use strings (keys from the session are always strings anyway)
|
23
24
|
if env.key?('tracker')
|
24
25
|
self.env['tracker'].deep_merge!(event) { |key, old, new| Array.wrap(old) + Array.wrap(new) }
|
25
26
|
else
|
data/lib/rack/tracker/version.rb
CHANGED
@@ -36,11 +36,12 @@ RSpec.describe Rack::Tracker::Facebook do
|
|
36
36
|
'tracker' => {
|
37
37
|
'facebook' =>
|
38
38
|
[
|
39
|
-
|
40
|
-
'id'=> '123456789',
|
41
|
-
|
42
|
-
|
43
|
-
|
39
|
+
{
|
40
|
+
'id' => '123456789',
|
41
|
+
'value' => '23',
|
42
|
+
'currency' => 'EUR',
|
43
|
+
'class_name' => 'Event'
|
44
|
+
}
|
44
45
|
]
|
45
46
|
}
|
46
47
|
}
|
@@ -14,7 +14,7 @@ RSpec.describe Rack::Tracker::GoSquared do
|
|
14
14
|
def env
|
15
15
|
{'tracker' => {
|
16
16
|
'go_squared' => [
|
17
|
-
|
17
|
+
{ 'class_name' => 'VisitorName', 'name' => 'John Doe' }
|
18
18
|
]
|
19
19
|
}}
|
20
20
|
end
|
@@ -30,7 +30,7 @@ RSpec.describe Rack::Tracker::GoSquared do
|
|
30
30
|
def env
|
31
31
|
{'tracker' => {
|
32
32
|
'go_squared' => [
|
33
|
-
|
33
|
+
{ 'class_name' => 'VisitorInfo', 'age' => 35, 'favorite_food' => 'pizza' }
|
34
34
|
]
|
35
35
|
}}
|
36
36
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
RSpec.describe Rack::Tracker::GoogleAdwordsConversion do
|
2
|
+
|
3
|
+
def env
|
4
|
+
{
|
5
|
+
misc: 'foobar',
|
6
|
+
user_id: '123'
|
7
|
+
}
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'will be placed in the body' do
|
11
|
+
expect(described_class.position).to eq(:body)
|
12
|
+
expect(described_class.new(env).position).to eq(:body)
|
13
|
+
expect(described_class.new(env, position: :body).position).to eq(:body)
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "with events" do
|
17
|
+
describe "default" do
|
18
|
+
def env
|
19
|
+
{'tracker' => {
|
20
|
+
'google_adwords_conversion' => [
|
21
|
+
{ 'class_name' => 'Conversion', 'id' => 123456, 'language' => 'en', 'format' => '3', 'color' => 'ffffff', 'label' => 'Conversion Label' }
|
22
|
+
]
|
23
|
+
}}
|
24
|
+
end
|
25
|
+
|
26
|
+
subject { described_class.new(env).render }
|
27
|
+
it 'will show events' do
|
28
|
+
expect(subject).to match(%r{var google_conversion_id = 123456;})
|
29
|
+
expect(subject).to match(%r{var google_conversion_language = 'en';})
|
30
|
+
expect(subject).to match(%r{var google_conversion_format = '3';})
|
31
|
+
expect(subject).to match(%r{var google_conversion_color = 'ffffff';})
|
32
|
+
expect(subject).to match(%r{var google_conversion_label = 'Conversion Label';})
|
33
|
+
expect(subject).to match(%r{<img.*src=\"\/\/www.googleadservices.com\/pagead\/conversion\/123456\/\?label=Conversion%20Label&guid=ON&script=0\"/>})
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -1,12 +1,15 @@
|
|
1
1
|
RSpec.describe Rack::Tracker::GoogleAnalytics do
|
2
|
-
|
3
2
|
def env
|
4
|
-
{
|
3
|
+
{
|
4
|
+
misc: 'foobar',
|
5
|
+
user_id: '123'
|
6
|
+
}
|
5
7
|
end
|
6
8
|
|
7
9
|
it 'will be placed in the head' do
|
8
10
|
expect(described_class.position).to eq(:head)
|
9
11
|
expect(described_class.new(env).position).to eq(:head)
|
12
|
+
expect(described_class.new(env, position: :body).position).to eq(:body)
|
10
13
|
end
|
11
14
|
|
12
15
|
describe '#ecommerce_events' do
|
@@ -29,12 +32,70 @@ RSpec.describe Rack::Tracker::GoogleAnalytics do
|
|
29
32
|
end
|
30
33
|
end
|
31
34
|
|
35
|
+
describe '#enhanced_ecommerce_events' do
|
36
|
+
subject { described_class.new(env) }
|
37
|
+
|
38
|
+
describe 'with stored enhanced ecommerce events' do
|
39
|
+
before { allow(subject).to receive(:events).and_return([Rack::Tracker::GoogleAnalytics::Send.new, Rack::Tracker::GoogleAnalytics::EnhancedEcommerce.new]) }
|
40
|
+
|
41
|
+
it 'will just return the enhanced ecommerce events' do
|
42
|
+
expect(subject.enhanced_ecommerce_events).to match_array(Rack::Tracker::GoogleAnalytics::EnhancedEcommerce)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe 'without stored enhanced ecommerce events' do
|
47
|
+
before { allow(subject).to receive(:events).and_return([Rack::Tracker::GoogleAnalytics::Send.new]) }
|
48
|
+
|
49
|
+
it 'will be empty' do
|
50
|
+
expect(subject.enhanced_ecommerce_events).to be_empty
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe '#tracker_options' do
|
56
|
+
before do
|
57
|
+
stub_const("#{described_class}::ALLOWED_TRACKER_OPTIONS", [:some_option])
|
58
|
+
end
|
59
|
+
|
60
|
+
context 'with an allowed option configured with a static value' do
|
61
|
+
subject { described_class.new(env, { some_option: 'value' }) }
|
62
|
+
|
63
|
+
it 'returns hash with option set' do
|
64
|
+
expect(subject.tracker_options).to eql ({ someOption: 'value' })
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
context 'with an allowed option configured with a block' do
|
69
|
+
subject { described_class.new(env, { some_option: lambda { |env| return env[:misc] } }) }
|
70
|
+
|
71
|
+
it 'returns hash with option set' do
|
72
|
+
expect(subject.tracker_options).to eql ({ someOption: 'foobar' })
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
context 'with an allowed option configured with a block returning nil' do
|
77
|
+
subject { described_class.new(env, { some_option: lambda { |env| return env[:non_existing_key] } }) }
|
78
|
+
|
79
|
+
it 'returns an empty hash' do
|
80
|
+
expect(subject.tracker_options).to eql ({})
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
context 'with a non allowed option' do
|
85
|
+
subject { described_class.new(env, { new_option: 'value' }) }
|
86
|
+
|
87
|
+
it 'returns an empty hash' do
|
88
|
+
expect(subject.tracker_options).to eql ({})
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
32
93
|
describe "with events" do
|
33
94
|
describe "default" do
|
34
95
|
def env
|
35
96
|
{'tracker' => {
|
36
97
|
'google_analytics' => [
|
37
|
-
|
98
|
+
{ 'class_name' => 'Send', 'category' => 'Users', 'action' => 'Login', 'label' => 'Standard' }
|
38
99
|
]
|
39
100
|
}}
|
40
101
|
end
|
@@ -48,7 +109,7 @@ RSpec.describe Rack::Tracker::GoogleAnalytics do
|
|
48
109
|
describe "with a event value" do
|
49
110
|
def env
|
50
111
|
{'tracker' => { 'google_analytics' => [
|
51
|
-
|
112
|
+
{ 'class_name' => 'Send', category: "Users", action: "Login", label: "Standard", value: "5" }
|
52
113
|
]}}
|
53
114
|
end
|
54
115
|
|
@@ -59,13 +120,13 @@ RSpec.describe Rack::Tracker::GoogleAnalytics do
|
|
59
120
|
end
|
60
121
|
end
|
61
122
|
|
62
|
-
describe 'with
|
123
|
+
describe 'with ecommerce events' do
|
63
124
|
describe "default" do
|
64
125
|
def env
|
65
126
|
{'tracker' => {
|
66
127
|
'google_analytics' => [
|
67
|
-
|
68
|
-
|
128
|
+
{ 'class_name' => 'Ecommerce', 'type' => 'addItem', 'id' => '1234', 'name' => 'Fluffy Pink Bunnies', 'sku' => 'DD23444', 'category' => 'Party Toys', 'price' => '11.99', 'quantity' => '1' },
|
129
|
+
{ 'class_name' => 'Ecommerce', 'type' => 'addTransaction', 'id' => '1234', 'affiliation' => 'Acme Clothing', 'revenue' => 11.99, 'shipping' => '5', 'tax' => '1.29', 'currency' => 'EUR' }
|
69
130
|
]
|
70
131
|
}}
|
71
132
|
end
|
@@ -83,6 +144,44 @@ RSpec.describe Rack::Tracker::GoogleAnalytics do
|
|
83
144
|
end
|
84
145
|
end
|
85
146
|
|
147
|
+
describe 'with enhanced ecommerce events' do
|
148
|
+
describe "default" do
|
149
|
+
def env
|
150
|
+
{'tracker' => {
|
151
|
+
'google_analytics' => [
|
152
|
+
{ 'class_name' => 'EnhancedEcommerce', 'type' => 'addProduct', 'id' => 'P12345', 'name' => 'Android Warhol T-Shirt', 'category' => 'Apparel', 'brand' => 'Google', 'variant' => 'black', 'price' => '29.20', 'coupon' => 'APPARELSALE', 'quantity' => 1 },
|
153
|
+
{ 'class_name' => 'EnhancedEcommerce', 'type' => 'setAction', 'id' => 'T12345', 'affiliation' => 'Google Store - Online', 'revenue' => '37.39', 'tax' => '2.85', 'shipping' => '5.34', 'coupon' => 'SUMMER2013' }
|
154
|
+
]
|
155
|
+
}}
|
156
|
+
end
|
157
|
+
|
158
|
+
subject { described_class.new(env, tracker: 'somebody', enhanced_ecommerce: true).render }
|
159
|
+
it "will add product" do
|
160
|
+
expect(subject).to match(%r{ga\(\"ec:addProduct\",#{{id: 'P12345', name: 'Android Warhol T-Shirt', category: 'Apparel', brand: 'Google', variant: 'black', price: '29.20', coupon: 'APPARELSALE', quantity: '1'}.to_json}})
|
161
|
+
end
|
162
|
+
|
163
|
+
it "will add action" do
|
164
|
+
expect(subject).to match(%r{ga\(\"ec:setAction\",#{{id: 'T12345', affiliation: 'Google Store - Online', revenue: '37.39', tax: '2.85', shipping: '5.34', coupon: 'SUMMER2013'}.to_json}})
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
describe 'with parameters events' do
|
170
|
+
def env
|
171
|
+
{'tracker' => {
|
172
|
+
'google_analytics' => [
|
173
|
+
{ 'class_name' => 'Parameter', 'dimension1' => 'pink' },
|
174
|
+
]
|
175
|
+
}}
|
176
|
+
end
|
177
|
+
|
178
|
+
subject { described_class.new(env, tracker: 'somebody').render }
|
179
|
+
|
180
|
+
it "will render dimension parameter" do
|
181
|
+
expect(subject).to match(%r{ga\('set', 'dimension1', 'pink'})
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
86
185
|
describe "with custom domain" do
|
87
186
|
subject { described_class.new(env, tracker: 'somebody', cookie_domain: "railslabs.com").render }
|
88
187
|
|
@@ -92,6 +191,15 @@ RSpec.describe Rack::Tracker::GoogleAnalytics do
|
|
92
191
|
end
|
93
192
|
end
|
94
193
|
|
194
|
+
describe "with user_id tracking" do
|
195
|
+
subject { described_class.new(env, tracker: 'somebody', user_id: lambda { |env| return env[:user_id] } ).render }
|
196
|
+
|
197
|
+
it "will show asyncronous tracker with userId" do
|
198
|
+
expect(subject).to match(%r{ga\('create', 'somebody', {\"userId\":\"123\"}\)})
|
199
|
+
expect(subject).to match(%r{ga\('send', 'pageview'\)})
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
95
203
|
describe "with enhanced_link_attribution" do
|
96
204
|
subject { described_class.new(env, tracker: 'happy', enhanced_link_attribution: true).render }
|
97
205
|
|
@@ -108,7 +216,33 @@ RSpec.describe Rack::Tracker::GoogleAnalytics do
|
|
108
216
|
end
|
109
217
|
end
|
110
218
|
|
111
|
-
describe "with
|
219
|
+
describe "with enhanced ecommerce" do
|
220
|
+
describe "without events" do
|
221
|
+
subject { described_class.new(env, tracker: 'happy', enhanced_ecommerce: true).render }
|
222
|
+
|
223
|
+
it "will require the enhanced ecommerce plugin" do
|
224
|
+
expect(subject).to_not match(%r{ga\('require', 'ec'\)})
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
describe "with events" do
|
229
|
+
def env
|
230
|
+
{'tracker' => {
|
231
|
+
'google_analytics' => [
|
232
|
+
{ 'class_name' => 'EnhancedEcommerce', 'type' => 'addProduct', 'id' => 'P12345', 'name' => 'Android Warhol T-Shirt', 'category' => 'Apparel', 'brand' => 'Google', 'variant' => 'black', 'price' => '29.20', 'coupon' => 'APPARELSALE', 'quantity' => 1 },
|
233
|
+
]
|
234
|
+
}}
|
235
|
+
end
|
236
|
+
|
237
|
+
subject { described_class.new(env, tracker: 'happy', enhanced_ecommerce: true).render }
|
238
|
+
|
239
|
+
it "will require the enhanced ecommerce plugin" do
|
240
|
+
expect(subject).to match(%r{ga\('require', 'ec'\)})
|
241
|
+
end
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
describe "with ecommerce" do
|
112
246
|
subject { described_class.new(env, tracker: 'happy', ecommerce: true).render }
|
113
247
|
|
114
248
|
it "will require the ecommerce plugin" do
|
@@ -140,5 +274,4 @@ RSpec.describe Rack::Tracker::GoogleAnalytics do
|
|
140
274
|
expect(subject).to match(%r{ga\('send', 'event', '30_seconds', 'read'\)})
|
141
275
|
end
|
142
276
|
end
|
143
|
-
|
144
277
|
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
RSpec.describe Rack::Tracker::GoogleTagManager do
|
2
|
+
|
3
|
+
def env
|
4
|
+
{
|
5
|
+
misc: 'foobar',
|
6
|
+
user_id: '123'
|
7
|
+
}
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'will be placed in the body by default' do
|
11
|
+
expect(described_class.position).to eq(:body)
|
12
|
+
expect(described_class.new(env).position).to eq(:body)
|
13
|
+
expect(described_class.new(env, position: :head).position).to eq(:head)
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "with events" do
|
17
|
+
describe "default" do
|
18
|
+
def env
|
19
|
+
{'tracker' => {
|
20
|
+
'google_tag_manager' => [
|
21
|
+
{ 'class_name' => 'Push', 'name' => 'page', 'value' => 'Cart' },
|
22
|
+
{ 'class_name' => 'Push', 'name' => 'price', 'value' => 50 }
|
23
|
+
]
|
24
|
+
}}
|
25
|
+
end
|
26
|
+
|
27
|
+
subject { described_class.new(env, container: 'somebody').render }
|
28
|
+
it "will show events" do
|
29
|
+
expect(subject).to match(%r{'page': 'Cart', 'price': '50'})
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "with dynamic tracker" do
|
35
|
+
subject { described_class.new(env, { container: lambda { |env| return env[:misc] }}).render }
|
36
|
+
|
37
|
+
it 'will call tracker lambdas to obtain tracking codes' do
|
38
|
+
expect(subject).to match(%r{\(window,document,'script','dataLayer','foobar'\)})
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'support/capybara_app_helper'
|
2
|
+
|
3
|
+
RSpec.describe "Google Adwords Conversion Integration" do
|
4
|
+
before do
|
5
|
+
setup_app(action: :google_adwords_conversion) do |tracker|
|
6
|
+
tracker.handler :google_adwords_conversion
|
7
|
+
end
|
8
|
+
visit '/'
|
9
|
+
end
|
10
|
+
|
11
|
+
subject { page }
|
12
|
+
|
13
|
+
it "embeds the script tag with tracking event from the controller action" do
|
14
|
+
expect(page.find("body")).to have_content("var google_conversion_id = 123456;\nvar google_conversion_language = 'en';\nvar google_conversion_format = '3';\nvar google_conversion_color = 'ffffff';\nvar google_conversion_label = 'Conversion Label';")
|
15
|
+
expect(page.find("body")).to have_xpath("//img[@src=\"//www.googleadservices.com/pagead/conversion/123456/?label=Conversion%20Label&guid=ON&script=0\"]")
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'support/capybara_app_helper'
|
2
2
|
|
3
|
-
RSpec.describe "
|
3
|
+
RSpec.describe "Google Analytics Integration" do
|
4
4
|
before do
|
5
5
|
setup_app(action: :google_analytics) do |tracker|
|
6
6
|
tracker.handler :google_analytics, { tracker: 'U-XXX-Y' }
|
@@ -11,8 +11,23 @@ RSpec.describe "Facebook Integration" do
|
|
11
11
|
subject { page }
|
12
12
|
|
13
13
|
it "embeds the script tag with tracking event from the controller action" do
|
14
|
-
expect(page).to have_content('ga("ecommerce:addItem",{"id":"1234","name":"Fluffy Pink Bunnies","sku":"DD23444","category":"Party Toys","price":"11.99","quantity":"1"})')
|
15
|
-
expect(page).to have_content('ga("ecommerce:addTransaction",{"id":"1234","affiliation":"Acme Clothing","revenue":"11.99","shipping":"5","tax":"1.29"})')
|
16
|
-
expect(page).to have_content('ga("send",{"hitType":"event","eventCategory":"button","eventAction":"click","eventLabel":"nav-buttons","eventValue":"X"})')
|
14
|
+
expect(page.find("head")).to have_content('ga("ecommerce:addItem",{"id":"1234","name":"Fluffy Pink Bunnies","sku":"DD23444","category":"Party Toys","price":"11.99","quantity":"1"})')
|
15
|
+
expect(page.find("head")).to have_content('ga("ecommerce:addTransaction",{"id":"1234","affiliation":"Acme Clothing","revenue":"11.99","shipping":"5","tax":"1.29"})')
|
16
|
+
expect(page.find("head")).to have_content('ga("send",{"hitType":"event","eventCategory":"button","eventAction":"click","eventLabel":"nav-buttons","eventValue":"X"})')
|
17
|
+
end
|
18
|
+
|
19
|
+
describe 'adjust tracker position via options' do
|
20
|
+
before do
|
21
|
+
setup_app(action: :google_analytics) do |tracker|
|
22
|
+
tracker.handler :google_analytics, { tracker: 'U-XXX-Y', position: :body }
|
23
|
+
end
|
24
|
+
visit '/'
|
25
|
+
end
|
26
|
+
|
27
|
+
it "will be placed in the specified tag" do
|
28
|
+
expect(page.find("head")).to_not have_content('U-XXX-Y')
|
29
|
+
expect(page.find("body")).to have_content('ga("ecommerce:addItem",{"id":"1234","name":"Fluffy Pink Bunnies","sku":"DD23444","category":"Party Toys","price":"11.99","quantity":"1"})')
|
30
|
+
end
|
31
|
+
|
17
32
|
end
|
18
33
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'support/capybara_app_helper'
|
2
|
+
|
3
|
+
RSpec.describe "Google Tag Manager Integration" do
|
4
|
+
before do
|
5
|
+
setup_app(action: :google_tag_manager) do |tracker|
|
6
|
+
tracker.handler :google_tag_manager, { container: 'GTM-ABCDEF' }
|
7
|
+
end
|
8
|
+
visit '/'
|
9
|
+
end
|
10
|
+
|
11
|
+
subject { page }
|
12
|
+
|
13
|
+
it "embeds the script tag with tracking event from the controller action" do
|
14
|
+
expect(page.find("body")).to have_content('GTM-ABCDEF')
|
15
|
+
expect(page.find("body")).to have_content('\'click\': \'X\', \'price\': \'10\'')
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -38,6 +38,21 @@ class MetalController < ActionController::Metal
|
|
38
38
|
render "metal/index"
|
39
39
|
end
|
40
40
|
|
41
|
+
def google_tag_manager
|
42
|
+
tracker do |t|
|
43
|
+
t.google_tag_manager :push, { name: 'click', value: 'X' }
|
44
|
+
t.google_tag_manager :push, { name: 'price', value: '10' }
|
45
|
+
end
|
46
|
+
render "metal/index"
|
47
|
+
end
|
48
|
+
|
49
|
+
def google_adwords_conversion
|
50
|
+
tracker do |t|
|
51
|
+
t.google_adwords_conversion :conversion, { id: 123456, language: 'en', format: '3', color: 'ffffff', label: 'Conversion Label' }
|
52
|
+
end
|
53
|
+
render "metal/index"
|
54
|
+
end
|
55
|
+
|
41
56
|
def vwo
|
42
57
|
render "metal/index"
|
43
58
|
end
|
@@ -22,11 +22,11 @@ end
|
|
22
22
|
|
23
23
|
RSpec.describe Rack::Tracker::Controller do
|
24
24
|
describe '#tracker' do
|
25
|
-
let(:send) {
|
26
|
-
let(:trx) {
|
27
|
-
let(:item_foo) {
|
28
|
-
let(:item_bar) {
|
29
|
-
let(:fb_event) {
|
25
|
+
let(:send) { { 'category' => 'foo', 'class_name' => 'Send' } }
|
26
|
+
let(:trx) { { 'type' => 'addTransaction', 'some' => 'thing', 'class_name' => 'Ecommerce' } }
|
27
|
+
let(:item_foo) { { 'type' => 'addItem', 'name' => 'foo', 'class_name' => 'Ecommerce' } }
|
28
|
+
let(:item_bar) { { 'type' => 'addItem', 'name' => 'bar', 'class_name' => 'Ecommerce' } }
|
29
|
+
let(:fb_event) { { 'id' => '1', 'value' => 1, 'currency' => 'USD', 'class_name' => 'Event' } }
|
30
30
|
let(:controller) { TestController.new({}) }
|
31
31
|
|
32
32
|
context 'controller' do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rack-tracker
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lars Brillert
|
@@ -9,132 +9,132 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2015-03-23 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rack
|
16
16
|
requirement: !ruby/object:Gem::Requirement
|
17
17
|
requirements:
|
18
|
-
- -
|
18
|
+
- - ">="
|
19
19
|
- !ruby/object:Gem::Version
|
20
20
|
version: 1.4.0
|
21
21
|
type: :runtime
|
22
22
|
prerelease: false
|
23
23
|
version_requirements: !ruby/object:Gem::Requirement
|
24
24
|
requirements:
|
25
|
-
- -
|
25
|
+
- - ">="
|
26
26
|
- !ruby/object:Gem::Version
|
27
27
|
version: 1.4.0
|
28
28
|
- !ruby/object:Gem::Dependency
|
29
29
|
name: tilt
|
30
30
|
requirement: !ruby/object:Gem::Requirement
|
31
31
|
requirements:
|
32
|
-
- - ~>
|
32
|
+
- - "~>"
|
33
33
|
- !ruby/object:Gem::Version
|
34
34
|
version: 1.4.1
|
35
35
|
type: :runtime
|
36
36
|
prerelease: false
|
37
37
|
version_requirements: !ruby/object:Gem::Requirement
|
38
38
|
requirements:
|
39
|
-
- - ~>
|
39
|
+
- - "~>"
|
40
40
|
- !ruby/object:Gem::Version
|
41
41
|
version: 1.4.1
|
42
42
|
- !ruby/object:Gem::Dependency
|
43
43
|
name: activesupport
|
44
44
|
requirement: !ruby/object:Gem::Requirement
|
45
45
|
requirements:
|
46
|
-
- -
|
46
|
+
- - ">="
|
47
47
|
- !ruby/object:Gem::Version
|
48
48
|
version: '3.0'
|
49
49
|
type: :runtime
|
50
50
|
prerelease: false
|
51
51
|
version_requirements: !ruby/object:Gem::Requirement
|
52
52
|
requirements:
|
53
|
-
- -
|
53
|
+
- - ">="
|
54
54
|
- !ruby/object:Gem::Version
|
55
55
|
version: '3.0'
|
56
56
|
- !ruby/object:Gem::Dependency
|
57
57
|
name: actionpack
|
58
58
|
requirement: !ruby/object:Gem::Requirement
|
59
59
|
requirements:
|
60
|
-
- -
|
60
|
+
- - ">="
|
61
61
|
- !ruby/object:Gem::Version
|
62
62
|
version: '3.0'
|
63
63
|
type: :development
|
64
64
|
prerelease: false
|
65
65
|
version_requirements: !ruby/object:Gem::Requirement
|
66
66
|
requirements:
|
67
|
-
- -
|
67
|
+
- - ">="
|
68
68
|
- !ruby/object:Gem::Version
|
69
69
|
version: '3.0'
|
70
70
|
- !ruby/object:Gem::Dependency
|
71
71
|
name: bundler
|
72
72
|
requirement: !ruby/object:Gem::Requirement
|
73
73
|
requirements:
|
74
|
-
- - ~>
|
74
|
+
- - "~>"
|
75
75
|
- !ruby/object:Gem::Version
|
76
76
|
version: '1.5'
|
77
77
|
type: :development
|
78
78
|
prerelease: false
|
79
79
|
version_requirements: !ruby/object:Gem::Requirement
|
80
80
|
requirements:
|
81
|
-
- - ~>
|
81
|
+
- - "~>"
|
82
82
|
- !ruby/object:Gem::Version
|
83
83
|
version: '1.5'
|
84
84
|
- !ruby/object:Gem::Dependency
|
85
85
|
name: rake
|
86
86
|
requirement: !ruby/object:Gem::Requirement
|
87
87
|
requirements:
|
88
|
-
- -
|
88
|
+
- - ">="
|
89
89
|
- !ruby/object:Gem::Version
|
90
90
|
version: '0'
|
91
91
|
type: :development
|
92
92
|
prerelease: false
|
93
93
|
version_requirements: !ruby/object:Gem::Requirement
|
94
94
|
requirements:
|
95
|
-
- -
|
95
|
+
- - ">="
|
96
96
|
- !ruby/object:Gem::Version
|
97
97
|
version: '0'
|
98
98
|
- !ruby/object:Gem::Dependency
|
99
99
|
name: rspec
|
100
100
|
requirement: !ruby/object:Gem::Requirement
|
101
101
|
requirements:
|
102
|
-
- - ~>
|
102
|
+
- - "~>"
|
103
103
|
- !ruby/object:Gem::Version
|
104
104
|
version: 3.0.0
|
105
105
|
type: :development
|
106
106
|
prerelease: false
|
107
107
|
version_requirements: !ruby/object:Gem::Requirement
|
108
108
|
requirements:
|
109
|
-
- - ~>
|
109
|
+
- - "~>"
|
110
110
|
- !ruby/object:Gem::Version
|
111
111
|
version: 3.0.0
|
112
112
|
- !ruby/object:Gem::Dependency
|
113
113
|
name: capybara
|
114
114
|
requirement: !ruby/object:Gem::Requirement
|
115
115
|
requirements:
|
116
|
-
- - ~>
|
116
|
+
- - "~>"
|
117
117
|
- !ruby/object:Gem::Version
|
118
118
|
version: 2.4.1
|
119
119
|
type: :development
|
120
120
|
prerelease: false
|
121
121
|
version_requirements: !ruby/object:Gem::Requirement
|
122
122
|
requirements:
|
123
|
-
- - ~>
|
123
|
+
- - "~>"
|
124
124
|
- !ruby/object:Gem::Version
|
125
125
|
version: 2.4.1
|
126
126
|
- !ruby/object:Gem::Dependency
|
127
127
|
name: pry
|
128
128
|
requirement: !ruby/object:Gem::Requirement
|
129
129
|
requirements:
|
130
|
-
- -
|
130
|
+
- - ">="
|
131
131
|
- !ruby/object:Gem::Version
|
132
132
|
version: '0'
|
133
133
|
type: :development
|
134
134
|
prerelease: false
|
135
135
|
version_requirements: !ruby/object:Gem::Requirement
|
136
136
|
requirements:
|
137
|
-
- -
|
137
|
+
- - ">="
|
138
138
|
- !ruby/object:Gem::Version
|
139
139
|
version: '0'
|
140
140
|
description: Don’t fool around with adding tracking partials to your app and concentrate
|
@@ -146,9 +146,9 @@ executables: []
|
|
146
146
|
extensions: []
|
147
147
|
extra_rdoc_files: []
|
148
148
|
files:
|
149
|
-
- .gitignore
|
150
|
-
- .rspec
|
151
|
-
- .travis.yml
|
149
|
+
- ".gitignore"
|
150
|
+
- ".rspec"
|
151
|
+
- ".travis.yml"
|
152
152
|
- CHANGELOG.md
|
153
153
|
- Gemfile
|
154
154
|
- LICENSE.txt
|
@@ -161,8 +161,12 @@ files:
|
|
161
161
|
- lib/rack/tracker/facebook/template/facebook.erb
|
162
162
|
- lib/rack/tracker/go_squared/go_squared.rb
|
163
163
|
- lib/rack/tracker/go_squared/template/go_squared.erb
|
164
|
+
- lib/rack/tracker/google_adwords_conversion/google_adwords_conversion.rb
|
165
|
+
- lib/rack/tracker/google_adwords_conversion/template/google_adwords_conversion.erb
|
164
166
|
- lib/rack/tracker/google_analytics/google_analytics.rb
|
165
167
|
- lib/rack/tracker/google_analytics/template/google_analytics.erb
|
168
|
+
- lib/rack/tracker/google_tag_manager/google_tag_manager.rb
|
169
|
+
- lib/rack/tracker/google_tag_manager/template/google_tag_manager.erb
|
166
170
|
- lib/rack/tracker/handler.rb
|
167
171
|
- lib/rack/tracker/handler_delegator.rb
|
168
172
|
- lib/rack/tracker/railtie.rb
|
@@ -177,11 +181,15 @@ files:
|
|
177
181
|
- spec/fixtures/views/metal/index.html.erb
|
178
182
|
- spec/handler/facebook_spec.rb
|
179
183
|
- spec/handler/go_squared_spec.rb
|
184
|
+
- spec/handler/google_adwords_conversion_spec.rb
|
180
185
|
- spec/handler/google_analytics_spec.rb
|
186
|
+
- spec/handler/google_tag_manager_spec.rb
|
181
187
|
- spec/handler/vwo_spec.rb
|
182
188
|
- spec/integration/facebook_integration_spec.rb
|
183
189
|
- spec/integration/go_squared_integration_spec.rb
|
190
|
+
- spec/integration/google_adwords_conversion_integration_spec.rb
|
184
191
|
- spec/integration/google_analytics_integration_spec.rb
|
192
|
+
- spec/integration/google_tag_manager_integration_spec.rb
|
185
193
|
- spec/integration/rails_integration_spec.rb
|
186
194
|
- spec/integration/vwo_integration_spec.rb
|
187
195
|
- spec/spec_helper.rb
|
@@ -202,17 +210,17 @@ require_paths:
|
|
202
210
|
- lib
|
203
211
|
required_ruby_version: !ruby/object:Gem::Requirement
|
204
212
|
requirements:
|
205
|
-
- -
|
213
|
+
- - ">="
|
206
214
|
- !ruby/object:Gem::Version
|
207
215
|
version: '0'
|
208
216
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
209
217
|
requirements:
|
210
|
-
- -
|
218
|
+
- - ">="
|
211
219
|
- !ruby/object:Gem::Version
|
212
220
|
version: '0'
|
213
221
|
requirements: []
|
214
222
|
rubyforge_project:
|
215
|
-
rubygems_version: 2.
|
223
|
+
rubygems_version: 2.4.3
|
216
224
|
signing_key:
|
217
225
|
specification_version: 4
|
218
226
|
summary: Tracking made easy
|
@@ -224,11 +232,15 @@ test_files:
|
|
224
232
|
- spec/fixtures/views/metal/index.html.erb
|
225
233
|
- spec/handler/facebook_spec.rb
|
226
234
|
- spec/handler/go_squared_spec.rb
|
235
|
+
- spec/handler/google_adwords_conversion_spec.rb
|
227
236
|
- spec/handler/google_analytics_spec.rb
|
237
|
+
- spec/handler/google_tag_manager_spec.rb
|
228
238
|
- spec/handler/vwo_spec.rb
|
229
239
|
- spec/integration/facebook_integration_spec.rb
|
230
240
|
- spec/integration/go_squared_integration_spec.rb
|
241
|
+
- spec/integration/google_adwords_conversion_integration_spec.rb
|
231
242
|
- spec/integration/google_analytics_integration_spec.rb
|
243
|
+
- spec/integration/google_tag_manager_integration_spec.rb
|
232
244
|
- spec/integration/rails_integration_spec.rb
|
233
245
|
- spec/integration/vwo_integration_spec.rb
|
234
246
|
- spec/spec_helper.rb
|