rack-tracker 0.4.0 → 0.4.1
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/CHANGELOG.md +3 -1
- data/README.md +79 -3
- data/lib/rack/tracker/criteo/criteo.rb +36 -0
- data/lib/rack/tracker/criteo/template/criteo.erb +9 -0
- data/lib/rack/tracker/google_analytics/google_analytics.rb +15 -2
- data/lib/rack/tracker/google_analytics/template/google_analytics.erb +1 -1
- data/lib/rack/tracker/version.rb +1 -1
- data/lib/rack/tracker/vwo/vwo.rb +1 -1
- data/lib/rack/tracker/zanox/template/zanox.erb +26 -0
- data/lib/rack/tracker/zanox/zanox.rb +37 -0
- data/lib/rack/tracker.rb +2 -0
- data/rack-tracker.gemspec +4 -4
- data/spec/handler/criteo_spec.rb +122 -0
- data/spec/handler/google_analytics_spec.rb +17 -28
- data/spec/handler/zanox_spec.rb +98 -0
- data/spec/integration/criteo_integration_spec.rb +44 -0
- data/spec/integration/google_analytics_integration_spec.rb +0 -1
- data/spec/integration/zanox_integration_spec.rb +25 -0
- data/spec/support/metal_controller.rb +18 -0
- metadata +25 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 656cd1cec1764543d2ab1814545365c34fc143b9
|
4
|
+
data.tar.gz: e801a731569b709bbe9ab85273c047a36e9be3ba
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3151dfd25013fc27de6cdb6dea1659164d2acb9541fbb128d98e2cc0b53f7dd25fd91d09c1f540a0f3142547068edc90d2374a46a7d2dd4ef2ef27425e192f05
|
7
|
+
data.tar.gz: ca4f109a8821ab137328b4c2f402e2e793d52882b3566ba128727049e36cc29dd68cd5ee9ada73db452eee08b972370544918c679380674c185cfffd01cc70e5
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -25,6 +25,8 @@ but to get you started we're shipping support for the following services out of
|
|
25
25
|
* [Facebook](#facebook)
|
26
26
|
* [Visual Website Optimizer (VWO)](#visual-website-optimizer-vwo)
|
27
27
|
* [GoSquared](#gosquared)
|
28
|
+
* [Criteo](#criteo)
|
29
|
+
* [Zanox](#zanox)
|
28
30
|
|
29
31
|
|
30
32
|
## Installation
|
@@ -328,6 +330,8 @@ It will render the following to the site source:
|
|
328
330
|
|
329
331
|
[Criteo](http://www.criteo.com/) retargeting service.
|
330
332
|
|
333
|
+
#### Basic configuration
|
334
|
+
|
331
335
|
```
|
332
336
|
config.middleware.use(Rack::Tracker) do
|
333
337
|
handler :criteo, { set_account: '1234' }
|
@@ -335,13 +339,85 @@ end
|
|
335
339
|
```
|
336
340
|
|
337
341
|
Other global criteo handler options are:
|
338
|
-
* `
|
339
|
-
* `
|
342
|
+
* `set_customer_id: 'x'`
|
343
|
+
* `set_site_type: 'd'` - possible values are `m` (mobile), `t` (tablet), `d` (desktop)
|
344
|
+
|
345
|
+
Option values can be either static or dynamic by providing a lambda being reevaluated for each request, e.g. `set_customer_id: lambda { |env| env['rack.session']['user_id'] }`
|
346
|
+
|
347
|
+
#### Tracking events
|
348
|
+
|
349
|
+
This will track a basic event:
|
350
|
+
|
351
|
+
```
|
352
|
+
def show
|
353
|
+
tracker do |t|
|
354
|
+
t.criteo :view_item, { item: 'P0001' }
|
355
|
+
end
|
356
|
+
end
|
357
|
+
```
|
358
|
+
|
359
|
+
This will render to the follwing code in the JS:
|
360
|
+
|
361
|
+
```
|
362
|
+
window.criteo_q.push({"event": "viewItem", "item": "P001" });
|
363
|
+
```
|
364
|
+
|
365
|
+
The first argument for `t.criteo` is always the criteo event (e.g. `:view_item`, `:view_list`, `:track_transaction`, `:view_basket`) and the second argument are additional properties for the event.
|
366
|
+
|
367
|
+
Another example
|
368
|
+
|
369
|
+
```
|
370
|
+
t.criteo :track_transaction, { id: 'id', item: { id: "P0038", price: "6.54", quantity: 1 } }
|
371
|
+
```
|
372
|
+
|
373
|
+
### Zanox
|
374
|
+
|
375
|
+
[Zanox](http://www.zanox.com/us/)
|
376
|
+
|
377
|
+
#### Basic Configuration
|
378
|
+
|
379
|
+
```
|
380
|
+
config.middleware.use(Rack::Tracker) do
|
381
|
+
handler :zanox, { account_id: '1234' }
|
382
|
+
end
|
383
|
+
```
|
384
|
+
|
385
|
+
#### Mastertag
|
386
|
+
|
387
|
+
This is an example of a mastertag:
|
388
|
+
|
389
|
+
```
|
390
|
+
def show
|
391
|
+
tracker do |t|
|
392
|
+
t.zanox :mastertag, { id: "25GHTE9A07DF67DFG90T" }
|
393
|
+
end
|
394
|
+
end
|
395
|
+
```
|
396
|
+
|
397
|
+
This will render to the follwing code in the JS:
|
398
|
+
|
399
|
+
```
|
400
|
+
window._zx.push({"id": "25GHTE9A07DF67DFG90T"});
|
401
|
+
```
|
402
|
+
|
403
|
+
#### Conversion tracking
|
404
|
+
|
405
|
+
This is an example of a lead event:
|
406
|
+
|
407
|
+
```
|
408
|
+
def show
|
409
|
+
tracker do |t|
|
410
|
+
t.zanox :track, { order_i_d: 'DEFC-4321'}
|
411
|
+
end
|
412
|
+
end
|
413
|
+
```
|
414
|
+
|
415
|
+
This is an example of a sale event:
|
340
416
|
|
341
417
|
```
|
342
418
|
def show
|
343
419
|
tracker do |t|
|
344
|
-
t.
|
420
|
+
t.zanox :track, { customer_i_d: '123456', order_i_d: 'DEFC-4321', currency_symbol: 'EUR', total_price: '150.00'}
|
345
421
|
end
|
346
422
|
end
|
347
423
|
```
|
@@ -0,0 +1,36 @@
|
|
1
|
+
class Rack::Tracker::Criteo < Rack::Tracker::Handler
|
2
|
+
|
3
|
+
TRACKER_EVENTS = {
|
4
|
+
# event name => event key name, e.g. { event: 'setSiteType', type: '' }
|
5
|
+
set_site_type: :type,
|
6
|
+
set_account: :account,
|
7
|
+
set_customer_id: :id
|
8
|
+
}
|
9
|
+
|
10
|
+
class Event < OpenStruct
|
11
|
+
def write
|
12
|
+
to_h.to_json
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
self.position = :body
|
17
|
+
|
18
|
+
# global events (setSiteType, setAccount, ...) for each tracker instance
|
19
|
+
def tracker_events
|
20
|
+
@tracker_events ||= [].tap do |tracker_events|
|
21
|
+
options.slice(*TRACKER_EVENTS.keys).each do |key, value|
|
22
|
+
if option_value = value.respond_to?(:call) ? value.call(env) : value
|
23
|
+
tracker_events << Event.new(:event => "#{key}".camelize(:lower), TRACKER_EVENTS[key] => "#{option_value}")
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def render
|
30
|
+
Tilt.new( File.join( File.dirname(__FILE__), 'template', 'criteo.erb') ).render(self)
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.track(name, event_name, event_args = {})
|
34
|
+
{ name.to_s => [{ 'class_name' => 'Event', 'event' => event_name.to_s.camelize(:lower) }.merge(event_args)] }
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
<% if events.any? %>
|
2
|
+
<script type='text/javascript' src='//static.criteo.net/js/ld/ld.js' async='true'></script>
|
3
|
+
<script type='text/javascript'>
|
4
|
+
window.criteo_q = window.criteo_q || [];
|
5
|
+
<% (tracker_events + events).each do |event| %>
|
6
|
+
window.criteo_q.push(<%= event.write %>);
|
7
|
+
<% end %>
|
8
|
+
</script>
|
9
|
+
<% end %>
|
@@ -23,13 +23,26 @@ class Rack::Tracker::GoogleAnalytics < Rack::Tracker::Handler
|
|
23
23
|
|
24
24
|
class EnhancedEcommerce < OpenStruct
|
25
25
|
def write
|
26
|
-
|
26
|
+
hash = self.to_h
|
27
|
+
label = hash[:label]
|
28
|
+
attributes = hash.except(:label, :type).compact.stringify_values
|
29
|
+
|
30
|
+
[
|
31
|
+
"ec:#{self.type}",
|
32
|
+
label,
|
33
|
+
attributes.empty? ? nil : attributes
|
34
|
+
].compact.to_json.gsub(/\[|\]/, '')
|
27
35
|
end
|
28
36
|
end
|
29
37
|
|
30
38
|
class Ecommerce < OpenStruct
|
31
39
|
def write
|
32
|
-
|
40
|
+
attributes = self.to_h.except(:type).compact.stringify_values
|
41
|
+
|
42
|
+
[
|
43
|
+
"ecommerce:#{self.type}",
|
44
|
+
attributes
|
45
|
+
].to_json.gsub(/\[|\]/, '')
|
33
46
|
end
|
34
47
|
end
|
35
48
|
|
@@ -14,7 +14,7 @@
|
|
14
14
|
<% if options[:advertising] %>
|
15
15
|
ga('require', 'displayfeatures');
|
16
16
|
<% end %>
|
17
|
-
<% if options[:enhanced_ecommerce]
|
17
|
+
<% if options[:enhanced_ecommerce] %>
|
18
18
|
ga('require', 'ec');
|
19
19
|
<% end %>
|
20
20
|
<% if options[:ecommerce] %>
|
data/lib/rack/tracker/version.rb
CHANGED
data/lib/rack/tracker/vwo/vwo.rb
CHANGED
@@ -0,0 +1,26 @@
|
|
1
|
+
<% if mastertag %>
|
2
|
+
|
3
|
+
<div class="zx_<%= mastertag.id %> zx_mediaslot">
|
4
|
+
<script type="text/javascript">
|
5
|
+
window._zx = window._zx || [];
|
6
|
+
window._zx.push({"id": "<%= mastertag.id %>"});
|
7
|
+
(function(d) {
|
8
|
+
var s = d.createElement("script"); s.async = true;
|
9
|
+
s.src = (d.location.protocol == "https:" ? "https:" : "http:") + "//static.zanox.com/scripts/zanox.js";
|
10
|
+
var a = d.getElementsByTagName("script")[0]; a.parentNode.insertBefore(s, a);
|
11
|
+
}(document));
|
12
|
+
</script>
|
13
|
+
</div>
|
14
|
+
|
15
|
+
<% end %>
|
16
|
+
|
17
|
+
<% tracking_events.each do |event| %>
|
18
|
+
|
19
|
+
<script type="text/javascript" src="https://ad.zanox.com/ppl/?<%= options[:account_id] %>&mode=[[1]]&<%= event.write %>">
|
20
|
+
</script>
|
21
|
+
|
22
|
+
<noscript>
|
23
|
+
<img src="https://ad.zanox.com/ppl/?<%= options[:account_id] %>&mode=[[2]]&<%= event.write %>" width="1" height="1" />
|
24
|
+
</noscript>
|
25
|
+
|
26
|
+
<% end %>
|
@@ -0,0 +1,37 @@
|
|
1
|
+
class Rack::Tracker::Zanox < Rack::Tracker::Handler
|
2
|
+
|
3
|
+
# name of the handler
|
4
|
+
# everything after is passed as options
|
5
|
+
class Mastertag < OpenStruct
|
6
|
+
end
|
7
|
+
|
8
|
+
class Track < OpenStruct
|
9
|
+
# Example: OrderID=[[DEFC-4321]]&CurrencySymbol=[[EUR]]&TotalPrice=[[23.40]]
|
10
|
+
def write
|
11
|
+
to_h.map do |k,v|
|
12
|
+
"#{k.to_s.camelize}=[[#{v}]]"
|
13
|
+
end.join('&')
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
self.position = :body
|
18
|
+
|
19
|
+
def mastertag
|
20
|
+
# First event should be stronger, e.g. one signs up and gets redirected to homepage
|
21
|
+
# "sign up" should be tracked instead of "view homepage"
|
22
|
+
events.select{ |event| event.class.to_s.demodulize == 'Mastertag' }.first
|
23
|
+
end
|
24
|
+
|
25
|
+
def tracking_events
|
26
|
+
events.select{ |event| event.class.to_s.demodulize == 'Track' }
|
27
|
+
end
|
28
|
+
|
29
|
+
def render
|
30
|
+
Tilt.new( File.join( File.dirname(__FILE__), 'template', 'zanox.erb') ).render(self)
|
31
|
+
end
|
32
|
+
|
33
|
+
# this is called with additional arguments to t.zanox
|
34
|
+
def self.track(name, *event)
|
35
|
+
{ name.to_s => [event.last.merge('class_name' => event.first.to_s.capitalize)] }
|
36
|
+
end
|
37
|
+
end
|
data/lib/rack/tracker.rb
CHANGED
@@ -17,6 +17,8 @@ require "rack/tracker/google_adwords_conversion/google_adwords_conversion"
|
|
17
17
|
require "rack/tracker/facebook/facebook"
|
18
18
|
require "rack/tracker/vwo/vwo"
|
19
19
|
require "rack/tracker/go_squared/go_squared"
|
20
|
+
require "rack/tracker/criteo/criteo"
|
21
|
+
require "rack/tracker/zanox/zanox"
|
20
22
|
|
21
23
|
module Rack
|
22
24
|
class Tracker
|
data/rack-tracker.gemspec
CHANGED
@@ -18,14 +18,14 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
|
-
spec.add_dependency "rack", ">= 1.4
|
22
|
-
spec.add_dependency "tilt", "
|
21
|
+
spec.add_dependency "rack", ">= 1.4"
|
22
|
+
spec.add_dependency "tilt", ">= 1.4"
|
23
23
|
spec.add_dependency 'activesupport', '>= 3.0'
|
24
24
|
|
25
25
|
spec.add_development_dependency 'actionpack', '>= 3.0'
|
26
26
|
spec.add_development_dependency "bundler", "~> 1.5"
|
27
27
|
spec.add_development_dependency "rake"
|
28
|
-
spec.add_development_dependency "rspec", "~> 3.
|
29
|
-
spec.add_development_dependency "capybara", "~> 2.4
|
28
|
+
spec.add_development_dependency "rspec", "~> 3.2"
|
29
|
+
spec.add_development_dependency "capybara", "~> 2.4"
|
30
30
|
spec.add_development_dependency "pry"
|
31
31
|
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
RSpec.describe Rack::Tracker::Criteo do
|
2
|
+
|
3
|
+
describe Rack::Tracker::Criteo::Event do
|
4
|
+
|
5
|
+
subject { described_class.new(event: "viewItem", item: 'P001') }
|
6
|
+
|
7
|
+
describe '#write' do
|
8
|
+
specify { expect(subject.write).to eq("{\"event\":\"viewItem\",\"item\":\"P001\"}") }
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def env
|
13
|
+
{}
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'will be placed in the body' do
|
17
|
+
expect(described_class.position).to eq(:body)
|
18
|
+
expect(described_class.new(env).position).to eq(:body)
|
19
|
+
end
|
20
|
+
|
21
|
+
describe '#render' do
|
22
|
+
context 'with events' do
|
23
|
+
let(:env) {
|
24
|
+
{
|
25
|
+
'tracker' => {
|
26
|
+
'criteo' =>
|
27
|
+
[
|
28
|
+
{
|
29
|
+
'event' => 'viewItem',
|
30
|
+
'item' => 'P001',
|
31
|
+
'class_name' => 'Event'
|
32
|
+
}
|
33
|
+
]
|
34
|
+
}
|
35
|
+
}
|
36
|
+
}
|
37
|
+
|
38
|
+
subject { described_class.new(env).render }
|
39
|
+
|
40
|
+
it 'will push the tracking events to the queue' do
|
41
|
+
expect(subject).to include 'window.criteo_q.push({"event":"viewItem","item":"P001"});'
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context 'without events' do
|
46
|
+
let(:env) {
|
47
|
+
{
|
48
|
+
'tracker' => {
|
49
|
+
'criteo' => []
|
50
|
+
}
|
51
|
+
}
|
52
|
+
}
|
53
|
+
|
54
|
+
subject { described_class.new(env, { user_id: ->(env){ '123' } }).render }
|
55
|
+
|
56
|
+
it 'should render nothing' do
|
57
|
+
expect(subject).to eql ""
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe '#tracker_events' do
|
63
|
+
subject { described_class.new(env, options) }
|
64
|
+
|
65
|
+
context 'nil value' do
|
66
|
+
let(:options) { { set_account: nil } }
|
67
|
+
|
68
|
+
it 'should ignore option' do
|
69
|
+
expect(subject.tracker_events).to match_array []
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
context 'static string value' do
|
74
|
+
let(:options) { { set_account: '1234' } }
|
75
|
+
|
76
|
+
it 'should set the value' do
|
77
|
+
expect(subject.tracker_events).to match_array [
|
78
|
+
Rack::Tracker::Criteo::Event.new(event: 'setAccount', account: '1234')
|
79
|
+
]
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
context 'static integer value' do
|
84
|
+
let(:options) { { set_customer_id: 1234 } }
|
85
|
+
|
86
|
+
it 'should set the value as string' do
|
87
|
+
expect(subject.tracker_events).to match_array [
|
88
|
+
Rack::Tracker::Criteo::Event.new(event: 'setCustomerId', id: '1234')
|
89
|
+
]
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
context 'unsupported option' do
|
94
|
+
let(:options) { { unsupported: "option" } }
|
95
|
+
|
96
|
+
subject { described_class.new(env, options) }
|
97
|
+
|
98
|
+
it 'should ignore the option' do
|
99
|
+
expect(subject.tracker_events).to match_array []
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
context 'proc returning value' do
|
104
|
+
let(:options) { { set_site_type: ->(env){ 'm' } } }
|
105
|
+
|
106
|
+
it 'should set the value' do
|
107
|
+
expect(subject.tracker_events).to match_array [
|
108
|
+
Rack::Tracker::Criteo::Event.new(event: 'setSiteType', type: 'm')
|
109
|
+
]
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
context 'proc returning nil' do
|
114
|
+
let(:options) { { set_account: ->(env){ nil } } }
|
115
|
+
|
116
|
+
it 'should ignore the option' do
|
117
|
+
expect(subject.tracker_events).to match_array []
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
@@ -91,6 +91,8 @@ RSpec.describe Rack::Tracker::GoogleAnalytics do
|
|
91
91
|
end
|
92
92
|
|
93
93
|
describe "with events" do
|
94
|
+
subject { described_class.new(env, tracker: 'somebody').render }
|
95
|
+
|
94
96
|
describe "default" do
|
95
97
|
def env
|
96
98
|
{'tracker' => {
|
@@ -100,7 +102,6 @@ RSpec.describe Rack::Tracker::GoogleAnalytics do
|
|
100
102
|
}}
|
101
103
|
end
|
102
104
|
|
103
|
-
subject { described_class.new(env, tracker: 'somebody').render }
|
104
105
|
it "will show events" do
|
105
106
|
expect(subject).to match(%r{ga\(\"send\",{\"hitType\":\"event\",\"eventCategory\":\"Users\",\"eventAction\":\"Login\",\"eventLabel\":\"Standard\"}\)})
|
106
107
|
end
|
@@ -113,7 +114,6 @@ RSpec.describe Rack::Tracker::GoogleAnalytics do
|
|
113
114
|
]}}
|
114
115
|
end
|
115
116
|
|
116
|
-
subject { described_class.new(env, tracker: 'somebody').render }
|
117
117
|
it "will show events with values" do
|
118
118
|
expect(subject).to match(%r{ga\(\"send\",{\"hitType\":\"event\",\"eventCategory\":\"Users\",\"eventAction\":\"Login\",\"eventLabel\":\"Standard\",\"eventValue\":\"5\"}\)},)
|
119
119
|
end
|
@@ -132,12 +132,17 @@ RSpec.describe Rack::Tracker::GoogleAnalytics do
|
|
132
132
|
end
|
133
133
|
|
134
134
|
subject { described_class.new(env, tracker: 'somebody', ecommerce: true).render }
|
135
|
+
|
135
136
|
it "will add items" do
|
136
|
-
|
137
|
+
attributes = { id: '1234', name: 'Fluffy Pink Bunnies', sku: 'DD23444', category: 'Party Toys', price: '11.99', quantity: '1' }.to_json
|
138
|
+
expect(subject).to match(%r{ga\(\"ecommerce:addItem\",#{attributes}\);})
|
137
139
|
end
|
140
|
+
|
138
141
|
it "will add transaction" do
|
139
|
-
|
142
|
+
attributes = { id: '1234', affiliation: 'Acme Clothing', revenue: '11.99', shipping: '5', tax: '1.29', currency: 'EUR' }.to_json
|
143
|
+
expect(subject).to match(%r{ga\(\"ecommerce:addTransaction\",#{attributes}\);})
|
140
144
|
end
|
145
|
+
|
141
146
|
it "will submit cart" do
|
142
147
|
expect(subject).to match(%r{ga\('ecommerce:send'\);})
|
143
148
|
end
|
@@ -150,18 +155,20 @@ RSpec.describe Rack::Tracker::GoogleAnalytics do
|
|
150
155
|
{'tracker' => {
|
151
156
|
'google_analytics' => [
|
152
157
|
{ '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', '
|
158
|
+
{ 'class_name' => 'EnhancedEcommerce', 'type' => 'setAction', 'label' => 'purchase' }
|
154
159
|
]
|
155
160
|
}}
|
156
161
|
end
|
157
162
|
|
158
163
|
subject { described_class.new(env, tracker: 'somebody', enhanced_ecommerce: true).render }
|
164
|
+
|
159
165
|
it "will add product" do
|
160
|
-
|
166
|
+
attributes = { id: 'P12345', name: 'Android Warhol T-Shirt', category: 'Apparel', brand: 'Google', variant: 'black', price: '29.20', coupon: 'APPARELSALE', quantity: '1' }.to_json
|
167
|
+
expect(subject).to match(%r{ga\(\"ec:addProduct\",#{attributes}\);})
|
161
168
|
end
|
162
169
|
|
163
170
|
it "will add action" do
|
164
|
-
expect(subject).to match(%r{ga\(\"ec:setAction\"
|
171
|
+
expect(subject).to match(%r{ga\(\"ec:setAction\",\"purchase\"\);})
|
165
172
|
end
|
166
173
|
end
|
167
174
|
end
|
@@ -217,28 +224,10 @@ RSpec.describe Rack::Tracker::GoogleAnalytics do
|
|
217
224
|
end
|
218
225
|
|
219
226
|
describe "with enhanced ecommerce" do
|
220
|
-
|
221
|
-
subject { described_class.new(env, tracker: 'happy', enhanced_ecommerce: true).render }
|
227
|
+
subject { described_class.new(env, tracker: 'happy', enhanced_ecommerce: true).render }
|
222
228
|
|
223
|
-
|
224
|
-
|
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
|
229
|
+
it "will require the enhanced ecommerce plugin" do
|
230
|
+
expect(subject).to match(%r{ga\('require', 'ec'\)})
|
242
231
|
end
|
243
232
|
end
|
244
233
|
|
@@ -0,0 +1,98 @@
|
|
1
|
+
RSpec.describe Rack::Tracker::Zanox do
|
2
|
+
|
3
|
+
describe Rack::Tracker::Zanox::Track do
|
4
|
+
|
5
|
+
subject { described_class.new(order_i_d: 'DEFC-4321', currency_symbol: 'EUR', total_price: '150.00') }
|
6
|
+
|
7
|
+
describe '#write' do
|
8
|
+
specify { expect(subject.write).to eq "OrderID=[[DEFC-4321]]&CurrencySymbol=[[EUR]]&TotalPrice=[[150.00]]" }
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def env
|
13
|
+
{}
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'will be placed in the body' do
|
17
|
+
expect(described_class.position).to eq(:body)
|
18
|
+
expect(described_class.new(env).position).to eq(:body)
|
19
|
+
end
|
20
|
+
|
21
|
+
describe '#render a sale #tracking_event' do
|
22
|
+
context 'with events' do
|
23
|
+
let(:env) {
|
24
|
+
{
|
25
|
+
'tracker' => {
|
26
|
+
'zanox' =>
|
27
|
+
[
|
28
|
+
{
|
29
|
+
'CustomerID' => '123456',
|
30
|
+
'OrderId' => 'DEFC-4321',
|
31
|
+
'CurrencySymbol' => 'EUR',
|
32
|
+
'TotalPrice' => '150.00',
|
33
|
+
'class_name' => 'Track'
|
34
|
+
}
|
35
|
+
]
|
36
|
+
}
|
37
|
+
}
|
38
|
+
}
|
39
|
+
|
40
|
+
subject { described_class.new(env, options).render }
|
41
|
+
let(:options) { { account_id: '123456H123456' } }
|
42
|
+
|
43
|
+
it 'will display the correct tracking events' do
|
44
|
+
expect(subject).to include "https://ad.zanox.com/ppl/?123456H123456&mode=[[1]]&CustomerID=[[123456]]&OrderId=[[DEFC-4321]]&CurrencySymbol=[[EUR]]&TotalPrice=[[150.00]]"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe '#render a lead #tracking_event' do
|
50
|
+
context 'with events' do
|
51
|
+
let(:env) {
|
52
|
+
{
|
53
|
+
'tracker' => {
|
54
|
+
'zanox' =>
|
55
|
+
[
|
56
|
+
{
|
57
|
+
'OrderId' => 'DEFC-4321',
|
58
|
+
'class_name' => 'Track'
|
59
|
+
}
|
60
|
+
]
|
61
|
+
}
|
62
|
+
}
|
63
|
+
}
|
64
|
+
|
65
|
+
subject { described_class.new(env, options).render }
|
66
|
+
let(:options) { { account_id: '123456H123456' } }
|
67
|
+
|
68
|
+
it 'will display the correct tracking events' do
|
69
|
+
expect(subject).to include "https://ad.zanox.com/ppl/?123456H123456&mode=[[1]]&OrderId=[[DEFC-4321]]"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
describe '#render a #mastertag event' do
|
75
|
+
context 'with events' do
|
76
|
+
let(:env) {
|
77
|
+
{
|
78
|
+
'tracker' => {
|
79
|
+
'zanox' =>
|
80
|
+
[
|
81
|
+
{
|
82
|
+
'id' => '12345678D2345',
|
83
|
+
'class_name' => 'Mastertag'
|
84
|
+
}
|
85
|
+
]
|
86
|
+
}
|
87
|
+
}
|
88
|
+
}
|
89
|
+
|
90
|
+
subject { described_class.new(env, options).render }
|
91
|
+
let(:options) { { account_id: '123456H123456' } }
|
92
|
+
|
93
|
+
it 'will display the correct tracking events' do
|
94
|
+
expect(subject).to include 'window._zx.push({"id": "12345678D2345"});'
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'support/capybara_app_helper'
|
2
|
+
|
3
|
+
RSpec.describe "Criteo Integration" do
|
4
|
+
before do
|
5
|
+
setup_app(action: :criteo) do |tracker|
|
6
|
+
tracker.handler(:criteo, {
|
7
|
+
set_account: '1234',
|
8
|
+
set_customer_id: ->(env){ '4711' },
|
9
|
+
set_site_type: ->(env){ 'm' }
|
10
|
+
})
|
11
|
+
end
|
12
|
+
visit '/'
|
13
|
+
end
|
14
|
+
|
15
|
+
subject { page }
|
16
|
+
|
17
|
+
it 'should include all the events' do
|
18
|
+
# tracker_events
|
19
|
+
expect(page.find("body")).to have_content "window.criteo_q.push({\"event\":\"setAccount\",\"account\":\"1234\"});"
|
20
|
+
expect(page.find("body")).to have_content "window.criteo_q.push({\"event\":\"setSiteType\",\"type\":\"m\"});"
|
21
|
+
expect(page.find("body")).to have_content "window.criteo_q.push({\"event\":\"setCustomerId\",\"id\":\"4711\"});"
|
22
|
+
|
23
|
+
# events
|
24
|
+
expect(page.find("body")).to have_content "window.criteo_q.push({\"event\":\"viewItem\",\"item\":\"P001\"});"
|
25
|
+
expect(page.find("body")).to have_content "window.criteo_q.push({\"event\":\"viewList\",\"item\":[\"P001\",\"P002\"]});"
|
26
|
+
expect(page.find("body")).to have_content "window.criteo_q.push({\"event\":\"trackTransaction\",\"id\":\"id\",\"item\":{\"id\":\"P0038\",\"price\":\"6.54\",\"quantity\":1}});"
|
27
|
+
expect(page.find("body")).to have_content "window.criteo_q.push({\"event\":\"viewBasket\",\"item\":[{\"id\":\"P001\",\"price\":\"6.54\",\"quantity\":1},{\"id\":\"P0038\",\"price\":\"2.99\",\"quantity\":1}]});"
|
28
|
+
end
|
29
|
+
|
30
|
+
describe 'adjust tracker position via options' do
|
31
|
+
before do
|
32
|
+
setup_app(action: :criteo) do |tracker|
|
33
|
+
tracker.handler :criteo, { set_account: '1234', position: :head }
|
34
|
+
end
|
35
|
+
visit '/'
|
36
|
+
end
|
37
|
+
|
38
|
+
it "will be placed in the specified tag" do
|
39
|
+
expect(page.find("body")).to_not have_content('criteo')
|
40
|
+
expect(page.find("head")).to have_content("{\"event\":\"setAccount\",\"account\":\"1234\"}")
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
@@ -28,6 +28,5 @@ RSpec.describe "Google Analytics Integration" do
|
|
28
28
|
expect(page.find("head")).to_not have_content('U-XXX-Y')
|
29
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
30
|
end
|
31
|
-
|
32
31
|
end
|
33
32
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'support/capybara_app_helper'
|
2
|
+
|
3
|
+
RSpec.describe "Zanox Integration" do
|
4
|
+
|
5
|
+
before do
|
6
|
+
setup_app(action: :zanox) do |tracker|
|
7
|
+
tracker.handler(:zanox, { account_id: '12345H123456789' } )
|
8
|
+
end
|
9
|
+
|
10
|
+
visit '/'
|
11
|
+
end
|
12
|
+
|
13
|
+
subject { page }
|
14
|
+
|
15
|
+
it 'should include the mastertag event' do
|
16
|
+
expect(page.find("body")).to have_content "window._zx.push({\"id\": \"blurg567\"});"
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should include the track event' do
|
20
|
+
expect(page).to have_xpath "//script[contains(@src,'12345H123456789&mode=[[1]]&CustomerID=[[123456]]&OrderID=[[DEFC-4321]]&CurrencySymbol=[[EUR]]&TotalPrice=[[150.00]]')]"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
|
@@ -64,4 +64,22 @@ class MetalController < ActionController::Metal
|
|
64
64
|
end
|
65
65
|
render "metal/index"
|
66
66
|
end
|
67
|
+
|
68
|
+
def criteo
|
69
|
+
tracker do |t|
|
70
|
+
t.criteo :view_item, { item: 'P001' }
|
71
|
+
t.criteo :view_list, { item: ['P001', 'P002'] }
|
72
|
+
t.criteo :track_transaction, { id: 'id', item: { id: "P0038", price:"6.54", quantity:1 } }
|
73
|
+
t.criteo :view_basket, { item: [{ id: "P001", price:"6.54", quantity:1 }, { id: "P0038", price:"2.99", quantity:1 }] }
|
74
|
+
end
|
75
|
+
render 'metal/index'
|
76
|
+
end
|
77
|
+
|
78
|
+
def zanox
|
79
|
+
tracker do |t|
|
80
|
+
t.zanox :mastertag, { id: 'blurg567'}
|
81
|
+
t.zanox :track, { customer_i_d: '123456', order_i_d: 'DEFC-4321', currency_symbol: 'EUR', total_price: '150.00'}
|
82
|
+
end
|
83
|
+
render 'metal/index'
|
84
|
+
end
|
67
85
|
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: 0.4.
|
4
|
+
version: 0.4.1
|
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: 2015-
|
12
|
+
date: 2015-05-22 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rack
|
@@ -17,28 +17,28 @@ dependencies:
|
|
17
17
|
requirements:
|
18
18
|
- - ">="
|
19
19
|
- !ruby/object:Gem::Version
|
20
|
-
version: 1.4
|
20
|
+
version: '1.4'
|
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
|
-
version: 1.4
|
27
|
+
version: '1.4'
|
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
|
-
version: 1.4
|
34
|
+
version: '1.4'
|
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
|
-
version: 1.4
|
41
|
+
version: '1.4'
|
42
42
|
- !ruby/object:Gem::Dependency
|
43
43
|
name: activesupport
|
44
44
|
requirement: !ruby/object:Gem::Requirement
|
@@ -101,28 +101,28 @@ dependencies:
|
|
101
101
|
requirements:
|
102
102
|
- - "~>"
|
103
103
|
- !ruby/object:Gem::Version
|
104
|
-
version: 3.
|
104
|
+
version: '3.2'
|
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
|
-
version: 3.
|
111
|
+
version: '3.2'
|
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
|
-
version: 2.4
|
118
|
+
version: '2.4'
|
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
|
-
version: 2.4
|
125
|
+
version: '2.4'
|
126
126
|
- !ruby/object:Gem::Dependency
|
127
127
|
name: pry
|
128
128
|
requirement: !ruby/object:Gem::Requirement
|
@@ -156,6 +156,8 @@ files:
|
|
156
156
|
- Rakefile
|
157
157
|
- lib/rack/tracker.rb
|
158
158
|
- lib/rack/tracker/controller.rb
|
159
|
+
- lib/rack/tracker/criteo/criteo.rb
|
160
|
+
- lib/rack/tracker/criteo/template/criteo.erb
|
159
161
|
- lib/rack/tracker/extensions.rb
|
160
162
|
- lib/rack/tracker/facebook/facebook.rb
|
161
163
|
- lib/rack/tracker/facebook/template/facebook.erb
|
@@ -173,18 +175,23 @@ files:
|
|
173
175
|
- lib/rack/tracker/version.rb
|
174
176
|
- lib/rack/tracker/vwo/template/vwo.erb
|
175
177
|
- lib/rack/tracker/vwo/vwo.rb
|
178
|
+
- lib/rack/tracker/zanox/template/zanox.erb
|
179
|
+
- lib/rack/tracker/zanox/zanox.rb
|
176
180
|
- rack-tracker.gemspec
|
177
181
|
- spec/fixtures/another_handler.erb
|
178
182
|
- spec/fixtures/dummy.erb
|
179
183
|
- spec/fixtures/track_all_the_things.erb
|
180
184
|
- spec/fixtures/views/layouts/application.html.erb
|
181
185
|
- spec/fixtures/views/metal/index.html.erb
|
186
|
+
- spec/handler/criteo_spec.rb
|
182
187
|
- spec/handler/facebook_spec.rb
|
183
188
|
- spec/handler/go_squared_spec.rb
|
184
189
|
- spec/handler/google_adwords_conversion_spec.rb
|
185
190
|
- spec/handler/google_analytics_spec.rb
|
186
191
|
- spec/handler/google_tag_manager_spec.rb
|
187
192
|
- spec/handler/vwo_spec.rb
|
193
|
+
- spec/handler/zanox_spec.rb
|
194
|
+
- spec/integration/criteo_integration_spec.rb
|
188
195
|
- spec/integration/facebook_integration_spec.rb
|
189
196
|
- spec/integration/go_squared_integration_spec.rb
|
190
197
|
- spec/integration/google_adwords_conversion_integration_spec.rb
|
@@ -192,6 +199,7 @@ files:
|
|
192
199
|
- spec/integration/google_tag_manager_integration_spec.rb
|
193
200
|
- spec/integration/rails_integration_spec.rb
|
194
201
|
- spec/integration/vwo_integration_spec.rb
|
202
|
+
- spec/integration/zanox_integration_spec.rb
|
195
203
|
- spec/spec_helper.rb
|
196
204
|
- spec/support/capybara_app_helper.rb
|
197
205
|
- spec/support/fake_handler.rb
|
@@ -220,7 +228,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
220
228
|
version: '0'
|
221
229
|
requirements: []
|
222
230
|
rubyforge_project:
|
223
|
-
rubygems_version: 2.
|
231
|
+
rubygems_version: 2.2.2
|
224
232
|
signing_key:
|
225
233
|
specification_version: 4
|
226
234
|
summary: Tracking made easy
|
@@ -230,12 +238,15 @@ test_files:
|
|
230
238
|
- spec/fixtures/track_all_the_things.erb
|
231
239
|
- spec/fixtures/views/layouts/application.html.erb
|
232
240
|
- spec/fixtures/views/metal/index.html.erb
|
241
|
+
- spec/handler/criteo_spec.rb
|
233
242
|
- spec/handler/facebook_spec.rb
|
234
243
|
- spec/handler/go_squared_spec.rb
|
235
244
|
- spec/handler/google_adwords_conversion_spec.rb
|
236
245
|
- spec/handler/google_analytics_spec.rb
|
237
246
|
- spec/handler/google_tag_manager_spec.rb
|
238
247
|
- spec/handler/vwo_spec.rb
|
248
|
+
- spec/handler/zanox_spec.rb
|
249
|
+
- spec/integration/criteo_integration_spec.rb
|
239
250
|
- spec/integration/facebook_integration_spec.rb
|
240
251
|
- spec/integration/go_squared_integration_spec.rb
|
241
252
|
- spec/integration/google_adwords_conversion_integration_spec.rb
|
@@ -243,6 +254,7 @@ test_files:
|
|
243
254
|
- spec/integration/google_tag_manager_integration_spec.rb
|
244
255
|
- spec/integration/rails_integration_spec.rb
|
245
256
|
- spec/integration/vwo_integration_spec.rb
|
257
|
+
- spec/integration/zanox_integration_spec.rb
|
246
258
|
- spec/spec_helper.rb
|
247
259
|
- spec/support/capybara_app_helper.rb
|
248
260
|
- spec/support/fake_handler.rb
|