@cross-deck/web 1.5.6 → 1.6.1

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.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,55 @@
2
2
 
3
3
  All notable changes to `@cross-deck/web` will be documented here. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
4
4
 
5
+ ## [1.6.1] — 2026-05-30
6
+
7
+ Minor — two autocapture fidelity fixes, plus a repair to the release
8
+ pipeline itself. (1.6.0 carried the same two fixes but never reached npm:
9
+ its automated publish hit a pre-existing broken test gate — a schema-lock
10
+ test that loaded a contract via a monorepo-only path that doesn't exist
11
+ in the published package. Fixed by reading the contract from the copy
12
+ bundled into the SDK, so this is the first build of these changes to
13
+ ship.) No public API change; event emission behaviour changes as
14
+ described, so read before upgrading if you have downstream logic keyed on
15
+ `session.ended` timing.
16
+
17
+ **Sessions now survive full-page navigations.** Session state was
18
+ in-memory only, so on a multi-page site (where the SDK re-installs on
19
+ every navigation) one visit was split into a separate session per page —
20
+ each `session.ended` on `pagehide` landing at the same instant the next
21
+ page's `session.started` fired. Sessions are now persisted (id, start,
22
+ last-activity, first-touch acquisition) to the same storage adapter as
23
+ identity and **resumed** across page loads within a rolling 30-minute
24
+ inactivity window.
25
+
26
+ - `session.started` no longer fires on a resumed page load — only on a
27
+ genuinely new session (first visit, or first load after >30 min idle).
28
+ - `session.ended` no longer fires on `pagehide` / `beforeunload` (a
29
+ navigation is not a session end). It fires only on real 30-min
30
+ inactivity or an explicit `Crossdeck.stop()`.
31
+ - The inactivity window is bumped by every tracked event (auto or
32
+ custom), not just pageviews/clicks.
33
+ - Honours consent posture: with `persistIdentity: false` or a
34
+ `MemoryStorage` adapter, the session is in-memory only (per-page, the
35
+ prior behaviour).
36
+ - Continuity is same-origin (localStorage); cross-subdomain stitching is
37
+ not yet handled.
38
+
39
+ **Click autocapture no longer mashes labels.** A click on a control that
40
+ wraps other controls or a content block (a card around several buttons, a
41
+ hero `<a>` around a heading + paragraph) used to collapse the whole
42
+ subtree into one string — `"Log inContinue with GoogleContinue with
43
+ Apple…"`, `"Tudo que você é,em um só link.Portfolio…"`. The resolver now
44
+ returns the control's own label (word boundaries preserved, decorative
45
+ `svg`/`style`/`script` skipped), or for a wrapper its direct label / the
46
+ first heading inside it, falling through to the selector rather than a
47
+ concatenation. Attribute precedence (`data-*` → aria → value → text →
48
+ title → img/svg) is unchanged.
49
+
50
+ Bundle-size budget for the core bundles raised 55 → 58 KB gzipped (ESM +
51
+ CJS) to fit the ~1 KB of new code; react/vue/UMD bundles unchanged and
52
+ still under budget.
53
+
5
54
  ## [1.5.1] — 2026-05-27
6
55
 
7
56
  `crossdeck.contract_failed` is now single-fire to a dedicated
package/README.md CHANGED
@@ -86,13 +86,15 @@ That's the full happy path.
86
86
 
87
87
  | Event | When |
88
88
  |---|---|
89
- | `session.started` | On boot. Carries `sessionId`. |
90
- | `session.ended` | On `pagehide` / `beforeunload`, OR when returning to a tab after >30 min idle. Carries `sessionId` and `durationMs`. |
89
+ | `session.started` | When a **new** session begins — first visit, or the first page load after >30 min of inactivity. A session resumed across a page navigation does **not** re-fire it. Carries `sessionId`. |
90
+ | `session.ended` | On a real session end only: >30 min of inactivity, or an explicit `Crossdeck.stop()`. Carries `sessionId` and `durationMs`. |
91
91
  | `page.viewed` | On initial load + every SPA navigation (`history.pushState`, `replaceState`, `popstate`). Carries `path`, `url`, `search`, `hash`, `title`, `referrer`. |
92
92
 
93
- Every event — auto-tracked and developer-emitted — is enriched with the device-info payload below. Quick tab switches (Cmd-Tab, switching browser tabs) don't end the session — only real closes do, matching GA4's session-window convention.
93
+ Every event — auto-tracked and developer-emitted — is enriched with the device-info payload below.
94
94
 
95
- **Per-session acquisition (v0.6.0+):** when a session starts the SDK reads `window.location.search` and `document.referrer` and captures `utm_source`, `utm_medium`, `utm_campaign`, `utm_content`, `utm_term`, plus `referrer`. Non-empty values are auto-attached to every subsequent event of that session first-touch attribution stays pinned to the entry URL even after SPA route changes strip the params away. A new session (>30 min idle) re-reads the URL.
95
+ **Sessions survive page loads (v1.6.0+).** A session is a *visit*, not a page. The SDK persists the session (id, start time, last-activity time, first-touch acquisition) to the same storage as identity, so a full-page navigation on a multi-page site **resumes the same session** rather than starting a new one. The window is a rolling 30-minute inactivity timer bumped by every tracked event (auto or custom); only real 30-min inactivity or `Crossdeck.stop()` ends it. A page unload (`pagehide`/`beforeunload`) is treated as a navigation, not an end. Quick tab switches (Cmd-Tab) likewise don't end the session — matching GA4's session-window convention. Continuity is same-origin; cross-subdomain stitching is on the roadmap. With `persistIdentity: false` (or a `MemoryStorage` adapter) the session is in-memory only and resets per page.
96
+
97
+ **Per-session acquisition (v0.6.0+):** when a session starts the SDK reads `window.location.search` and `document.referrer` and captures `utm_source`, `utm_medium`, `utm_campaign`, `utm_content`, `utm_term`, plus `referrer`. Non-empty values are auto-attached to every subsequent event of that session — first-touch attribution stays pinned to the entry URL even after SPA route changes strip the params away, and now stays pinned across full-page navigations within the session too. A new session (>30 min idle) re-reads the URL.
96
98
 
97
99
  ## Auto-attached device info
98
100
 
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
- "generatedAt": "2026-05-27T15:13:48.473Z",
3
+ "generatedAt": "2026-05-30T11:19:57.350Z",
4
4
  "sdk": "@cross-deck/web",
5
- "sdkVersion": "1.5.3",
6
- "bundledIn": "@cross-deck/web@1.5.3",
5
+ "sdkVersion": "1.6.1",
6
+ "bundledIn": "@cross-deck/web@1.6.1",
7
7
  "count": 8,
8
8
  "contracts": [
9
9
  {
@@ -126,7 +126,7 @@
126
126
  "legal/security/index.html#diagnostic",
127
127
  "legal/sdk-data/index.html#b-diagnostic"
128
128
  ],
129
- "bundledIn": "@cross-deck/web@1.5.3"
129
+ "bundledIn": "@cross-deck/web@1.6.1"
130
130
  },
131
131
  {
132
132
  "id": "error-envelope-shape",
@@ -165,7 +165,7 @@
165
165
  ],
166
166
  "registeredAt": "2026-05-26",
167
167
  "firstRegisteredIn": "bank-grade reconciliation v1.4.0 — phase 8 (codifies existing contract)",
168
- "bundledIn": "@cross-deck/web@1.5.3"
168
+ "bundledIn": "@cross-deck/web@1.6.1"
169
169
  },
170
170
  {
171
171
  "id": "flush-interval-parity",
@@ -210,7 +210,7 @@
210
210
  ],
211
211
  "registeredAt": "2026-05-26",
212
212
  "firstRegisteredIn": "bank-grade reconciliation v1.4.0 — phase 3.3",
213
- "bundledIn": "@cross-deck/web@1.5.3"
213
+ "bundledIn": "@cross-deck/web@1.6.1"
214
214
  },
215
215
  {
216
216
  "id": "idempotency-key-deterministic",
@@ -315,7 +315,7 @@
315
315
  ],
316
316
  "registeredAt": "2026-05-26",
317
317
  "firstRegisteredIn": "bank-grade reconciliation v1.4.0 — phase 2.2.a + 2.2.b + 2.2.c",
318
- "bundledIn": "@cross-deck/web@1.5.3"
318
+ "bundledIn": "@cross-deck/web@1.6.1"
319
319
  },
320
320
  {
321
321
  "id": "init-reentry-drains-prior-queue",
@@ -342,7 +342,7 @@
342
342
  ],
343
343
  "registeredAt": "2026-05-26",
344
344
  "firstRegisteredIn": "bank-grade reconciliation v1.4.0 — phase 5.5",
345
- "bundledIn": "@cross-deck/web@1.5.3"
345
+ "bundledIn": "@cross-deck/web@1.6.1"
346
346
  },
347
347
  {
348
348
  "id": "per-user-cache-isolation",
@@ -421,7 +421,7 @@
421
421
  ],
422
422
  "registeredAt": "2026-05-26",
423
423
  "firstRegisteredIn": "bank-grade reconciliation v1.4.0 — phase 1.3 (web/RN) + dogfood-gap fix (swift + android)",
424
- "bundledIn": "@cross-deck/web@1.5.3"
424
+ "bundledIn": "@cross-deck/web@1.6.1"
425
425
  },
426
426
  {
427
427
  "id": "sdk-error-codes-catalogue",
@@ -461,7 +461,7 @@
461
461
  ],
462
462
  "registeredAt": "2026-05-26",
463
463
  "firstRegisteredIn": "bank-grade reconciliation v1.4.0 — phase 6.2",
464
- "bundledIn": "@cross-deck/web@1.5.3"
464
+ "bundledIn": "@cross-deck/web@1.6.1"
465
465
  },
466
466
  {
467
467
  "id": "sync-purchases-funnel-parity",
@@ -494,7 +494,7 @@
494
494
  ],
495
495
  "registeredAt": "2026-05-26",
496
496
  "firstRegisteredIn": "bank-grade reconciliation v1.4.0 — phase 3.5",
497
- "bundledIn": "@cross-deck/web@1.5.3"
497
+ "bundledIn": "@cross-deck/web@1.6.1"
498
498
  }
499
499
  ]
500
500
  }