@reservamos/browser-analytics 1.1.8-alpha.1 → 1.1.8-alpha.3

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.
Files changed (30) hide show
  1. package/CHANGELOG.md +19 -2
  2. package/README.md +32 -4
  3. package/dist/browser-analytics.cjs +2 -2
  4. package/dist/browser-analytics.cjs.map +1 -1
  5. package/dist/browser-analytics.d.ts +23 -10
  6. package/dist/browser-analytics.esm.js +466 -154
  7. package/dist/browser-analytics.esm.js.map +1 -1
  8. package/dist/browser-analytics.iife.js +2 -2
  9. package/dist/browser-analytics.iife.js.map +1 -1
  10. package/package.json +2 -2
  11. package/src/events/identify/identify.recovery.test.ts +367 -0
  12. package/src/events/identify/identify.robustness.test.ts +112 -13
  13. package/src/events/identify/identify.ts +72 -35
  14. package/src/events/passengersCreated/passengersCreatedSchema.test.ts +142 -0
  15. package/src/events/passengersCreated/passengersCreatedSchema.ts +7 -1
  16. package/src/events/purchaseConfirmation/purchaseConfirmation.integration.test.ts +49 -0
  17. package/src/events/purchaseConfirmation/purchaseConfirmation.test.ts +17 -0
  18. package/src/events/purchaseConfirmation/purchaseConfirmationSchema.ts +2 -0
  19. package/src/index.ts +1 -0
  20. package/src/init.ts +10 -1
  21. package/src/profiles/createAnonymousProfile/createAnonymousProfile.ts +18 -2
  22. package/src/services/botDetectionRelay.test.ts +3 -2
  23. package/src/services/fingerprint.test.ts +172 -0
  24. package/src/services/fingerprint.ts +106 -5
  25. package/src/services/fingerprint.wait.integration.test.ts +129 -0
  26. package/src/services/mixpanel.batch.test.ts +108 -0
  27. package/src/services/mixpanel.test.ts +77 -73
  28. package/src/services/mixpanel.ts +45 -18
  29. package/src/services/profileEnrichment.ts +258 -0
  30. package/src/track.storage.test.ts +27 -12
package/CHANGELOG.md CHANGED
@@ -2,15 +2,32 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ - Pin js-api-client 6.28.1 to keep an initiated Fingerprint observation relay alive across navigation within browser limits; retain its five-second timeout and add a local redirect fixture.
6
+
7
+ - Recover pending `reservamos_one_id` profile enrichment after same-tab, same-origin navigation without another application identify call. Scope the original normalized Core request in sessionStorage to the current user and configuration, expire it after ten minutes, and limit profile requests to three attempts. Keep foreground identity nonblocking and fall back to ordinary in-memory enrichment when storage is unavailable.
8
+
9
+ - Reduce the Mixpanel batch flush interval to one second for events and people updates, including native identity events, while retaining batching and local identify completion semantics. Smaller batches can increase HTTP requests; the interval does not guarantee delivery before redirects.
10
+
11
+ - Apply Identify identity and initial people properties before optional profile/fingerprint enrichment; resolve locally before enrichment and suppress stale results without mutating caller properties.
12
+ - Add `analytics.identifiers.waitForFingerprintId(timeoutMs = 2000)` to await cached or in-flight identity within a caller budget without forcing fresh identification; preserve late successful cache updates when the caller times out and the identity lifecycle remains current.
13
+ - Accept optional validated `product` on Purchase Confirmation Viewed. These additive public changes require minor release impact.
14
+ - Accept an optional `Coupon` on `Passengers Created`, validated like `Payment Attempt`, so checkout events that carry a coupon are no longer rejected.
15
+
5
16
  - Accept zero departure and return stops in trip schemas so nonstop journeys can be tracked in Purchase Attempt and Payment Attempt.
6
17
 
18
+ - Submit View Results with cached or empty identity before refreshing Fingerprint, so pending identification cannot block the event.
19
+
7
20
  - Retain valid events that have not reached Mixpanel for up to 60 seconds with bounded memory and a five-second foreground wait. Claim each event once and never retry a submission that throws, preventing SDK recovery from replaying uncertain sends.
8
21
  - Defer Bot Detection observations for up to ten seconds while Fingerprint loads, cap actual identification concurrency at three, and suppress expired or stale identity/configuration effects without replaying original Mixpanel events.
9
22
  - Invalidate stale readiness during reinitialization, preserve original pending payload snapshots, and reuse matching Mixpanel singleton initialization without awaiting an unavailable callback. Reject unsupported in-place project/proxy changes before disturbing the active session.
10
23
 
11
- - Add manual alpha and stable publication alongside automatic patch/minor/major releases for PRs merged into main. Alphas also support the temporary alpha-sbx branch; both paths allocate versions from npm, validate fully, and tag the exact source commit without version commits on main.
12
- - A pending location permission or Fingerprint load no longer holds Tracker Ready. Core API is configured before listeners run; optional initialization waits are bounded to 3 seconds and pre-initialization fingerprint cache reads remain safe.
13
24
  - Search, Payment Attempt, and Purchase Attempt are submitted before fresh Fingerprint identification and Bot Detection relay. View Results and other non-bot events continue with an empty fingerprint when retrieval fails.
25
+
26
+ - A pending location permission or Fingerprint load no longer holds Tracker Ready. Core API is configured before listeners run; optional initialization waits are bounded to 3 seconds and pre-initialization fingerprint cache reads remain safe.
27
+ - Document that Search, Payment Attempt and Purchase Attempt fired before Fingerprint readiness can omit Bot Detection observations when Fingerprint remains unavailable throughout the ten-second deferral window; regression coverage verifies original event submission and no replay after optional initialization.
28
+
29
+ - Events called before Mixpanel is ready now wait up to 5 seconds instead of rejecting an unobserved promise, and resume directly when Mixpanel loads without waiting for optional initialization or `Tracker Ready`. Expired attempts log a controlled diagnostic, release their resources, and do not replay after late readiness.
30
+ - Add manual alpha and stable publication alongside automatic patch/minor/major releases for PRs merged into main. Alphas also support the temporary alpha-sbx branch; both paths allocate versions from npm, validate fully, and tag the exact source commit without version commits on main.
14
31
  - Blocked SDK localStorage no longer discards events or live Mixpanel identity. Cache fallback safely returns null when unavailable, and identify retains its controlled cache diagnostic and people updates.
15
32
 
16
33
  ## 1.1.7
package/README.md CHANGED
@@ -64,14 +64,14 @@ The SDK owns the eligible event list. Consumers do not configure a URL or choose
64
64
 
65
65
  For those events, fresh identification bypasses the Fingerprint SPA cache and runs in the background after the original event has been submitted. Its returned visitor ID and request ID are used for the relay; they do not replace the cached or empty fingerprint already submitted with the original event. View Results submits cached or empty identity before refreshing Fingerprint without a Bot Detection relay. Other events retain their existing cache selection and continue with an empty fingerprint if retrieval rejects.
66
66
 
67
- After handing the original event to Mixpanel, the SDK sends this JSON payload to `${coreApiBaseUrl}/v1/fingerprint/bot-detection` with `POST`, `Content-Type: application/json`, optional `x-app-name`, and `keepalive: true`. The browser supplies the actual `Origin` header:
67
+ After handing the original event to Mixpanel, the SDK sends this JSON payload to `${coreApiBaseUrl}/v1/fingerprint/bot-detection` with `POST`, `Content-Type: application/json`, optional `x-app-name`, through `js-api-client`. The pinned 6.28.1 client uses fetch `keepalive` with a five-second abort, allowing an already-started relay to continue after navigation within browser transport limits. The browser supplies the actual `Origin` header:
68
68
 
69
69
  ```json
70
70
  {
71
71
  "requestId": "request-123",
72
72
  "visitorId": "visitor-123",
73
73
  "distinctId": "mixpanel-distinct-123",
74
- "eventName": "Payment Attempt"
74
+ "eventName": "Fingerprint Requested"
75
75
  }
76
76
  ```
77
77
 
@@ -81,9 +81,9 @@ Relay failures are logged with `console.error` and do not turn an event already
81
81
 
82
82
  ## Identifying Users
83
83
 
84
- `await analytics.identify(...)` waits for the local identification attempt, not confirmed remote delivery. The SDK limits readiness to 5 seconds, anonymous-profile enrichment to 3 seconds, and fingerprint enrichment to 2 seconds. Optional enrichment or SDK cache failures do not block the Mixpanel attempt. Once readiness expires, a later `Tracker Ready` does not reactivate that call.
84
+ `await analytics.identify(...)` resolves after Mixpanel identity and initial people properties are submitted locally, without waiting for optional enrichment or confirming remote delivery. Readiness is limited to 5 seconds before that submission; anonymous-profile enrichment and fingerprint enrichment run afterward with limits of 3 and 2 seconds. Once readiness expires, a later `Tracker Ready` does not reactivate that call.
85
85
 
86
- Mixpanel profile callbacks and the existing geolocation request are observed separately for up to 5 seconds. The SDK does not retry requests; a missing callback means its outcome was not observed. Diagnostics use controlled stage/reason values without user identifiers or personal properties. `Visitor Found` is optional metadata: available booleans are preserved, and absent values are not replaced with `false` or inferred from cache state.
86
+ Mixpanel profile callbacks and the existing geolocation request are observed separately for up to 5 seconds. Profile recovery after navigation is bounded as described below; other optional requests are not retried. A missing callback means its outcome was not observed. Diagnostics use controlled stage/reason values without user identifiers or personal properties. `Visitor Found` is optional metadata: available booleans are preserved, and absent values are not replaced with `false` or inferred from cache state.
87
87
 
88
88
  The `identify` method accepts a main identifier and an object containing user information. The object has four predefined fields: `email`, `firstName`, `lastName`, and `phone`. In addition to these, you can include any custom fields to store additional user-specific information as needed.
89
89
 
@@ -165,3 +165,31 @@ Use these slash commands in Cursor or Claude Code:
165
165
  5. `/opsx-archive` — move the change to `openspec/changes/archive/`
166
166
 
167
167
  When OpenSpec is used, `tasks.md` is the canonical implementation plan. Do not also run `ce-plan` for the same change.
168
+
169
+ ## Comporte redirect and identity readiness
170
+
171
+ `await analytics.identify(userId, properties)` resolves after Mixpanel identity and the initial people properties are submitted locally. Anonymous profile and fingerprint enrichment run afterward, with their existing time limits. A later profile ID updates `reservamos_one_id` without identifying again. New identify attempts or initialization invalidate stale enrichment; caller properties are not mutated. Redirects can interrupt background work, and local completion does not guarantee remote delivery.
172
+
173
+ The SDK keeps Mixpanel batching enabled and configures a 1000 ms batch flush interval for events and people updates, including the native `$identify` event. This reduces queueing time before short redirects, but can produce smaller batches and more HTTP requests. Network delays and retries can extend delivery beyond that interval; it does not guarantee receipt before navigation.
174
+
175
+ Pending `reservamos_one_id` enrichment can resume after a full-page redirect when the destination initializes the SDK in the same tab and origin, with the same Mixpanel project/proxy, Core API base URL/application, and current user. No additional application `identify()` call is needed. Recovery restores native people readiness for that unchanged user without emitting a new `$identify` event; it does not replay business events or location identification.
176
+
177
+ The SDK stores at most one 4 KiB recovery entry in `sessionStorage`, containing the current user ID, configuration scope, attempt metadata, and the normalized original Core profile request: its email/phone, additional identifiers (including captured fingerprint and distinct ID), and name fields when supplied. Arbitrary custom properties and credentials are excluded. Replaying the same request preserves profile matching and details; it does not rebuild identifiers in the destination. The SDK replaces that request with the profile ID once resolved, then removes the entry after Mixpanel accepts the property update into its queue or confirms an unbatched request. Queue acceptance does not confirm remote delivery. Unresolved profiles allow at most three HTTP attempts, including the original, with no retry loop within one initialization. Entries expire after ten minutes and are checked and cleaned on SDK reads; tab closure ends their storage lifetime. Invalid entries and user/configuration mismatches are discarded. Blocked storage preserves ordinary in-memory enrichment but prevents recovery across navigation. A recovery HTTP request starts only after its attempt count is saved.
178
+
179
+ `analytics.identifiers.getFingerprintId()` remains a synchronous cache lookup. To wait for agent loading or an identification already in flight, use:
180
+
181
+ ```typescript
182
+ const fingerprintId = await analytics.identifiers.waitForFingerprintId(2000);
183
+ // fingerprintId is string | null. Waiting does not force a fresh FPJS request.
184
+ analytics.track.search(searchProperties);
185
+ ```
186
+
187
+ The wait defaults to 2000 ms and resolves `null` on timeout, failure or replaced session/initialization. Concurrent waits share identification; the timeout does not cancel an underlying provider request, and a late successful result still fills the cache while its initialization and identity lifecycle remain current. When neither cache nor in-flight work exists, waiting can start one cache-eligible FPJS identification. Eligible Bot Detection events still request their own fresh identification as before. Events keep their nonblocking cached-or-empty fingerprint behavior. If the cache cannot be written, the returned ID is still available, but later events may carry an empty fingerprint.
188
+
189
+ Send `analytics.track.purchaseConfirmation` when the confirmation page is viewed, with `Operation Id` and `Payment Status` (`confirmed` or `pending_pix`). Optional `product` accepts the same values as other SDK events (`web`, `web-mobile`, `ios`, `android`, `app`). This browser event is separate from datalake's Purchase Completed.
190
+
191
+ ## Local relay navigation check
192
+
193
+ Run `node scripts/serve-relay-redirect.mjs` and open the printed URL in a browser. The fixture invokes the real SDK relay with dummy IDs and credentials against a second local origin, then navigates without awaiting it. The local backend delays its response by 1.5 seconds. Read its `/observations` endpoint afterward to check CORS preflight, one POST, headers, normal completion or early disconnection. The pending-IDs button navigates before its simulated IDs exist and should produce no POST.
194
+
195
+ This check uses the published 6.28.1 client pinned by the SDK; it can also be repeated with a locally built candidate. Candidate verification is recorded in `openspec/changes/sdk-relay-keepalive/verification.md`; Comporte staging is still needed for their real origin, FPJS acquisition and backend. The fixture contacts only its localhost backend and does not initialize real Mixpanel or Fingerprint services.