rack-tracker 1.6.0 → 1.7.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 0a9cfcc30e5e0f2ad7537aaa11e73bcfeafe80fa
4
- data.tar.gz: 7645b119a9d73df232c29ee86f2d55f43118403c
2
+ SHA256:
3
+ metadata.gz: 55705dd46c88e815dd7b0187c3d6d2a50b36a79f5ccc52e801a96d282ba348be
4
+ data.tar.gz: 5cad1746a043405f4f0e1b2cf85904dd9a6daa50923199d77d71bb32b7a357ba
5
5
  SHA512:
6
- metadata.gz: ecea4935a9470f58ab52b413f0e6b984238d5db11d527fa5eaceeda5dac904bdcd65c804b2f0fe2680224b135e71c4443554f3d6d8f7aaa556c9b75b32d6c499
7
- data.tar.gz: 6ecdf64a615c1bc9d46828c817e5836e5af6d64cc9ec5476fe19558b8c498a68211112386ef3838645828b5796e44e29da30cf4a81a94c4fa91c1604fd5cc648
6
+ metadata.gz: 0ea613048f9899f3c532eee40c7dd40ed9e4c6c6623f318df1522bbb11e3a05656bb3b96adf0b3b46bd10e33c34f9ab5774c7d48402e1830e3efff2042b144e2
7
+ data.tar.gz: ea8b57893ebdcc970e55085f20cefc4cdb1e18f5172b6e44cc3c54a2189335109cafe0694e30854edaa90ed3f3d8330051dc2619b7826f3a5180cb168ea129d3
@@ -1,3 +1,8 @@
1
+ # 1.7.0
2
+
3
+ * [BUGFIX] dup response string in Rack::Tracker#inject to avoid RuntimeError #114 (thx @zpfled)
4
+ * [ENHANCEMENT] Allow to use custom pageview url script for GoogleAnalytics tracker. #119 (thx @Haerezis)
5
+
1
6
  # 1.6.0
2
7
 
3
8
  * [BUGFIX] set wildcard to non-greedy for GTM body insertion #107
data/README.md CHANGED
@@ -30,6 +30,32 @@ but to get you started we're shipping support for the following services out of
30
30
  * [Zanox](#zanox)
31
31
  * [Hotjar](#hotjar)
32
32
 
33
+ ## Respecting the Do Not Track (DNT) HTTP header
34
+
35
+ The Do Not Track (DNT) HTTP header is a HTTP header that requests the server to disable its tracking of the individual user.
36
+ This is an opt-out option supported by most browsers. This option is disabled by default and has to be explicitly enabled to indicate the user's request to opt-out.
37
+ We believe evey application should respect the user's choice to opt-out and respect this HTTP header.
38
+
39
+ Since version 2.0.0 rack-tracker respects that request header by default. That means NO tracker is injected IF the DNT header is set to "1".
40
+
41
+ This option can be overwriten using the `DO_NOT_RESPECT_DNT_HEADER => true` option which must be set on any handler that should ignore the DNT header. (but please think twice before doing that)
42
+
43
+ ### Example on how to not respect the DNT header
44
+
45
+ ```ruby
46
+ use Rack::Tracker do
47
+ # this tracker will be injected EVEN IF the DNT header is set to 1
48
+ handler :maybe_a_friendly_tracker, { tracker: 'U-XXXXX-Y', DO_NOT_RESPECT_DNT_HEADER: true }
49
+ # this tracker will NOT be injected if the DNT header is set to 1
50
+ handler :google_analytics, { tracker: 'U-XXXXX-Y' }
51
+ end
52
+ ```
53
+
54
+ Further reading on the DNT header:
55
+
56
+ * [Wikipedia Do Not Track](https://en.wikipedia.org/wiki/Do_Not_Track)
57
+ * [EFF: Do Not Track](https://www.eff.org/issues/do-not-track)
58
+
33
59
 
34
60
  ## Installation
35
61
 
@@ -97,6 +123,7 @@ request.env['tracker'] = {
97
123
  * `:ecommerce` - Enables [Ecommerce Tracking](https://developers.google.com/analytics/devguides/collection/analyticsjs/ecommerce).
98
124
  * `:enhanced_ecommerce` - Enables [Enhanced Ecommerce Tracking](https://developers.google.com/analytics/devguides/collection/analyticsjs/enhanced-ecommerce)
99
125
  * `:optimize` - pass [Google Optimize container ID](https://support.google.com/360suite/optimize/answer/6262084#example-combined-snippet) as value (e.g. `optimize: 'GTM-1234'`).
126
+ * `:pageview_url_script` - a String containing a custom js script evaluating to the url that shoudl be given to the pageview event. Default to `window.location.pathname + window.location.search`.
100
127
 
101
128
  #### Events
102
129
 
@@ -276,6 +303,26 @@ First, add the following to your config:
276
303
  end
277
304
  ```
278
305
 
306
+ #### Dynamic Pixel Configuration
307
+
308
+ If you need to have different pixel ids e.g. based on the request or serving pages for different accounts, you have the possibility to achieve this by passing a lambda:
309
+
310
+ ```ruby
311
+ config.middleware.use(Rack::Tracker) do
312
+ handler :facebook_pixel, { id: lambda { |env| env['PIXEL_ID'] } }
313
+ end
314
+ ```
315
+
316
+ and set the pixel id within the request `env` variable. Here an example on how it can be done in a rails action:
317
+
318
+ ```ruby
319
+ class MyController < ApplicationController
320
+ def show
321
+ request.env['PIXEL_ID'] = 'DYNAMIC_PIXEL_ID'
322
+ end
323
+ end
324
+ ```
325
+
279
326
  #### Standard Events
280
327
 
281
328
  To track Standard Events from the server side just call the `tracker` method in your controller.
@@ -58,10 +58,11 @@ module Rack
58
58
  def html?; @headers['Content-Type'] =~ /html/; end
59
59
 
60
60
  def inject(env, response)
61
+ duplicated_response = response.dup
61
62
  @handlers.each(env) do |handler|
62
- handler.inject(response)
63
+ handler.inject(duplicated_response)
63
64
  end
64
- response
65
+ duplicated_response
65
66
  end
66
67
 
67
68
  class HandlerSet
@@ -65,6 +65,10 @@ class Rack::Tracker::GoogleAnalytics < Rack::Tracker::Handler
65
65
  events.select {|e| e.kind_of?(EnhancedEcommerce) }
66
66
  end
67
67
 
68
+ def pageview_url_script
69
+ options[:pageview_url_script] || 'window.location.pathname + window.location.search'
70
+ end
71
+
68
72
  private
69
73
 
70
74
  def tracker_option_key(key)
@@ -39,6 +39,6 @@
39
39
  ga('ecommerce:send');
40
40
  <% end %>
41
41
  <% if tracker %>
42
- ga('send', 'pageview', window.location.pathname + window.location.search);
42
+ ga('send', 'pageview', <%= pageview_url_script %>);
43
43
  <% end %>
44
44
  </script>
@@ -38,6 +38,11 @@ class Rack::Tracker::Handler
38
38
  end
39
39
 
40
40
  def inject(response)
41
+ # default to not inject this tracker if the DNT HTTP header is set
42
+ # if the DO_NOT_RESPECT_DNT_HEADER config is set the DNT header is ignored :( - please do respect the DNT header!
43
+ if self.dnt_header_opt_out? && !self.options.has_key?(:DO_NOT_RESPECT_DNT_HEADER)
44
+ return response
45
+ end
41
46
  # Sub! is enough, in well formed html there's only one head or body tag.
42
47
  # Block syntax need to be used, otherwise backslashes in input will mess the output.
43
48
  # @see http://stackoverflow.com/a/4149087/518204 and https://github.com/railslove/rack-tracker/issues/50
@@ -70,6 +75,11 @@ class Rack::Tracker::Handler
70
75
  end
71
76
  end
72
77
 
78
+ # the request has set the DO NOT TRACK (DNT) and has opted to get not tracked (DNT=1)
79
+ def dnt_header_opt_out?
80
+ self.env['HTTP_DNT'] && self.env['HTTP_DNT'].to_s == '1'
81
+ end
82
+
73
83
  private
74
84
 
75
85
  # Transformations to be applied to tracker option keys.
@@ -1,5 +1,5 @@
1
1
  module Rack
2
2
  class Tracker
3
- VERSION = '1.6.0'
3
+ VERSION = '1.7.0'
4
4
  end
5
5
  end
@@ -267,4 +267,22 @@ RSpec.describe Rack::Tracker::GoogleAnalytics do
267
267
  expect(subject).to include %q{setTimeout(function() { ga('send', 'event', '30_seconds', 'read'); },30000)}
268
268
  end
269
269
  end
270
+
271
+ describe '#pageview_url_script' do
272
+ context 'without custom pageview url script' do
273
+ subject { described_class.new(env, {} ) }
274
+
275
+ it 'returns return the custom pageview url script' do
276
+ expect(subject.pageview_url_script).to eql ("window.location.pathname + window.location.search")
277
+ end
278
+ end
279
+
280
+ context 'with a custom pageview url script' do
281
+ subject { described_class.new(env, { pageview_url_script: "{ 'page': location.pathname + location.search + location.hash }"}) }
282
+
283
+ it 'returns return the custom pageview url script' do
284
+ expect(subject.pageview_url_script).to eql ("{ 'page': location.pathname + location.search + location.hash }")
285
+ end
286
+ end
287
+ end
270
288
  end
@@ -16,6 +16,10 @@ RSpec.describe "Google Analytics Integration" do
16
16
  expect(page.find("head")).to have_content('ga("send",{"hitType":"event","eventCategory":"button","eventAction":"click","eventLabel":"nav-buttons","eventValue":"X"})')
17
17
  end
18
18
 
19
+ it "will have default pageview url script" do
20
+ expect(page.find("head")).to have_content("ga('send', 'pageview', window.location.pathname + window.location.search);")
21
+ end
22
+
19
23
  describe 'adjust tracker position via options' do
20
24
  before do
21
25
  setup_app(action: :google_analytics) do |tracker|
@@ -49,4 +53,18 @@ RSpec.describe "Google Analytics Integration" do
49
53
  expect(page.find('head')).to have_content %q{Author\\'s name}
50
54
  end
51
55
  end
52
- end
56
+
57
+ describe 'Use custom pageview script' do
58
+ before do
59
+ setup_app(action: :google_analytics) do |tracker|
60
+ tracker.handler :google_analytics, { tracker: 'U-XXX-Y', pageview_url_script: "{ 'page': location.pathname + location.search + location.hash }"}
61
+ end
62
+ visit '/'
63
+ end
64
+
65
+ it "will use the custom pageview script for the pageview event" do
66
+ expect(page.find("head")).to have_content("ga('send', 'pageview', { 'page': location.pathname + location.search + location.hash });")
67
+ end
68
+ end
69
+
70
+ end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  class DummyHandler < Rack::Tracker::Handler
2
3
  def render
3
4
  Tilt.new( File.join( File.dirname(__FILE__), '../fixtures/dummy.erb') ).render(self)
@@ -20,6 +21,7 @@ RSpec.describe Rack::Tracker do
20
21
  use Rack::Tracker do
21
22
  handler DummyHandler, { foo: 'head' }
22
23
  handler BodyHandler, { foo: 'body' }
24
+ handler DummyHandler, { foo: 'I am evil', DO_NOT_RESPECT_DNT_HEADER: true }
23
25
  end
24
26
 
25
27
  run lambda {|env|
@@ -105,4 +107,39 @@ RSpec.describe Rack::Tracker do
105
107
  expect(last_response.body).to_not include("alert('this is a dummy class');")
106
108
  end
107
109
  end
110
+
111
+ describe 'do not track' do
112
+ context 'DNT header set to 1' do
113
+ it 'will not inject any tracker' do
114
+ get '/', {}, {'HTTP_DNT' => 1 }
115
+
116
+ # the DummyHandler respects the DNT
117
+ expect(last_response.body).to_not include("console.log('head');")
118
+ end
119
+
120
+ it 'will allow the DO_NOT_RESPECT_DNT_HEADER overwrite' do
121
+ get '/', {}, {'HTTP_DNT' => 1 }
122
+
123
+ # the EvilHandler respects the DNT
124
+ expect(last_response.body).to include("console.log('I am evil');")
125
+ end
126
+ end
127
+
128
+ context 'DNT header set to 0' do
129
+ it 'injects all trackers' do
130
+ get '/', {}, {'HTTP_DNT' => 0 }
131
+ expect(last_response.body).to include("console.log('head');")
132
+ expect(last_response.body).to include("console.log('I am evil');")
133
+ end
134
+ end
135
+
136
+ context 'DNT header is not set' do
137
+ it 'injects all trackers' do
138
+ get '/'
139
+ expect(last_response.body).to include("console.log('head');")
140
+ expect(last_response.body).to include("console.log('I am evil');")
141
+ end
142
+ end
143
+
144
+ end
108
145
  end
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: 1.6.0
4
+ version: 1.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lars Brillert
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2018-03-27 00:00:00.000000000 Z
12
+ date: 2018-07-19 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rack
@@ -246,7 +246,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
246
246
  version: '0'
247
247
  requirements: []
248
248
  rubyforge_project:
249
- rubygems_version: 2.6.14
249
+ rubygems_version: 2.7.6
250
250
  signing_key:
251
251
  specification_version: 4
252
252
  summary: Tracking made easy