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 +5 -5
- data/CHANGELOG.md +5 -0
- data/README.md +47 -0
- data/lib/rack/tracker.rb +3 -2
- data/lib/rack/tracker/google_analytics/google_analytics.rb +4 -0
- data/lib/rack/tracker/google_analytics/template/google_analytics.erb +1 -1
- data/lib/rack/tracker/handler.rb +10 -0
- data/lib/rack/tracker/version.rb +1 -1
- data/spec/handler/google_analytics_spec.rb +18 -0
- data/spec/integration/google_analytics_integration_spec.rb +19 -1
- data/spec/tracker/tracker_spec.rb +37 -0
- metadata +3 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 55705dd46c88e815dd7b0187c3d6d2a50b36a79f5ccc52e801a96d282ba348be
|
|
4
|
+
data.tar.gz: 5cad1746a043405f4f0e1b2cf85904dd9a6daa50923199d77d71bb32b7a357ba
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 0ea613048f9899f3c532eee40c7dd40ed9e4c6c6623f318df1522bbb11e3a05656bb3b96adf0b3b46bd10e33c34f9ab5774c7d48402e1830e3efff2042b144e2
|
|
7
|
+
data.tar.gz: ea8b57893ebdcc970e55085f20cefc4cdb1e18f5172b6e44cc3c54a2189335109cafe0694e30854edaa90ed3f3d8330051dc2619b7826f3a5180cb168ea129d3
|
data/CHANGELOG.md
CHANGED
|
@@ -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.
|
data/lib/rack/tracker.rb
CHANGED
|
@@ -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(
|
|
63
|
+
handler.inject(duplicated_response)
|
|
63
64
|
end
|
|
64
|
-
|
|
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)
|
data/lib/rack/tracker/handler.rb
CHANGED
|
@@ -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.
|
data/lib/rack/tracker/version.rb
CHANGED
|
@@ -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
|
-
|
|
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.
|
|
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-
|
|
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
|
|
249
|
+
rubygems_version: 2.7.6
|
|
250
250
|
signing_key:
|
|
251
251
|
specification_version: 4
|
|
252
252
|
summary: Tracking made easy
|