mbuzz 0.7.1 → 0.7.2
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/lib/mbuzz/client/session_request.rb +75 -0
- data/lib/mbuzz/client.rb +12 -0
- data/lib/mbuzz/current.rb +1 -0
- data/lib/mbuzz/middleware/tracking.rb +76 -2
- data/lib/mbuzz/version.rb +1 -1
- data/lib/mbuzz.rb +5 -0
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0d8514076473bbc4fa543510e84789f8cb91ccc99e916b3cef4f4928aaf6baf5
|
|
4
|
+
data.tar.gz: 159074f0dbac29eb6b721bab4288ce976e4e4361ba503caffc36f37e79cf315e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3d515f639e577a68d9daa8afe13de92dec0a5556cfad2e335ea482f7db0240ff996dd1fb6bbf3388e7f632cb8300e439028091cf1c551627c9be1c22e73ca666
|
|
7
|
+
data.tar.gz: 9fbe4999f2ce0855d83847d61b4684f30217c01c9074df4cced51e4083167cf3ca24e0e5223f2e57fd859aab6d88f60a68a0adc3074bd0a7f4356c0f9d3e5116
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Mbuzz
|
|
4
|
+
class Client
|
|
5
|
+
class SessionRequest
|
|
6
|
+
# Response keys
|
|
7
|
+
STATUS_KEY = "status"
|
|
8
|
+
VISITOR_ID_KEY = "visitor_id"
|
|
9
|
+
SESSION_ID_KEY = "session_id"
|
|
10
|
+
CHANNEL_KEY = "channel"
|
|
11
|
+
|
|
12
|
+
# Response values
|
|
13
|
+
ACCEPTED_STATUS = "accepted"
|
|
14
|
+
|
|
15
|
+
def initialize(visitor_id:, session_id:, url:, referrer: nil, device_fingerprint: nil, started_at: nil)
|
|
16
|
+
@visitor_id = visitor_id
|
|
17
|
+
@session_id = session_id
|
|
18
|
+
@url = url
|
|
19
|
+
@referrer = referrer
|
|
20
|
+
@device_fingerprint = device_fingerprint
|
|
21
|
+
@started_at = started_at
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def call
|
|
25
|
+
return false unless valid?
|
|
26
|
+
|
|
27
|
+
parse_response(response)
|
|
28
|
+
rescue StandardError
|
|
29
|
+
false
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
private
|
|
33
|
+
|
|
34
|
+
attr_reader :visitor_id, :session_id, :url, :referrer, :device_fingerprint, :started_at
|
|
35
|
+
|
|
36
|
+
def valid?
|
|
37
|
+
present?(visitor_id) && present?(session_id) && present?(url)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def response
|
|
41
|
+
@response ||= Api.post_with_response(SESSIONS_PATH, { session: payload })
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def payload
|
|
45
|
+
{
|
|
46
|
+
visitor_id: visitor_id,
|
|
47
|
+
session_id: session_id,
|
|
48
|
+
url: url,
|
|
49
|
+
referrer: referrer,
|
|
50
|
+
device_fingerprint: device_fingerprint,
|
|
51
|
+
started_at: started_at || Time.now.utc.iso8601
|
|
52
|
+
}.compact
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def parse_response(resp)
|
|
56
|
+
return false unless accepted?(resp)
|
|
57
|
+
|
|
58
|
+
{
|
|
59
|
+
success: true,
|
|
60
|
+
visitor_id: resp[VISITOR_ID_KEY],
|
|
61
|
+
session_id: resp[SESSION_ID_KEY],
|
|
62
|
+
channel: resp[CHANNEL_KEY]
|
|
63
|
+
}
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def accepted?(resp)
|
|
67
|
+
resp && resp[STATUS_KEY] == ACCEPTED_STATUS
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def present?(value)
|
|
71
|
+
value && !value.to_s.strip.empty?
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
data/lib/mbuzz/client.rb
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
require_relative "client/track_request"
|
|
4
4
|
require_relative "client/identify_request"
|
|
5
5
|
require_relative "client/conversion_request"
|
|
6
|
+
require_relative "client/session_request"
|
|
6
7
|
|
|
7
8
|
module Mbuzz
|
|
8
9
|
class Client
|
|
@@ -30,5 +31,16 @@ module Mbuzz
|
|
|
30
31
|
identifier: identifier
|
|
31
32
|
).call
|
|
32
33
|
end
|
|
34
|
+
|
|
35
|
+
def self.session(visitor_id:, session_id:, url:, referrer: nil, device_fingerprint: nil, started_at: nil)
|
|
36
|
+
SessionRequest.new(
|
|
37
|
+
visitor_id: visitor_id,
|
|
38
|
+
session_id: session_id,
|
|
39
|
+
url: url,
|
|
40
|
+
referrer: referrer,
|
|
41
|
+
device_fingerprint: device_fingerprint,
|
|
42
|
+
started_at: started_at
|
|
43
|
+
).call
|
|
44
|
+
end
|
|
33
45
|
end
|
|
34
46
|
end
|
data/lib/mbuzz/current.rb
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "rack"
|
|
4
|
+
require "digest"
|
|
5
|
+
require "securerandom"
|
|
4
6
|
|
|
5
7
|
module Mbuzz
|
|
6
8
|
module Middleware
|
|
@@ -16,13 +18,17 @@ module Mbuzz
|
|
|
16
18
|
context = build_request_context(request)
|
|
17
19
|
|
|
18
20
|
env[ENV_VISITOR_ID_KEY] = context[:visitor_id]
|
|
21
|
+
env[ENV_SESSION_ID_KEY] = context[:session_id]
|
|
19
22
|
env[ENV_USER_ID_KEY] = context[:user_id]
|
|
20
23
|
|
|
21
24
|
store_in_current_attributes(context, request)
|
|
22
25
|
|
|
26
|
+
create_session_async(context, request) if context[:new_session]
|
|
27
|
+
|
|
23
28
|
RequestContext.with_context(request: request) do
|
|
24
29
|
status, headers, body = @app.call(env)
|
|
25
30
|
set_visitor_cookie(headers, context, request)
|
|
31
|
+
set_session_cookie(headers, context, request)
|
|
26
32
|
[status, headers, body]
|
|
27
33
|
ensure
|
|
28
34
|
reset_current_attributes
|
|
@@ -49,10 +55,26 @@ module Mbuzz
|
|
|
49
55
|
|
|
50
56
|
# Build all request-specific context as a frozen hash
|
|
51
57
|
# This ensures thread-safety by using local variables only
|
|
58
|
+
# IMPORTANT: All values needed by async session creation must be captured here,
|
|
59
|
+
# NOT accessed from the request object in the background thread (see #create_session)
|
|
52
60
|
def build_request_context(request)
|
|
61
|
+
existing_session_id = session_id_from_cookie(request)
|
|
62
|
+
new_session = existing_session_id.nil?
|
|
63
|
+
ip = extract_ip(request)
|
|
64
|
+
user_agent = request.user_agent.to_s
|
|
65
|
+
|
|
53
66
|
{
|
|
54
67
|
visitor_id: resolve_visitor_id(request),
|
|
55
|
-
|
|
68
|
+
session_id: existing_session_id || generate_session_id,
|
|
69
|
+
user_id: user_id_from_session(request),
|
|
70
|
+
new_session: new_session,
|
|
71
|
+
# Session creation data - captured here for thread-safety
|
|
72
|
+
# Background thread must NOT read from request object
|
|
73
|
+
url: request.url,
|
|
74
|
+
referrer: request.referer,
|
|
75
|
+
ip: ip,
|
|
76
|
+
user_agent: user_agent,
|
|
77
|
+
device_fingerprint: Digest::SHA256.hexdigest("#{ip}|#{user_agent}")[0, 32]
|
|
56
78
|
}.freeze
|
|
57
79
|
end
|
|
58
80
|
|
|
@@ -64,11 +86,47 @@ module Mbuzz
|
|
|
64
86
|
request.cookies[VISITOR_COOKIE_NAME]
|
|
65
87
|
end
|
|
66
88
|
|
|
89
|
+
def session_id_from_cookie(request)
|
|
90
|
+
request.cookies[SESSION_COOKIE_NAME]
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def generate_session_id
|
|
94
|
+
SecureRandom.uuid
|
|
95
|
+
end
|
|
96
|
+
|
|
67
97
|
def user_id_from_session(request)
|
|
68
98
|
request.session[SESSION_USER_ID_KEY] if request.session
|
|
69
99
|
end
|
|
70
100
|
|
|
71
|
-
#
|
|
101
|
+
# Session creation - async to not block request
|
|
102
|
+
# IMPORTANT: This runs in a background thread. All data must come from
|
|
103
|
+
# the context hash, NOT from the request object (which may be invalid)
|
|
104
|
+
|
|
105
|
+
def create_session_async(context, _request)
|
|
106
|
+
Thread.new do
|
|
107
|
+
create_session(context)
|
|
108
|
+
rescue StandardError => e
|
|
109
|
+
log_error("Session creation failed: #{e.message}") if Mbuzz.config.debug
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def create_session(context)
|
|
114
|
+
Client.session(
|
|
115
|
+
visitor_id: context[:visitor_id],
|
|
116
|
+
session_id: context[:session_id],
|
|
117
|
+
url: context[:url],
|
|
118
|
+
referrer: context[:referrer],
|
|
119
|
+
device_fingerprint: context[:device_fingerprint]
|
|
120
|
+
)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def log_error(message)
|
|
124
|
+
return unless defined?(Rails) && Rails.logger
|
|
125
|
+
|
|
126
|
+
Rails.logger.error("[Mbuzz] #{message}")
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# Cookie setting - visitor and session cookies
|
|
72
130
|
|
|
73
131
|
def set_visitor_cookie(headers, context, request)
|
|
74
132
|
Rack::Utils.set_cookie_header!(
|
|
@@ -78,6 +136,14 @@ module Mbuzz
|
|
|
78
136
|
)
|
|
79
137
|
end
|
|
80
138
|
|
|
139
|
+
def set_session_cookie(headers, context, request)
|
|
140
|
+
Rack::Utils.set_cookie_header!(
|
|
141
|
+
headers,
|
|
142
|
+
SESSION_COOKIE_NAME,
|
|
143
|
+
session_cookie_options(context, request)
|
|
144
|
+
)
|
|
145
|
+
end
|
|
146
|
+
|
|
81
147
|
def visitor_cookie_options(context, request)
|
|
82
148
|
base_cookie_options(request).merge(
|
|
83
149
|
value: context[:visitor_id],
|
|
@@ -85,6 +151,13 @@ module Mbuzz
|
|
|
85
151
|
)
|
|
86
152
|
end
|
|
87
153
|
|
|
154
|
+
def session_cookie_options(context, request)
|
|
155
|
+
base_cookie_options(request).merge(
|
|
156
|
+
value: context[:session_id],
|
|
157
|
+
max_age: SESSION_COOKIE_MAX_AGE
|
|
158
|
+
)
|
|
159
|
+
end
|
|
160
|
+
|
|
88
161
|
def base_cookie_options(request)
|
|
89
162
|
options = {
|
|
90
163
|
path: VISITOR_COOKIE_PATH,
|
|
@@ -100,6 +173,7 @@ module Mbuzz
|
|
|
100
173
|
return unless defined?(Mbuzz::Current)
|
|
101
174
|
|
|
102
175
|
Mbuzz::Current.visitor_id = context[:visitor_id]
|
|
176
|
+
Mbuzz::Current.session_id = context[:session_id]
|
|
103
177
|
Mbuzz::Current.user_id = context[:user_id]
|
|
104
178
|
Mbuzz::Current.ip = extract_ip(request)
|
|
105
179
|
Mbuzz::Current.user_agent = request.user_agent
|
data/lib/mbuzz/version.rb
CHANGED
data/lib/mbuzz.rb
CHANGED
|
@@ -20,15 +20,20 @@ module Mbuzz
|
|
|
20
20
|
EVENTS_PATH = "/events"
|
|
21
21
|
IDENTIFY_PATH = "/identify"
|
|
22
22
|
CONVERSIONS_PATH = "/conversions"
|
|
23
|
+
SESSIONS_PATH = "/sessions"
|
|
23
24
|
|
|
24
25
|
VISITOR_COOKIE_NAME = "_mbuzz_vid"
|
|
25
26
|
VISITOR_COOKIE_MAX_AGE = 60 * 60 * 24 * 365 * 2 # 2 years
|
|
26
27
|
VISITOR_COOKIE_PATH = "/"
|
|
27
28
|
VISITOR_COOKIE_SAME_SITE = "Lax"
|
|
28
29
|
|
|
30
|
+
SESSION_COOKIE_NAME = "_mbuzz_sid"
|
|
31
|
+
SESSION_COOKIE_MAX_AGE = 30 * 60 # 30 minutes
|
|
32
|
+
|
|
29
33
|
SESSION_USER_ID_KEY = "user_id"
|
|
30
34
|
ENV_USER_ID_KEY = "mbuzz.user_id"
|
|
31
35
|
ENV_VISITOR_ID_KEY = "mbuzz.visitor_id"
|
|
36
|
+
ENV_SESSION_ID_KEY = "mbuzz.session_id"
|
|
32
37
|
|
|
33
38
|
# ============================================================================
|
|
34
39
|
# Configuration
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: mbuzz
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.7.
|
|
4
|
+
version: 0.7.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- mbuzz team
|
|
@@ -44,6 +44,7 @@ files:
|
|
|
44
44
|
- lib/mbuzz/client.rb
|
|
45
45
|
- lib/mbuzz/client/conversion_request.rb
|
|
46
46
|
- lib/mbuzz/client/identify_request.rb
|
|
47
|
+
- lib/mbuzz/client/session_request.rb
|
|
47
48
|
- lib/mbuzz/client/track_request.rb
|
|
48
49
|
- lib/mbuzz/configuration.rb
|
|
49
50
|
- lib/mbuzz/controller_helpers.rb
|