@cross-deck/web 0.5.0 → 0.7.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.
package/dist/index.d.mts CHANGED
@@ -148,6 +148,15 @@ interface AutoTrackOptions {
148
148
  pageViews: boolean;
149
149
  /** Auto-attach os/browser/locale/screen/etc to every event's `properties`. Default true (browser only). */
150
150
  deviceInfo: boolean;
151
+ /**
152
+ * Click autocapture — fire `element.clicked` for every interactive
153
+ * click on the page. Default true. Mixpanel/Amplitude pattern. Powers
154
+ * Crossdeck's funnel-attribution USP ("clicked X then converted").
155
+ * Privacy: skips form inputs / password fields / [class~="cd-noTrack"]
156
+ * subtrees. Override on individual elements with data-cd-event="custom"
157
+ * or data-cd-prop-* for custom property tagging.
158
+ */
159
+ clicks: boolean;
151
160
  }
152
161
  /** Minimal interface for any pluggable key-value persistence. */
153
162
  interface KeyValueStorage {
@@ -402,7 +411,20 @@ declare class CrossdeckClient {
402
411
  * — matches the resolveCrossdeckCustomerId precedence on the server.
403
412
  */
404
413
  private identityQueryParams;
405
- /** Pick the right identity hint to embed on a queued event. */
414
+ /**
415
+ * Embed every known identity axis on the event. Earlier this returned
416
+ * just the highest-priority hint (cdcust → developerUserId → anonymousId)
417
+ * to keep payloads small, but that leaked into analytics: once a user
418
+ * was logged in, every subsequent page.viewed shipped without
419
+ * anonymousId, and `uniqExact(anonymous_id)` on the warehouse side
420
+ * counted 0 visitors for the entire authenticated app.
421
+ *
422
+ * Bank-grade rule: the server is the single source of truth on
423
+ * dedup. Send everything we know; let CH count by whichever axis
424
+ * matches the question. Each field is at most 32 bytes — sending
425
+ * three on every event costs ~80 bytes per request, which is
426
+ * trivial compared to the analytics correctness it buys.
427
+ */
406
428
  private identityHintForEvent;
407
429
  private mintEventId;
408
430
  }
@@ -448,12 +470,40 @@ declare class CrossdeckError extends Error {
448
470
  /**
449
471
  * Storage adapters for SDK-persisted state.
450
472
  *
451
- * Two flavours:
473
+ * Three flavours:
452
474
  * - browser localStorage (default in browsers)
475
+ * - 1st-party document.cookie (redundancy for cleared localStorage)
453
476
  * - in-memory (default in Node, or as an explicit fallback)
454
477
  *
455
478
  * Detection is at construction time, not at every call — picking the
456
479
  * adapter once means we don't hit `typeof window` checks on hot paths.
480
+ *
481
+ * ----- Bank-grade identity continuity -----
482
+ *
483
+ * Plain localStorage is not enough. ITP, private browsing, "clear site
484
+ * data" actions, and aggressive privacy extensions all wipe it. When
485
+ * that happens, the SDK mints a fresh anonymousId on next page load
486
+ * and the customer's analytics see one human as multiple "new
487
+ * visitors" — a credibility hit on every dashboard chart that depends
488
+ * on visitor uniqueness (new vs returning, retention, funnels).
489
+ *
490
+ * The fix is redundancy: we write the same identity to BOTH
491
+ * localStorage AND a 1st-party cookie. On boot we read both; whichever
492
+ * survived wins. On set, we write to both stores so a future clear of
493
+ * either doesn't lose the user.
494
+ *
495
+ * Caveats (documented honestly):
496
+ * 1. Safari ITP caps client-set 1st-party cookies at 7 days. Cookie
497
+ * redundancy protects against localStorage clears WITHIN that
498
+ * 7-day window, not beyond it. The full ITP-bypass story (server-
499
+ * set cookies via a customer-CNAMEd subdomain) is a Phase 2
500
+ * follow-up that requires customer DNS configuration.
501
+ * 2. We never write fingerprintable data — only the same anonymousId
502
+ * already in localStorage. Privacy posture is unchanged from
503
+ * single-store identity.
504
+ * 3. `persistIdentity: false` disables BOTH stores so customers
505
+ * running strict consent flows can defer cookie writes until the
506
+ * user opts in.
457
507
  */
458
508
 
459
509
  /**
@@ -476,7 +526,7 @@ declare class MemoryStorage implements KeyValueStorage {
476
526
  * fetch shim, no transitive deps.
477
527
  */
478
528
  declare const SDK_NAME = "@cross-deck/web";
479
- declare const SDK_VERSION = "0.5.0";
529
+ declare const SDK_VERSION = "0.6.0";
480
530
  declare const DEFAULT_BASE_URL = "https://api.cross-deck.com/v1";
481
531
 
482
532
  /**
package/dist/index.d.ts CHANGED
@@ -148,6 +148,15 @@ interface AutoTrackOptions {
148
148
  pageViews: boolean;
149
149
  /** Auto-attach os/browser/locale/screen/etc to every event's `properties`. Default true (browser only). */
150
150
  deviceInfo: boolean;
151
+ /**
152
+ * Click autocapture — fire `element.clicked` for every interactive
153
+ * click on the page. Default true. Mixpanel/Amplitude pattern. Powers
154
+ * Crossdeck's funnel-attribution USP ("clicked X then converted").
155
+ * Privacy: skips form inputs / password fields / [class~="cd-noTrack"]
156
+ * subtrees. Override on individual elements with data-cd-event="custom"
157
+ * or data-cd-prop-* for custom property tagging.
158
+ */
159
+ clicks: boolean;
151
160
  }
152
161
  /** Minimal interface for any pluggable key-value persistence. */
153
162
  interface KeyValueStorage {
@@ -402,7 +411,20 @@ declare class CrossdeckClient {
402
411
  * — matches the resolveCrossdeckCustomerId precedence on the server.
403
412
  */
404
413
  private identityQueryParams;
405
- /** Pick the right identity hint to embed on a queued event. */
414
+ /**
415
+ * Embed every known identity axis on the event. Earlier this returned
416
+ * just the highest-priority hint (cdcust → developerUserId → anonymousId)
417
+ * to keep payloads small, but that leaked into analytics: once a user
418
+ * was logged in, every subsequent page.viewed shipped without
419
+ * anonymousId, and `uniqExact(anonymous_id)` on the warehouse side
420
+ * counted 0 visitors for the entire authenticated app.
421
+ *
422
+ * Bank-grade rule: the server is the single source of truth on
423
+ * dedup. Send everything we know; let CH count by whichever axis
424
+ * matches the question. Each field is at most 32 bytes — sending
425
+ * three on every event costs ~80 bytes per request, which is
426
+ * trivial compared to the analytics correctness it buys.
427
+ */
406
428
  private identityHintForEvent;
407
429
  private mintEventId;
408
430
  }
@@ -448,12 +470,40 @@ declare class CrossdeckError extends Error {
448
470
  /**
449
471
  * Storage adapters for SDK-persisted state.
450
472
  *
451
- * Two flavours:
473
+ * Three flavours:
452
474
  * - browser localStorage (default in browsers)
475
+ * - 1st-party document.cookie (redundancy for cleared localStorage)
453
476
  * - in-memory (default in Node, or as an explicit fallback)
454
477
  *
455
478
  * Detection is at construction time, not at every call — picking the
456
479
  * adapter once means we don't hit `typeof window` checks on hot paths.
480
+ *
481
+ * ----- Bank-grade identity continuity -----
482
+ *
483
+ * Plain localStorage is not enough. ITP, private browsing, "clear site
484
+ * data" actions, and aggressive privacy extensions all wipe it. When
485
+ * that happens, the SDK mints a fresh anonymousId on next page load
486
+ * and the customer's analytics see one human as multiple "new
487
+ * visitors" — a credibility hit on every dashboard chart that depends
488
+ * on visitor uniqueness (new vs returning, retention, funnels).
489
+ *
490
+ * The fix is redundancy: we write the same identity to BOTH
491
+ * localStorage AND a 1st-party cookie. On boot we read both; whichever
492
+ * survived wins. On set, we write to both stores so a future clear of
493
+ * either doesn't lose the user.
494
+ *
495
+ * Caveats (documented honestly):
496
+ * 1. Safari ITP caps client-set 1st-party cookies at 7 days. Cookie
497
+ * redundancy protects against localStorage clears WITHIN that
498
+ * 7-day window, not beyond it. The full ITP-bypass story (server-
499
+ * set cookies via a customer-CNAMEd subdomain) is a Phase 2
500
+ * follow-up that requires customer DNS configuration.
501
+ * 2. We never write fingerprintable data — only the same anonymousId
502
+ * already in localStorage. Privacy posture is unchanged from
503
+ * single-store identity.
504
+ * 3. `persistIdentity: false` disables BOTH stores so customers
505
+ * running strict consent flows can defer cookie writes until the
506
+ * user opts in.
457
507
  */
458
508
 
459
509
  /**
@@ -476,7 +526,7 @@ declare class MemoryStorage implements KeyValueStorage {
476
526
  * fetch shim, no transitive deps.
477
527
  */
478
528
  declare const SDK_NAME = "@cross-deck/web";
479
- declare const SDK_VERSION = "0.5.0";
529
+ declare const SDK_VERSION = "0.6.0";
480
530
  declare const DEFAULT_BASE_URL = "https://api.cross-deck.com/v1";
481
531
 
482
532
  /**