mbuzz 0.10.0 → 0.11.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 03aa54a68ab1b6e6313d69c910c88aec7241e19d65b72b9cee37a6e187454692
4
- data.tar.gz: 3ddce95a2f8795635278785f403daf6a41e15bc31fc01c3990989c20911ebc21
3
+ metadata.gz: ff302e119aa981ced654677a020929b3b2065055961e253b08e106b52750fed4
4
+ data.tar.gz: ed21ef016dcbac2bb9918a07f03efcce264b9f01046a1ada510e526a107c7ed1
5
5
  SHA512:
6
- metadata.gz: 4ba8606ecbeec460a9145937b8d123c93c455476d92795e9ddf2b291082e57cdce4818cd709a427ed28d125e0ee6766110f0425039c43bfba75328f5da6f756f
7
- data.tar.gz: 8d9233587278aaccb19fd5f124e486e1385b626b2eb4db3d7125ab0e64d6b1500117a33fe89e1fad84c846e6a292e6183760013ecb33e16d44082036d2c5a299
6
+ metadata.gz: 6f9e1ff36c152c2eaa085892b41f7e18e995f7de122413d6d42cc4d44d2199f6e8fa3096ce2e06be4b87a6b2a8daaebcaf80d037e11e85df9298d9b3a33f7e27
7
+ data.tar.gz: 1a18bdf46411b450c247396d595e094404d6b8f7ef487560c8af697c65317f2f6efcf1969a0a86b3a9b349a95f89fd0dce5b546a4d9d5307dd99cf0a3b9d3f85
data/CHANGELOG.md CHANGED
@@ -5,6 +5,43 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.11.0] - 2026-10-14
9
+
10
+ ### Added
11
+
12
+ - **Meta's `_fbp` is forwarded on the session call.** The SDK reads the `_fbp` cookie the customer's
13
+ Meta Pixel already set and sends it as `fbp` on the session payload, on both paths (the session
14
+ endpoint and the tracking middleware). Meta merges a server event with the browser Pixel's event on
15
+ `event_name` + `fbp` when the event IDs differ, so without it every server `Lead` counted as a
16
+ second one. Accepts Meta's `fb.<n>.<ts>.<random>` and the optional appendix its server-side
17
+ Parameter Builder adds (`...AQECAQIB`); anything else is dropped. Never written, never invented.
18
+ The key is omitted, not null, when the cookie is absent or malformed. No install change needed.
19
+
20
+ ### Fixed
21
+
22
+ - **A session call made outside Rack/Rails failed silently.** `SessionRequest` called
23
+ `Time#iso8601` without `require "time"`; Rack and Rails load it, a plain script did not, and the
24
+ `NoMethodError` was rescued to `false`.
25
+
26
+ ## [0.10.1] - 2026-09-17
27
+
28
+ ### Fixed — the visitor's IP now reaches mbuzz on session create
29
+
30
+ - **`POST /api/v1/sessions` now carries `ip`.** The middleware already extracted the visitor's
31
+ address — it is half of `device_fingerprint = SHA256(ip|user_agent)` — and then dropped it at
32
+ three points on the way out: `Client.session` had no `ip:` keyword, `SessionRequest#payload`
33
+ omitted it, and `Middleware::Tracking`'s own call site omitted it too. Events and conversions have
34
+ always sent one; only sessions did not.
35
+ - **Why it matters.** mbuzz sends Meta's Conversions API `client_ip_address`, which Meta documents
36
+ as **required** for website events, and a session with no address means the events resolved
37
+ through it carry none either. Upgrading improves Event Match Quality for anyone using conversion
38
+ feedback; it changes nothing else.
39
+ - **No API change.** `ip:` is an optional keyword on `Client.session` and both middlewares fill it
40
+ automatically. Existing callers need no edit.
41
+
42
+ Found by the SDK integration harness rather than by unit tests: every layer was correct on its own,
43
+ and only a real request through a real app could tell the visitor's address from the app server's.
44
+
8
45
  ## [0.10.0] - 2026-09-08
9
46
 
10
47
  ### BREAKING — the page snippet is now required
@@ -1,5 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # Time#iso8601 lives here, not in core. Rack and Rails load it; a plain script
4
+ # did not, and the session call then failed silently (rescued to false).
5
+ require "time"
6
+
3
7
  module Mbuzz
4
8
  class Client
5
9
  class SessionRequest
@@ -12,7 +16,8 @@ module Mbuzz
12
16
  # Response values
13
17
  ACCEPTED_STATUS = "accepted"
14
18
 
15
- def initialize(visitor_id:, session_id:, url:, referrer: nil, device_fingerprint: nil, user_agent: nil, started_at: nil)
19
+ def initialize(visitor_id:, session_id:, url:, referrer: nil, device_fingerprint: nil,
20
+ user_agent: nil, started_at: nil, ip: nil, fbp: nil)
16
21
  @visitor_id = visitor_id
17
22
  @session_id = session_id
18
23
  @url = url
@@ -20,6 +25,8 @@ module Mbuzz
20
25
  @device_fingerprint = device_fingerprint
21
26
  @user_agent = user_agent
22
27
  @started_at = started_at
28
+ @ip = ip
29
+ @fbp = fbp
23
30
  end
24
31
 
25
32
  def call
@@ -32,7 +39,8 @@ module Mbuzz
32
39
 
33
40
  private
34
41
 
35
- attr_reader :visitor_id, :session_id, :url, :referrer, :device_fingerprint, :user_agent, :started_at
42
+ attr_reader :visitor_id, :session_id, :url, :referrer, :device_fingerprint, :user_agent,
43
+ :started_at, :ip, :fbp
36
44
 
37
45
  def valid?
38
46
  present?(visitor_id) && present?(session_id) && present?(url)
@@ -42,6 +50,11 @@ module Mbuzz
42
50
  @response ||= Api.post_with_response(SESSIONS_PATH, { session: payload })
43
51
  end
44
52
 
53
+ # `ip` is the visitor's address, which the middleware already extracted to
54
+ # compute `device_fingerprint` (SHA256(ip|user_agent)). It was computed
55
+ # and then dropped here until 2026-09-17: mbuzz needs it for Meta's
56
+ # `client_ip_address`, which Meta documents as required for website
57
+ # events, and the events/conversions payloads have always carried it.
45
58
  def payload
46
59
  {
47
60
  visitor_id: visitor_id,
@@ -50,6 +63,10 @@ module Mbuzz
50
63
  referrer: referrer,
51
64
  device_fingerprint: device_fingerprint,
52
65
  user_agent: user_agent,
66
+ ip: ip,
67
+ # Meta's browser id, already format-checked by Mbuzz::Fbp. Dropped by
68
+ # .compact when absent: omitted, not null.
69
+ fbp: fbp,
53
70
  started_at: started_at || Time.now.utc.iso8601
54
71
  }.compact
55
72
  end
data/lib/mbuzz/client.rb CHANGED
@@ -32,7 +32,8 @@ module Mbuzz
32
32
  ).call
33
33
  end
34
34
 
35
- def self.session(visitor_id:, session_id:, url:, referrer: nil, device_fingerprint: nil, user_agent: nil, started_at: nil)
35
+ def self.session(visitor_id:, session_id:, url:, referrer: nil, device_fingerprint: nil,
36
+ user_agent: nil, started_at: nil, ip: nil, fbp: nil)
36
37
  SessionRequest.new(
37
38
  visitor_id: visitor_id,
38
39
  session_id: session_id,
@@ -40,7 +41,9 @@ module Mbuzz
40
41
  referrer: referrer,
41
42
  device_fingerprint: device_fingerprint,
42
43
  user_agent: user_agent,
43
- started_at: started_at
44
+ started_at: started_at,
45
+ ip: ip,
46
+ fbp: fbp
44
47
  ).call
45
48
  end
46
49
  end
data/lib/mbuzz/fbp.rb ADDED
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mbuzz
4
+ # Meta's browser id, written client-side by the customer's Meta Pixel. Read
5
+ # only, never set: forwarded on the session call so Meta can merge mbuzz's
6
+ # server event with the Pixel's browser event.
7
+ module Fbp
8
+ # Meta's documented shape, fb.<subdomainIndex>.<creationTime>.<random>, plus
9
+ # the optional appendix Meta's server-side Parameter Builder adds
10
+ # (fb.1.<ts>.<random>.AQECAQIB). Both are valid to Meta. \A…\z, not ^…$:
11
+ # `$` matches before a trailing newline.
12
+ FORMAT = /\Afb\.\d+\.\d+\.\d+(?:\.[A-Za-z0-9_-]+)?\z/
13
+
14
+ # The Pixel's _fbp, or nil when absent or not in Meta's format. mbuzz never
15
+ # invents one and never rewrites what it forwards.
16
+ def self.read(value)
17
+ value if value.is_a?(String) && FORMAT.match?(value)
18
+ end
19
+ end
20
+ end
@@ -67,6 +67,7 @@ module Mbuzz
67
67
  referrer: payload["referrer"],
68
68
  ip: ip,
69
69
  user_agent: user_agent,
70
+ fbp: Fbp.read(request.cookies[FBP_COOKIE_NAME]),
70
71
  device_fingerprint: Digest::SHA256.hexdigest("#{ip}|#{user_agent}")[0, 32]
71
72
  }.freeze
72
73
  end
@@ -93,7 +94,9 @@ module Mbuzz
93
94
  url: context[:url],
94
95
  referrer: context[:referrer],
95
96
  device_fingerprint: context[:device_fingerprint],
96
- user_agent: context[:user_agent]
97
+ user_agent: context[:user_agent],
98
+ ip: context[:ip],
99
+ fbp: context[:fbp]
97
100
  )
98
101
  rescue StandardError => e
99
102
  log_error("Session creation failed: #{e.message}") if Mbuzz.config.debug
@@ -102,6 +102,7 @@ module Mbuzz
102
102
  referrer: request.referer,
103
103
  ip: ip,
104
104
  user_agent: user_agent,
105
+ fbp: Fbp.read(request.cookies[FBP_COOKIE_NAME]),
105
106
  device_fingerprint: Digest::SHA256.hexdigest("#{ip}|#{user_agent}")[0, 32]
106
107
  }.freeze
107
108
  end
@@ -133,7 +134,9 @@ module Mbuzz
133
134
  url: context[:url],
134
135
  referrer: context[:referrer],
135
136
  device_fingerprint: context[:device_fingerprint],
136
- user_agent: context[:user_agent]
137
+ user_agent: context[:user_agent],
138
+ ip: context[:ip],
139
+ fbp: context[:fbp]
137
140
  )
138
141
  end
139
142
 
data/lib/mbuzz/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Mbuzz
4
- VERSION = "0.10.0"
4
+ VERSION = "0.11.0"
5
5
  end
data/lib/mbuzz.rb CHANGED
@@ -4,6 +4,7 @@ require_relative "mbuzz/version"
4
4
  require_relative "mbuzz/configuration"
5
5
  require_relative "mbuzz/dropped_call"
6
6
  require_relative "mbuzz/visitor/identifier"
7
+ require_relative "mbuzz/fbp"
7
8
  require_relative "mbuzz/request_context"
8
9
  require_relative "mbuzz/api"
9
10
  require_relative "mbuzz/client"
@@ -29,6 +30,9 @@ module Mbuzz
29
30
  VISITOR_COOKIE_PATH = "/"
30
31
  VISITOR_COOKIE_SAME_SITE = "Lax"
31
32
 
33
+ # Meta Pixel's browser id. Read only; see Mbuzz::Fbp.
34
+ FBP_COOKIE_NAME = "_fbp"
35
+
32
36
  # The one request a cached page always sends to the app. Kept off /api and
33
37
  # /assets so host-app routing and cache rules don't shadow it.
34
38
  SESSION_ENDPOINT_PATH = "/_mbuzz/session"
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.10.0
4
+ version: 0.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - mbuzz team
@@ -47,6 +47,7 @@ files:
47
47
  - lib/mbuzz/controller_helpers.rb
48
48
  - lib/mbuzz/current.rb
49
49
  - lib/mbuzz/dropped_call.rb
50
+ - lib/mbuzz/fbp.rb
50
51
  - lib/mbuzz/middleware/session_endpoint.rb
51
52
  - lib/mbuzz/middleware/tracking.rb
52
53
  - lib/mbuzz/railtie.rb