rack-tracker 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|