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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0f0a68c680e45358ffb42303ad9556ef64d3b788
4
- data.tar.gz: 33478c535dcdebd32ce278c763384e5b41fc5a65
3
+ metadata.gz: 06a5db11fbd86405523dbc25c7be6f8b81f2149d
4
+ data.tar.gz: 900ce6c698fe6db41c3cf073bf3c523e3056a366
5
5
  SHA512:
6
- metadata.gz: 799632382d7f8c85cfe51f0e4f74784eb1a37089cd99af4bf6ad586366fd4e21f4488c90843464819d0827fd8c7adf89dd3fe615fdd3a218016d1453e29a9e6d
7
- data.tar.gz: a1488e39161fb2e081de609947e36fab6cf7f61645aa7a0e0054948ef0bf29a360e43b16b1c021869b505b37c4d92de37c6f0f55a9cccf04905ec6782dc83fb2
6
+ metadata.gz: 300d2b933c171c031439480702b5e64cf824d25fc8d4e2007d6eb2d09d9852447306b5a56621b520367b20bcbafeafc967cd0ac61f04a28faa24b0e02a680202
7
+ data.tar.gz: 4f2e384af4d3a3da6fd48f2210f11a92c37b31adb156f47cea6f104743720717f8df2a05965c2935cd5456ba59820dd8c4049f4d985b78caa572e06210d8e87d
data/.travis.yml CHANGED
@@ -3,4 +3,5 @@ rvm:
3
3
  - 1.9.3
4
4
  - 2.0.0
5
5
  - 2.1.2
6
+ - 2.2.1
6
7
  - jruby
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
- Rack::Tracker::GoogleAnalytics::Send.new(category: "Users", action: "Login", label: "Standard")
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. Defaults to `auto`.
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"
@@ -12,7 +12,7 @@ class Rack::Tracker::Facebook < Rack::Tracker::Handler
12
12
  end
13
13
 
14
14
  def self.track(name, *event)
15
- { name.to_s => [Event.new(event.last)] }
15
+ { name.to_s => [event.last.merge('class_name' => 'Event')] }
16
16
  end
17
17
 
18
18
  end
@@ -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 => [const_get(event.first.to_s.classify).new(event.last)] }
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) %>&amp;guid=ON&amp;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 => [const_get(event.first.to_s.capitalize).new(event.last)] }
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
- (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 %>', <%= (options[:cookie_domain] ? {cookieDomain: options[:cookie_domain]} : {}).to_json %>);
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 %>
@@ -7,11 +7,13 @@ class Rack::Tracker::Handler
7
7
 
8
8
  def initialize(env, options = {})
9
9
  self.env = env
10
- self.options = 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
@@ -1,5 +1,5 @@
1
1
  module Rack
2
2
  class Tracker
3
- VERSION = '0.3.0'
3
+ VERSION = '0.4.0'
4
4
  end
5
5
  end
@@ -1,3 +1,3 @@
1
1
  <script type="text/javascript">
2
- myAwesomeFunction("tracks", "like", "<%= track_me[:like] %>", "<%= options[:custom_key] %>");
2
+ myAwesomeFunction("tracks", "like", "<%= track_me['like'] %>", "<%= options[:custom_key] %>");
3
3
  </script>
@@ -36,11 +36,12 @@ RSpec.describe Rack::Tracker::Facebook do
36
36
  'tracker' => {
37
37
  'facebook' =>
38
38
  [
39
- Rack::Tracker::Facebook::Event.new(
40
- 'id'=> '123456789',
41
- 'value' => '23',
42
- 'currency' => 'EUR'
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
- Rack::Tracker::GoSquared::VisitorName.new(name: "John Doe")
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
- Rack::Tracker::GoSquared::VisitorInfo.new(age: 35, favorite_food: 'pizza')
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&amp;guid=ON&amp;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
- {misc: 'foobar'}
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
- Rack::Tracker::GoogleAnalytics::Send.new(category: "Users", action: "Login", label: "Standard")
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
- Rack::Tracker::GoogleAnalytics::Send.new(category: "Users", action: "Login", label: "Standard", value: "5")
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 e-commerce events' do
123
+ describe 'with ecommerce events' do
63
124
  describe "default" do
64
125
  def env
65
126
  {'tracker' => {
66
127
  'google_analytics' => [
67
- Rack::Tracker::GoogleAnalytics::Ecommerce.new({type: 'addItem', id: '1234', name: 'Fluffy Pink Bunnies', sku: 'DD23444', category: 'Party Toys', price: '11.99', quantity: '1'}),
68
- Rack::Tracker::GoogleAnalytics::Ecommerce.new({type: 'addTransaction', id: '1234', affiliation: 'Acme Clothing', revenue: 11.99, shipping: '5', tax: '1.29', currency: 'EUR'})
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 e-commerce" do
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 "Facebook Integration" do
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
@@ -5,6 +5,7 @@ require 'rspec'
5
5
  require 'rack/test'
6
6
  require 'capybara/rspec'
7
7
  require 'rack/tracker'
8
+ require 'pry'
8
9
 
9
10
  # Requires supporting files with custom matchers and macros, etc,
10
11
  # in ./support/ and its subdirectories.
@@ -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) { Rack::Tracker::GoogleAnalytics::Send.new(category: 'foo') }
26
- let(:trx) { Rack::Tracker::GoogleAnalytics::Ecommerce.new(type: 'addTransaction', some: 'thing') }
27
- let(:item_foo) { Rack::Tracker::GoogleAnalytics::Ecommerce.new(type: 'addItem', name: 'foo') }
28
- let(:item_bar) { Rack::Tracker::GoogleAnalytics::Ecommerce.new(type: 'addItem', name: 'bar') }
29
- let(:fb_event) { Rack::Tracker::Facebook::Event.new(id: '1', value: 1, currency: 'USD') }
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.3.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: 2014-11-19 00:00:00.000000000 Z
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.2.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