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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +92 -0
- data/LICENSE.txt +21 -0
- data/README.md +173 -0
- data/Rakefile +8 -0
- data/lib/mbuzz/api.rb +102 -0
- data/lib/mbuzz/client/conversion_request.rb +85 -0
- data/lib/mbuzz/client/identify_request.rb +37 -0
- data/lib/mbuzz/client/session_request.rb +43 -0
- data/lib/mbuzz/client/track_request.rb +50 -0
- data/lib/mbuzz/client.rb +36 -0
- data/lib/mbuzz/configuration.rb +51 -0
- data/lib/mbuzz/controller_helpers.rb +34 -0
- data/lib/mbuzz/middleware/tracking.rb +157 -0
- data/lib/mbuzz/railtie.rb +13 -0
- data/lib/mbuzz/request_context.rb +40 -0
- data/lib/mbuzz/version.rb +5 -0
- data/lib/mbuzz/visitor/identifier.rb +13 -0
- data/lib/mbuzz.rb +178 -0
- data/lib/specs/old/SPECIFICATION.md +695 -0
- data/lib/specs/old/conversions.md +585 -0
- data/lib/specs/old/event_ids_response.md +346 -0
- data/lib/specs/old/v0.2.0_breaking_changes.md +519 -0
- data/lib/specs/old/v2.0.0_sessions_upgrade.md +265 -0
- data/lib/specs/v0.5.0_four_call_model.md +505 -0
- data/mbuzz-0.6.0.gem +0 -0
- data/sig/mbuzz.rbs +4 -0
- metadata +89 -0
|
@@ -0,0 +1,505 @@
|
|
|
1
|
+
# mbuzz Ruby Gem v0.5.0 - Four-Call Model
|
|
2
|
+
|
|
3
|
+
**Status**: Complete
|
|
4
|
+
**Last Updated**: 2025-11-29
|
|
5
|
+
**Breaking Change**: Yes (from 0.4.0)
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
Simplify the SDK to a 4-method model:
|
|
12
|
+
|
|
13
|
+
| Method | Purpose |
|
|
14
|
+
|--------|---------|
|
|
15
|
+
| `Mbuzz.init` | Configure SDK |
|
|
16
|
+
| `Mbuzz.event` | Track journey steps |
|
|
17
|
+
| `Mbuzz.conversion` | Track revenue outcomes |
|
|
18
|
+
| `Mbuzz.identify` | Link visitor to user + store traits |
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Changes from v0.4.0
|
|
23
|
+
|
|
24
|
+
| Change | Before (v0.4.0) | After (v0.5.0) |
|
|
25
|
+
|--------|-----------------|----------------|
|
|
26
|
+
| Configuration | `Mbuzz.configure { \|c\| ... }` | `Mbuzz.init(api_key: ...)` |
|
|
27
|
+
| Track events | `Mbuzz.track(event_type:, ...)` | `Mbuzz.event("event_type", ...)` |
|
|
28
|
+
| Link visitor | `Mbuzz.alias(user_id:, visitor_id:)` | Merged into `identify` |
|
|
29
|
+
| Identify | `Mbuzz.identify(user_id:, traits:)` | `Mbuzz.identify(user_id, traits:, visitor_id:)` |
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## New Public API
|
|
34
|
+
|
|
35
|
+
### `Mbuzz.init`
|
|
36
|
+
|
|
37
|
+
```ruby
|
|
38
|
+
Mbuzz.init(
|
|
39
|
+
api_key: "sk_live_...", # Required
|
|
40
|
+
api_url: "https://mbuzz.co/api/v1", # Optional - API endpoint
|
|
41
|
+
debug: false # Optional - enable debug logging
|
|
42
|
+
)
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**Note**: Session timeout is fixed at 30 minutes (cookie expiry). HTTP timeout defaults to 5 seconds.
|
|
46
|
+
|
|
47
|
+
### `Mbuzz.event`
|
|
48
|
+
|
|
49
|
+
```ruby
|
|
50
|
+
Mbuzz.event("add_to_cart",
|
|
51
|
+
product_id: "SKU-123",
|
|
52
|
+
price: 49.99
|
|
53
|
+
)
|
|
54
|
+
# Returns: { success: true, event_id: "evt_abc123" } or false
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### `Mbuzz.conversion`
|
|
58
|
+
|
|
59
|
+
```ruby
|
|
60
|
+
Mbuzz.conversion("purchase",
|
|
61
|
+
revenue: 99.99,
|
|
62
|
+
order_id: "ORD-123"
|
|
63
|
+
)
|
|
64
|
+
# Returns: { success: true, conversion_id: "conv_abc123" } or false
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### `Mbuzz.identify`
|
|
68
|
+
|
|
69
|
+
```ruby
|
|
70
|
+
# Links visitor (from cookie) to user + stores traits
|
|
71
|
+
Mbuzz.identify("user_123",
|
|
72
|
+
traits: { email: "jane@example.com", name: "Jane" }
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
# Or with explicit visitor_id
|
|
76
|
+
Mbuzz.identify("user_123",
|
|
77
|
+
visitor_id: "abc123...",
|
|
78
|
+
traits: { email: "jane@example.com" }
|
|
79
|
+
)
|
|
80
|
+
# Returns: true on success, false on failure
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
**Backend Response**: The API returns `{ success: true, identity_id: "idt_...", visitor_linked: true/false }` but the SDK simplifies this to a boolean for ease of use.
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## Removed
|
|
88
|
+
|
|
89
|
+
- `Mbuzz.configure` → use `Mbuzz.init`
|
|
90
|
+
- `Mbuzz.track` → use `Mbuzz.event`
|
|
91
|
+
- `Mbuzz.alias` → use `Mbuzz.identify` with `visitor_id:`
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## Files to Change
|
|
96
|
+
|
|
97
|
+
| File | Action |
|
|
98
|
+
|------|--------|
|
|
99
|
+
| `lib/mbuzz/version.rb` | Bump to 0.5.0 |
|
|
100
|
+
| `lib/mbuzz.rb` | New API methods |
|
|
101
|
+
| `lib/mbuzz/client.rb` | Update signatures |
|
|
102
|
+
| `lib/mbuzz/client/identify_request.rb` | Accept visitor_id |
|
|
103
|
+
| `lib/mbuzz/client/alias_request.rb` | DELETE |
|
|
104
|
+
| `README.md` | Complete rewrite |
|
|
105
|
+
| `CHANGELOG.md` | Add 0.5.0 entry |
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## README Content
|
|
110
|
+
|
|
111
|
+
```markdown
|
|
112
|
+
# mbuzz
|
|
113
|
+
|
|
114
|
+
Server-side multi-touch attribution for Ruby. Track customer journeys, attribute conversions, know which channels drive revenue.
|
|
115
|
+
|
|
116
|
+
## Installation
|
|
117
|
+
|
|
118
|
+
Add to your Gemfile:
|
|
119
|
+
|
|
120
|
+
```ruby
|
|
121
|
+
gem 'mbuzz'
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Then:
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
bundle install
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## Quick Start
|
|
131
|
+
|
|
132
|
+
### 1. Initialize
|
|
133
|
+
|
|
134
|
+
```ruby
|
|
135
|
+
# config/initializers/mbuzz.rb
|
|
136
|
+
Mbuzz.init(api_key: ENV['MBUZZ_API_KEY'])
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### 2. Track Events
|
|
140
|
+
|
|
141
|
+
Track steps in the customer journey:
|
|
142
|
+
|
|
143
|
+
```ruby
|
|
144
|
+
Mbuzz.event("page_view", url: request.url)
|
|
145
|
+
Mbuzz.event("add_to_cart", product_id: "SKU-123", price: 49.99)
|
|
146
|
+
Mbuzz.event("checkout_started", cart_total: 99.99)
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### 3. Track Conversions
|
|
150
|
+
|
|
151
|
+
Record revenue-generating outcomes:
|
|
152
|
+
|
|
153
|
+
```ruby
|
|
154
|
+
Mbuzz.conversion("purchase",
|
|
155
|
+
revenue: 99.99,
|
|
156
|
+
order_id: order.id
|
|
157
|
+
)
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### 4. Identify Users
|
|
161
|
+
|
|
162
|
+
Link visitors to known users (enables cross-device attribution):
|
|
163
|
+
|
|
164
|
+
```ruby
|
|
165
|
+
# On signup or login
|
|
166
|
+
Mbuzz.identify(current_user.id,
|
|
167
|
+
traits: {
|
|
168
|
+
email: current_user.email,
|
|
169
|
+
name: current_user.name
|
|
170
|
+
}
|
|
171
|
+
)
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## Rails Integration
|
|
175
|
+
|
|
176
|
+
mbuzz provides:
|
|
177
|
+
- Middleware for visitor and session cookie management
|
|
178
|
+
- `mbuzz_visitor_id` helper in controllers
|
|
179
|
+
|
|
180
|
+
## Configuration Options
|
|
181
|
+
|
|
182
|
+
```ruby
|
|
183
|
+
Mbuzz.init(
|
|
184
|
+
api_key: "sk_live_...", # Required - from mbuzz.co dashboard
|
|
185
|
+
api_url: "https://mbuzz.co/api/v1", # Optional - API endpoint
|
|
186
|
+
debug: false # Optional - enable debug logging
|
|
187
|
+
)
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
## The 4-Call Model
|
|
191
|
+
|
|
192
|
+
| Method | When to Use |
|
|
193
|
+
|--------|-------------|
|
|
194
|
+
| `init` | Once on app boot |
|
|
195
|
+
| `event` | User interactions, funnel steps |
|
|
196
|
+
| `conversion` | Purchases, signups, any revenue event |
|
|
197
|
+
| `identify` | Login, signup, when you know the user |
|
|
198
|
+
|
|
199
|
+
## Error Handling
|
|
200
|
+
|
|
201
|
+
mbuzz never raises exceptions. All methods return `false` on failure and log errors in debug mode.
|
|
202
|
+
|
|
203
|
+
## Requirements
|
|
204
|
+
|
|
205
|
+
- Ruby 2.7+
|
|
206
|
+
- Rails 6.0+ (for automatic integration) or any Rack app
|
|
207
|
+
|
|
208
|
+
## Links
|
|
209
|
+
|
|
210
|
+
- [Documentation](https://mbuzz.co/docs)
|
|
211
|
+
- [Dashboard](https://mbuzz.co/dashboard)
|
|
212
|
+
|
|
213
|
+
## License
|
|
214
|
+
|
|
215
|
+
MIT License
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
## CHANGELOG Entry
|
|
221
|
+
|
|
222
|
+
```markdown
|
|
223
|
+
## [0.5.0] - 2025-XX-XX
|
|
224
|
+
|
|
225
|
+
### Breaking Changes
|
|
226
|
+
|
|
227
|
+
- `Mbuzz.configure` replaced with `Mbuzz.init`
|
|
228
|
+
- `Mbuzz.track` renamed to `Mbuzz.event`
|
|
229
|
+
- `Mbuzz.alias` removed - merged into `Mbuzz.identify`
|
|
230
|
+
- `Mbuzz.identify` signature changed: positional user_id, keyword traits/visitor_id
|
|
231
|
+
|
|
232
|
+
### Added
|
|
233
|
+
|
|
234
|
+
- `Mbuzz.init(api_key:, ...)` - new configuration method
|
|
235
|
+
- `Mbuzz.event(event_type, **properties)` - cleaner event tracking
|
|
236
|
+
- Automatic visitor linking in `identify` when visitor_id available
|
|
237
|
+
|
|
238
|
+
### Removed
|
|
239
|
+
|
|
240
|
+
- `Mbuzz.configure` block syntax
|
|
241
|
+
- `Mbuzz.track` method
|
|
242
|
+
- `Mbuzz.alias` method
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
---
|
|
246
|
+
|
|
247
|
+
## Backend Requirements ✅ COMPLETE
|
|
248
|
+
|
|
249
|
+
Backend `POST /api/v1/identify` must:
|
|
250
|
+
1. ✅ Accept optional `visitor_id` in payload
|
|
251
|
+
2. ✅ Link visitor to identity if visitor_id present
|
|
252
|
+
3. ✅ Store/update traits
|
|
253
|
+
4. ✅ Check for retroactive attribution (triggers `ReattributionJob`)
|
|
254
|
+
5. ✅ Return `{ success: true, identity_id: "...", visitor_linked: true/false }`
|
|
255
|
+
|
|
256
|
+
Backend `POST /api/v1/alias` ✅ REMOVED (commit 5c4b555)
|
|
257
|
+
|
|
258
|
+
---
|
|
259
|
+
|
|
260
|
+
## Session & Cookie Management
|
|
261
|
+
|
|
262
|
+
### Cookie Specifications
|
|
263
|
+
|
|
264
|
+
| Cookie | Name | Format | Max-Age | Purpose |
|
|
265
|
+
|--------|------|--------|---------|---------|
|
|
266
|
+
| Visitor | `_mbuzz_vid` | 64 hex chars | 2 years | Persistent visitor ID |
|
|
267
|
+
| Session | `_mbuzz_sid` | 64 hex chars | 30 min | Session tracking |
|
|
268
|
+
|
|
269
|
+
### Middleware Implementation
|
|
270
|
+
|
|
271
|
+
```ruby
|
|
272
|
+
# lib/mbuzz/middleware/tracking.rb
|
|
273
|
+
module Mbuzz
|
|
274
|
+
module Middleware
|
|
275
|
+
class Tracking
|
|
276
|
+
SESSION_TIMEOUT = 1800 # 30 minutes
|
|
277
|
+
VISITOR_COOKIE = "_mbuzz_vid"
|
|
278
|
+
SESSION_COOKIE = "_mbuzz_sid"
|
|
279
|
+
|
|
280
|
+
def initialize(app)
|
|
281
|
+
@app = app
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
def call(env)
|
|
285
|
+
@request = Rack::Request.new(env)
|
|
286
|
+
|
|
287
|
+
env[Mbuzz::ENV_VISITOR_ID_KEY] = visitor_id
|
|
288
|
+
env[Mbuzz::ENV_SESSION_ID_KEY] = session_id
|
|
289
|
+
|
|
290
|
+
Mbuzz::RequestContext.with_context(request: @request) do
|
|
291
|
+
status, headers, body = @app.call(env)
|
|
292
|
+
set_cookies(headers)
|
|
293
|
+
[status, headers, body]
|
|
294
|
+
end
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
private
|
|
298
|
+
|
|
299
|
+
def visitor_id
|
|
300
|
+
@visitor_id ||= @request.cookies[VISITOR_COOKIE] || SecureRandom.hex(32)
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
def session_id
|
|
304
|
+
@session_id ||= @request.cookies[SESSION_COOKIE] || SecureRandom.hex(32)
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
def set_cookies(headers)
|
|
308
|
+
Rack::Utils.set_cookie_header!(headers, VISITOR_COOKIE, visitor_cookie_options)
|
|
309
|
+
Rack::Utils.set_cookie_header!(headers, SESSION_COOKIE, session_cookie_options)
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
def visitor_cookie_options
|
|
313
|
+
{ value: visitor_id, path: "/", max_age: 63072000, httponly: true, same_site: :lax, secure: @request.ssl? }
|
|
314
|
+
end
|
|
315
|
+
|
|
316
|
+
def session_cookie_options
|
|
317
|
+
{ value: session_id, path: "/", max_age: SESSION_TIMEOUT, httponly: true, same_site: :lax, secure: @request.ssl? }
|
|
318
|
+
end
|
|
319
|
+
end
|
|
320
|
+
end
|
|
321
|
+
end
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
### Request Context (URL/Referrer Enrichment)
|
|
325
|
+
|
|
326
|
+
```ruby
|
|
327
|
+
# lib/mbuzz/request_context.rb
|
|
328
|
+
module Mbuzz
|
|
329
|
+
class RequestContext
|
|
330
|
+
def self.with_context(request:)
|
|
331
|
+
Thread.current[:mbuzz_context] = new(request)
|
|
332
|
+
yield
|
|
333
|
+
ensure
|
|
334
|
+
Thread.current[:mbuzz_context] = nil
|
|
335
|
+
end
|
|
336
|
+
|
|
337
|
+
def self.current
|
|
338
|
+
Thread.current[:mbuzz_context]
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
attr_reader :request
|
|
342
|
+
|
|
343
|
+
def initialize(request)
|
|
344
|
+
@request = request
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
def url
|
|
348
|
+
request.url
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
def referrer
|
|
352
|
+
request.referrer
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
def visitor_id
|
|
356
|
+
request.env[Mbuzz::ENV_VISITOR_ID_KEY]
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
def session_id
|
|
360
|
+
request.env[Mbuzz::ENV_SESSION_ID_KEY]
|
|
361
|
+
end
|
|
362
|
+
|
|
363
|
+
def enriched_properties(custom = {})
|
|
364
|
+
{ url: url, referrer: referrer }.compact.merge(custom)
|
|
365
|
+
end
|
|
366
|
+
end
|
|
367
|
+
end
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
---
|
|
371
|
+
|
|
372
|
+
## Implementation Checklist
|
|
373
|
+
|
|
374
|
+
### Phase 1: API Rename
|
|
375
|
+
- [x] Add `Mbuzz.init` (wrapper for configure)
|
|
376
|
+
- [x] Add `Mbuzz.event` (wrapper for track)
|
|
377
|
+
- [x] Deprecate `Mbuzz.configure` with warning
|
|
378
|
+
- [x] Deprecate `Mbuzz.track` with warning
|
|
379
|
+
- [x] Remove `Mbuzz.alias` method
|
|
380
|
+
- [x] Update `Mbuzz.identify` to accept visitor_id
|
|
381
|
+
|
|
382
|
+
### Phase 2: Internals
|
|
383
|
+
- [x] Update `lib/mbuzz/client/identify_request.rb` for visitor_id
|
|
384
|
+
- [x] Delete `lib/mbuzz/client/alias_request.rb`
|
|
385
|
+
- [x] Update middleware for session cookies (if not already)
|
|
386
|
+
- [x] Add RequestContext for URL/referrer enrichment
|
|
387
|
+
|
|
388
|
+
### Phase 3: Documentation
|
|
389
|
+
- [x] Rewrite README.md
|
|
390
|
+
- [x] Update CHANGELOG.md
|
|
391
|
+
- [x] Update gemspec description
|
|
392
|
+
|
|
393
|
+
### Phase 4: Testing
|
|
394
|
+
- [x] Unit tests for new API methods
|
|
395
|
+
- [ ] Integration test with backend
|
|
396
|
+
- [x] Verify cookies set correctly
|
|
397
|
+
|
|
398
|
+
---
|
|
399
|
+
|
|
400
|
+
## Migration Guide
|
|
401
|
+
|
|
402
|
+
### Existing Integrations
|
|
403
|
+
|
|
404
|
+
**No code changes required for basic usage!** The SDK auto-enriches events with URL and referrer.
|
|
405
|
+
|
|
406
|
+
#### Configuration Change
|
|
407
|
+
|
|
408
|
+
```ruby
|
|
409
|
+
# Before (v0.4.0)
|
|
410
|
+
Mbuzz.configure do |config|
|
|
411
|
+
config.api_key = ENV['MBUZZ_API_KEY']
|
|
412
|
+
end
|
|
413
|
+
|
|
414
|
+
# After (v0.5.0)
|
|
415
|
+
Mbuzz.init(api_key: ENV['MBUZZ_API_KEY'])
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
#### Event Tracking Change
|
|
419
|
+
|
|
420
|
+
```ruby
|
|
421
|
+
# Before (v0.4.0)
|
|
422
|
+
Mbuzz.track("add_to_cart", properties: { product_id: "123" })
|
|
423
|
+
|
|
424
|
+
# After (v0.5.0)
|
|
425
|
+
Mbuzz.event("add_to_cart", product_id: "123")
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
#### Alias → Identify
|
|
429
|
+
|
|
430
|
+
```ruby
|
|
431
|
+
# Before (v0.4.0)
|
|
432
|
+
Mbuzz.alias(user_id: "user_123", visitor_id: visitor_id)
|
|
433
|
+
|
|
434
|
+
# After (v0.5.0)
|
|
435
|
+
Mbuzz.identify("user_123") # visitor_id auto-captured from cookie
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
---
|
|
439
|
+
|
|
440
|
+
## Testing Plan
|
|
441
|
+
|
|
442
|
+
### Unit Tests
|
|
443
|
+
|
|
444
|
+
```ruby
|
|
445
|
+
# test/mbuzz_test.rb
|
|
446
|
+
class MbuzzTest < Minitest::Test
|
|
447
|
+
def test_init_stores_api_key
|
|
448
|
+
Mbuzz.init(api_key: "sk_test_123")
|
|
449
|
+
assert_equal "sk_test_123", Mbuzz.config.api_key
|
|
450
|
+
end
|
|
451
|
+
|
|
452
|
+
def test_event_sends_to_api
|
|
453
|
+
stub_request(:post, "https://mbuzz.co/api/v1/events")
|
|
454
|
+
.to_return(status: 202, body: '{"accepted":1}')
|
|
455
|
+
|
|
456
|
+
result = Mbuzz.event("page_view", url: "https://example.com")
|
|
457
|
+
assert result
|
|
458
|
+
end
|
|
459
|
+
|
|
460
|
+
def test_identify_includes_visitor_id
|
|
461
|
+
stub_request(:post, "https://mbuzz.co/api/v1/identify")
|
|
462
|
+
.with(body: hash_including(visitor_id: "abc123"))
|
|
463
|
+
.to_return(status: 200, body: '{"success":true}')
|
|
464
|
+
|
|
465
|
+
with_visitor_id("abc123") do
|
|
466
|
+
Mbuzz.identify("user_123", traits: { email: "test@example.com" })
|
|
467
|
+
end
|
|
468
|
+
end
|
|
469
|
+
end
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
### Integration Test
|
|
473
|
+
|
|
474
|
+
```ruby
|
|
475
|
+
# test/integration/tracking_test.rb
|
|
476
|
+
class TrackingIntegrationTest < ActionDispatch::IntegrationTest
|
|
477
|
+
def test_full_journey
|
|
478
|
+
# 1. Visit with UTMs
|
|
479
|
+
get "/?utm_source=google&utm_campaign=q4"
|
|
480
|
+
assert cookies["_mbuzz_vid"].present?
|
|
481
|
+
assert cookies["_mbuzz_sid"].present?
|
|
482
|
+
|
|
483
|
+
# 2. Track event
|
|
484
|
+
Mbuzz.event("page_view")
|
|
485
|
+
|
|
486
|
+
# 3. Convert
|
|
487
|
+
Mbuzz.conversion("signup", revenue: 0)
|
|
488
|
+
|
|
489
|
+
# 4. Identify
|
|
490
|
+
result = Mbuzz.identify("user_123")
|
|
491
|
+
assert result[:visitor_linked]
|
|
492
|
+
end
|
|
493
|
+
end
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
---
|
|
497
|
+
|
|
498
|
+
## Success Metrics
|
|
499
|
+
|
|
500
|
+
After deployment, verify:
|
|
501
|
+
|
|
502
|
+
1. **Visitor creation**: `Visitor.where(created_at: 1.day.ago..).count` should match unique visitors
|
|
503
|
+
2. **Session tracking**: Sessions with UTMs should have `initial_utm` populated
|
|
504
|
+
3. **Event enrichment**: Events should have `url` in properties
|
|
505
|
+
4. **Attribution accuracy**: Conversions attributed to original acquisition channel
|
data/mbuzz-0.6.0.gem
ADDED
|
Binary file
|
data/sig/mbuzz.rbs
ADDED
metadata
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: mbuzz
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.6.2
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- mbuzz team
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: exe
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2025-12-12 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: rack
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ">="
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '2.0'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - ">="
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '2.0'
|
|
27
|
+
description: 'Track customer journeys, attribute conversions, know which channels
|
|
28
|
+
drive revenue. Simple 4-call API: init, event, conversion, identify. Works with
|
|
29
|
+
Rails, Sinatra, and any Rack application.'
|
|
30
|
+
email:
|
|
31
|
+
- support@mbuzz.co
|
|
32
|
+
executables: []
|
|
33
|
+
extensions: []
|
|
34
|
+
extra_rdoc_files: []
|
|
35
|
+
files:
|
|
36
|
+
- CHANGELOG.md
|
|
37
|
+
- LICENSE.txt
|
|
38
|
+
- README.md
|
|
39
|
+
- Rakefile
|
|
40
|
+
- lib/mbuzz.rb
|
|
41
|
+
- lib/mbuzz/api.rb
|
|
42
|
+
- lib/mbuzz/client.rb
|
|
43
|
+
- lib/mbuzz/client/conversion_request.rb
|
|
44
|
+
- lib/mbuzz/client/identify_request.rb
|
|
45
|
+
- lib/mbuzz/client/session_request.rb
|
|
46
|
+
- lib/mbuzz/client/track_request.rb
|
|
47
|
+
- lib/mbuzz/configuration.rb
|
|
48
|
+
- lib/mbuzz/controller_helpers.rb
|
|
49
|
+
- lib/mbuzz/middleware/tracking.rb
|
|
50
|
+
- lib/mbuzz/railtie.rb
|
|
51
|
+
- lib/mbuzz/request_context.rb
|
|
52
|
+
- lib/mbuzz/version.rb
|
|
53
|
+
- lib/mbuzz/visitor/identifier.rb
|
|
54
|
+
- lib/specs/old/SPECIFICATION.md
|
|
55
|
+
- lib/specs/old/conversions.md
|
|
56
|
+
- lib/specs/old/event_ids_response.md
|
|
57
|
+
- lib/specs/old/v0.2.0_breaking_changes.md
|
|
58
|
+
- lib/specs/old/v2.0.0_sessions_upgrade.md
|
|
59
|
+
- lib/specs/v0.5.0_four_call_model.md
|
|
60
|
+
- mbuzz-0.6.0.gem
|
|
61
|
+
- sig/mbuzz.rbs
|
|
62
|
+
homepage: https://mbuzz.co
|
|
63
|
+
licenses:
|
|
64
|
+
- MIT
|
|
65
|
+
metadata:
|
|
66
|
+
homepage_uri: https://mbuzz.co
|
|
67
|
+
source_code_uri: https://github.com/mbuzz/mbuzz-ruby
|
|
68
|
+
changelog_uri: https://github.com/mbuzz/mbuzz-ruby/blob/main/CHANGELOG.md
|
|
69
|
+
documentation_uri: https://mbuzz.co/docs
|
|
70
|
+
post_install_message:
|
|
71
|
+
rdoc_options: []
|
|
72
|
+
require_paths:
|
|
73
|
+
- lib
|
|
74
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
75
|
+
requirements:
|
|
76
|
+
- - ">="
|
|
77
|
+
- !ruby/object:Gem::Version
|
|
78
|
+
version: 3.0.0
|
|
79
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
80
|
+
requirements:
|
|
81
|
+
- - ">="
|
|
82
|
+
- !ruby/object:Gem::Version
|
|
83
|
+
version: '0'
|
|
84
|
+
requirements: []
|
|
85
|
+
rubygems_version: 3.5.16
|
|
86
|
+
signing_key:
|
|
87
|
+
specification_version: 4
|
|
88
|
+
summary: Server-side multi-touch attribution for Ruby
|
|
89
|
+
test_files: []
|