This repository was archived by the owner on Oct 12, 2023. It is now read-only.
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
108 lines (90 loc) · 3.22 KB
/
tracker.rb
File metadata and controls
108 lines (90 loc) · 3.22 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
# frozen_string_literal: true
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)
@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
session[EVENT_TRACKING_KEY] = env[EVENT_TRACKING_KEY] if response.redirection? && session
@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 = {})
# 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