mbuzz 0.6.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.
@@ -0,0 +1,265 @@
1
+ # mbuzz-ruby v2.0.0 Upgrade: Sessions Endpoint
2
+
3
+ **Created**: 2025-11-28
4
+ **Status**: Required for full SDK compliance
5
+
6
+ ---
7
+
8
+ ## Summary
9
+
10
+ The Multibuzz backend now has a dedicated `POST /api/v1/sessions` endpoint for creating sessions with full acquisition context (UTM parameters, referrer, channel). The SDK must be updated to call this endpoint on new session creation.
11
+
12
+ ---
13
+
14
+ ## Current State
15
+
16
+ The current SDK (v0.x/v1.x):
17
+ - Generates visitor_id and session_id cookies
18
+ - Does NOT explicitly create sessions on the backend
19
+ - Sessions are created implicitly when events are tracked
20
+
21
+ ## Required Changes
22
+
23
+ ### 1. Add Session Creation on New Session
24
+
25
+ When the middleware detects a new session (no session cookie or expired), it must:
26
+
27
+ 1. Generate new session_id
28
+ 2. POST to `/api/v1/sessions` with full context
29
+ 3. Store session_id in cookie
30
+
31
+ **New Endpoint:**
32
+
33
+ ```
34
+ POST /api/v1/sessions
35
+
36
+ {
37
+ "session": {
38
+ "visitor_id": "64-char-hex-string",
39
+ "session_id": "64-char-hex-string",
40
+ "url": "https://example.com/landing?utm_source=google&utm_medium=cpc",
41
+ "referrer": "https://www.google.com/search",
42
+ "started_at": "2025-11-28T10:30:00Z"
43
+ }
44
+ }
45
+ ```
46
+
47
+ **Response (202 Accepted):**
48
+
49
+ ```json
50
+ {
51
+ "status": "accepted",
52
+ "visitor_id": "abc123...",
53
+ "session_id": "xyz789...",
54
+ "channel": "paid_search"
55
+ }
56
+ ```
57
+
58
+ ### 2. New Files Required
59
+
60
+ ```
61
+ lib/mbuzz/client/session_request.rb # New request class
62
+ ```
63
+
64
+ ### 3. Update Middleware
65
+
66
+ Update `lib/mbuzz/middleware/tracking.rb`:
67
+
68
+ ```ruby
69
+ # Add session constant
70
+ SESSION_COOKIE_NAME = "_mbuzz_sid"
71
+ SESSION_COOKIE_MAX_AGE = 30 * 60 # 30 minutes
72
+
73
+ def call(env)
74
+ @request = Rack::Request.new(env)
75
+
76
+ env[ENV_VISITOR_ID_KEY] = visitor_id
77
+ env[ENV_SESSION_ID_KEY] = session_id # NEW
78
+
79
+ RequestContext.with_context(request: request) do
80
+ create_session_if_new # NEW - fire and forget
81
+
82
+ status, headers, body = app.call(env)
83
+ set_visitor_cookie(headers)
84
+ set_session_cookie(headers) # NEW
85
+ [status, headers, body]
86
+ end
87
+ end
88
+
89
+ private
90
+
91
+ def session_id
92
+ @session_id ||= session_id_from_cookie || generate_session_id
93
+ end
94
+
95
+ def session_id_from_cookie
96
+ request.cookies[SESSION_COOKIE_NAME]
97
+ end
98
+
99
+ def generate_session_id
100
+ SecureRandom.hex(32)
101
+ end
102
+
103
+ def new_session?
104
+ session_id_from_cookie.nil?
105
+ end
106
+
107
+ def create_session_if_new
108
+ return unless new_session?
109
+
110
+ # Fire and forget - don't block the request
111
+ Thread.new do
112
+ Client.session(
113
+ visitor_id: visitor_id,
114
+ session_id: session_id,
115
+ url: request.url,
116
+ referrer: request.referer
117
+ )
118
+ rescue => e
119
+ # Log but don't raise - session creation is non-critical
120
+ Mbuzz.config.logger&.error("Session creation failed: #{e.message}")
121
+ end
122
+ end
123
+
124
+ def set_session_cookie(headers)
125
+ cookie_options = {
126
+ value: session_id,
127
+ path: VISITOR_COOKIE_PATH,
128
+ max_age: SESSION_COOKIE_MAX_AGE,
129
+ httponly: true,
130
+ same_site: VISITOR_COOKIE_SAME_SITE
131
+ }
132
+ cookie_options[:secure] = true if request.ssl?
133
+
134
+ Rack::Utils.set_cookie_header!(headers, SESSION_COOKIE_NAME, cookie_options)
135
+ end
136
+ ```
137
+
138
+ ### 4. Add Client Method
139
+
140
+ Update `lib/mbuzz/client.rb`:
141
+
142
+ ```ruby
143
+ def self.session(visitor_id:, session_id:, url:, referrer: nil, started_at: nil)
144
+ SessionRequest.new(visitor_id, session_id, url, referrer, started_at).call
145
+ end
146
+ ```
147
+
148
+ ### 5. Create SessionRequest Class
149
+
150
+ Create `lib/mbuzz/client/session_request.rb`:
151
+
152
+ ```ruby
153
+ # frozen_string_literal: true
154
+
155
+ module Mbuzz
156
+ class Client
157
+ class SessionRequest
158
+ def initialize(visitor_id, session_id, url, referrer, started_at)
159
+ @visitor_id = visitor_id
160
+ @session_id = session_id
161
+ @url = url
162
+ @referrer = referrer
163
+ @started_at = started_at || Time.now.utc.iso8601
164
+ end
165
+
166
+ def call
167
+ return false unless valid?
168
+
169
+ Api.post(SESSIONS_PATH, payload)
170
+ end
171
+
172
+ private
173
+
174
+ attr_reader :visitor_id, :session_id, :url, :referrer, :started_at
175
+
176
+ def valid?
177
+ visitor_id.present? && session_id.present? && url.present?
178
+ end
179
+
180
+ def payload
181
+ {
182
+ session: {
183
+ visitor_id: visitor_id,
184
+ session_id: session_id,
185
+ url: url,
186
+ referrer: referrer,
187
+ started_at: started_at
188
+ }.compact
189
+ }
190
+ end
191
+ end
192
+ end
193
+ end
194
+ ```
195
+
196
+ ### 6. Add Constant
197
+
198
+ Update `lib/mbuzz.rb`:
199
+
200
+ ```ruby
201
+ SESSIONS_PATH = "/sessions"
202
+ SESSION_COOKIE_NAME = "_mbuzz_sid"
203
+ SESSION_COOKIE_MAX_AGE = 30 * 60 # 30 minutes
204
+
205
+ ENV_SESSION_ID_KEY = "mbuzz.session_id"
206
+ ```
207
+
208
+ ### 7. Add Helper Method
209
+
210
+ Update `lib/mbuzz/controller_helpers.rb`:
211
+
212
+ ```ruby
213
+ def mbuzz_session_id
214
+ request.env[Mbuzz::ENV_SESSION_ID_KEY]
215
+ end
216
+ ```
217
+
218
+ ---
219
+
220
+ ## Benefits
221
+
222
+ 1. **Accurate Attribution**: Sessions are created with full acquisition context (UTMs, referrer, channel) at session start, not when first event is tracked
223
+ 2. **Channel Attribution**: Backend determines channel immediately from URL/referrer
224
+ 3. **Consistent Data**: Session data matches the landing page, not a later page view
225
+ 4. **Decoupled from Events**: Sessions exist even if no events are tracked
226
+
227
+ ---
228
+
229
+ ## Migration Path
230
+
231
+ ### Breaking Changes
232
+
233
+ None - this is additive. Existing events endpoint still creates sessions implicitly.
234
+
235
+ ### Recommended Upgrade
236
+
237
+ 1. Add session creation to middleware
238
+ 2. Add session cookie management
239
+ 3. Add `mbuzz_session_id` helper
240
+ 4. Bump version to 2.0.0
241
+
242
+ ---
243
+
244
+ ## Testing
245
+
246
+ Add tests for:
247
+
248
+ 1. Session cookie is created on new visit
249
+ 2. Session cookie is reused within 30 minutes
250
+ 3. New session is created after 30 minute gap
251
+ 4. `POST /api/v1/sessions` is called on new session
252
+ 5. Session creation failures don't break the request
253
+ 6. `mbuzz_session_id` helper returns correct value
254
+
255
+ ---
256
+
257
+ ## API Contract
258
+
259
+ See: `multibuzz/lib/docs/sdk/api_contract.md` for full endpoint documentation.
260
+
261
+ Key points:
262
+ - Sessions endpoint requires: `visitor_id`, `session_id`, `url`
263
+ - Optional: `referrer`, `started_at`
264
+ - Returns: `status`, `visitor_id`, `session_id`, `channel`
265
+ - Backend extracts UTMs from URL, determines channel from UTM/referrer