forked from railslove/rack-tracker
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtracker.rb
More file actions
109 lines (92 loc) · 3.25 KB
/
tracker.rb
File metadata and controls
109 lines (92 loc) · 3.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
require "rack"
require "tilt"
require "active_support/core_ext/class/attribute"
require "active_support/core_ext/hash"
require "active_support/json"
require "active_support/inflector"
require "rack/tracker/version"
require "rack/tracker/extensions"
require "rack/tracker/javascript_helper"
require 'rack/tracker/railtie' if defined?(Rails)
require "rack/tracker/handler"
require "rack/tracker/handler_delegator"
require "rack/tracker/controller"
require "rack/tracker/google_analytics/google_analytics"
require "rack/tracker/google_global/google_global"
require "rack/tracker/google_tag_manager/google_tag_manager"
require "rack/tracker/google_adwords_conversion/google_adwords_conversion"
require "rack/tracker/facebook/facebook"
require "rack/tracker/facebook_pixel/facebook_pixel"
require "rack/tracker/vwo/vwo"
require "rack/tracker/go_squared/go_squared"
require "rack/tracker/criteo/criteo"
require "rack/tracker/zanox/zanox"
require "rack/tracker/hotjar/hotjar"
require "rack/tracker/bing/bing"
require "rack/tracker/hubspot/hubspot"
require "rack/tracker/drift/drift"
require "rack/tracker/heap/heap"
module Rack
class Tracker
EVENT_TRACKING_KEY = 'tracker'
def initialize(app, &block)
@app = app
@handlers = Rack::Tracker::HandlerSet.new(&block)
end
def call(env)
dup._call(env)
end
def _call(env)
@status, @headers, @body = @app.call(env)
return [@status, @headers, @body] unless html?
response = Rack::Response.new([], @status, @headers)
env[EVENT_TRACKING_KEY] ||= {}
if session = env["rack.session"]
env[EVENT_TRACKING_KEY].deep_merge!(session.delete(EVENT_TRACKING_KEY) || {}) { |key, old, new| Array.wrap(old) + Array.wrap(new) }
end
if response.redirection? && session
session[EVENT_TRACKING_KEY] = env[EVENT_TRACKING_KEY]
end
@body.each { |fragment| response.write inject(env, fragment) }
@body.close if @body.respond_to?(:close)
response.finish
end
private
def html?; @headers['Content-Type'] =~ /html/; end
def inject(env, response)
duplicated_response = response.dup
@handlers.each(env) do |handler|
handler.inject(duplicated_response)
end
duplicated_response
end
class HandlerSet
Handler = Struct.new(:klass, :configuration) do
def init(env)
klass.new(env, configuration)
end
end
def initialize(&block)
@handlers = []
instance_exec(&block) if block_given?
end
# setup the handler class with configuration options and make it ready for receiving the env during injection
#
# usage:
#
# use Rack::Tracker do
# handler :google_analytics, { tracker: 'U-XXXXX-Y' }
# end
#
def handler(name, configuration = {}, &block)
# we need here "something" (which is atm the handler struct)
# to postpone the initialization of the handler,
# to give it the env and configuration options when the result of the handler is injected into the response.
@handlers << Handler.new(Rack::Tracker::HandlerDelegator.handler(name), configuration)
end
def each(env = {}, &block)
@handlers.map { |h| h.init(env) }.each(&block)
end
end
end
end