@cross-deck/web 1.9.1 → 1.10.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.
package/dist/index.d.mts CHANGED
@@ -494,6 +494,14 @@ declare class CrossdeckClient {
494
494
  * `configure`). `start` will be removed in a future major version.
495
495
  */
496
496
  start(options: CrossdeckOptions): void;
497
+ /**
498
+ * Campaign-arrival connect. If the landing URL carries a Crossdeck tag
499
+ * (`cd_ref`), post it to the arrival endpoint so the backend binds this
500
+ * anonymous session to the tagged person and pulls their integration
501
+ * record (deals, pipeline) onto their journey. Browser-only; fire-and-
502
+ * forget (never throws); backend-idempotent so a re-fire is harmless.
503
+ */
504
+ private captureCampaignArrival;
497
505
  /**
498
506
  * Link the anonymous device to a developer-supplied user ID. Cache
499
507
  * the resolved Crossdeck customer for follow-up calls.
@@ -961,7 +969,7 @@ declare class MemoryStorage implements KeyValueStorage {
961
969
  *
962
970
  * Do NOT edit by hand — `node scripts/sync-sdk-versions.mjs`.
963
971
  */
964
- declare const SDK_VERSION = "1.9.1";
972
+ declare const SDK_VERSION = "1.10.3";
965
973
  declare const SDK_NAME = "@cross-deck/web";
966
974
 
967
975
  /**
package/dist/index.d.ts CHANGED
@@ -494,6 +494,14 @@ declare class CrossdeckClient {
494
494
  * `configure`). `start` will be removed in a future major version.
495
495
  */
496
496
  start(options: CrossdeckOptions): void;
497
+ /**
498
+ * Campaign-arrival connect. If the landing URL carries a Crossdeck tag
499
+ * (`cd_ref`), post it to the arrival endpoint so the backend binds this
500
+ * anonymous session to the tagged person and pulls their integration
501
+ * record (deals, pipeline) onto their journey. Browser-only; fire-and-
502
+ * forget (never throws); backend-idempotent so a re-fire is harmless.
503
+ */
504
+ private captureCampaignArrival;
497
505
  /**
498
506
  * Link the anonymous device to a developer-supplied user ID. Cache
499
507
  * the resolved Crossdeck customer for follow-up calls.
@@ -961,7 +969,7 @@ declare class MemoryStorage implements KeyValueStorage {
961
969
  *
962
970
  * Do NOT edit by hand — `node scripts/sync-sdk-versions.mjs`.
963
971
  */
964
- declare const SDK_VERSION = "1.9.1";
972
+ declare const SDK_VERSION = "1.10.3";
965
973
  declare const SDK_NAME = "@cross-deck/web";
966
974
 
967
975
  /**
package/dist/index.mjs CHANGED
@@ -69,7 +69,7 @@ function typeMapForStatus(status) {
69
69
  }
70
70
 
71
71
  // src/_version.ts
72
- var SDK_VERSION = "1.9.1";
72
+ var SDK_VERSION = "1.10.3";
73
73
  var SDK_NAME = "@cross-deck/web";
74
74
 
75
75
  // src/http.ts
@@ -1633,24 +1633,32 @@ var AutoTracker = class {
1633
1633
  this.emitSessionStart();
1634
1634
  }
1635
1635
  const onVisChange = () => {
1636
- if (!this.session) return;
1637
- const doc2 = globalThis.document;
1638
- if (doc2.visibilityState === "hidden") {
1639
- this.session.hiddenAt = Date.now();
1640
- this.persistSession();
1641
- } else if (doc2.visibilityState === "visible") {
1642
- const idleFor = Date.now() - this.session.lastActivityAt;
1643
- if (idleFor >= SESSION_RESUME_THRESHOLD_MS) {
1644
- this.pageviewId = null;
1645
- this.session = this.startNewSession();
1636
+ try {
1637
+ if (!this.session) return;
1638
+ const doc2 = globalThis.document;
1639
+ if (doc2.visibilityState === "hidden") {
1640
+ this.session.hiddenAt = Date.now();
1646
1641
  this.persistSession();
1647
- this.emitSessionStart();
1648
- } else {
1649
- this.session.hiddenAt = null;
1642
+ } else if (doc2.visibilityState === "visible") {
1643
+ const idleFor = Date.now() - this.session.lastActivityAt;
1644
+ if (idleFor >= SESSION_RESUME_THRESHOLD_MS) {
1645
+ this.pageviewId = null;
1646
+ this.session = this.startNewSession();
1647
+ this.persistSession();
1648
+ this.emitSessionStart();
1649
+ } else {
1650
+ this.session.hiddenAt = null;
1651
+ }
1650
1652
  }
1653
+ } catch {
1654
+ }
1655
+ };
1656
+ const onPageHide = () => {
1657
+ try {
1658
+ this.persistSession();
1659
+ } catch {
1651
1660
  }
1652
1661
  };
1653
- const onPageHide = () => this.persistSession();
1654
1662
  const w = globalThis.window;
1655
1663
  const doc = globalThis.document;
1656
1664
  doc.addEventListener("visibilitychange", onVisChange);
@@ -2514,17 +2522,20 @@ var WebVitalsTracker = class {
2514
2522
  } catch {
2515
2523
  }
2516
2524
  const flush = () => {
2517
- if (lcpValue > 0 && !this.flushed.has("lcp")) {
2518
- this.flushed.add("lcp");
2519
- this.report("webvitals.lcp", { valueMs: Math.round(lcpValue) });
2520
- }
2521
- if (this.cls > 0 && !this.flushed.has("cls")) {
2522
- this.flushed.add("cls");
2523
- this.report("webvitals.cls", { value: Math.round(this.cls * 1e3) / 1e3 });
2524
- }
2525
- if (this.inp > 0 && !this.flushed.has("inp")) {
2526
- this.flushed.add("inp");
2527
- this.report("webvitals.inp", { valueMs: Math.round(this.inp) });
2525
+ try {
2526
+ if (lcpValue > 0 && !this.flushed.has("lcp")) {
2527
+ this.flushed.add("lcp");
2528
+ this.report("webvitals.lcp", { valueMs: Math.round(lcpValue) });
2529
+ }
2530
+ if (this.cls > 0 && !this.flushed.has("cls")) {
2531
+ this.flushed.add("cls");
2532
+ this.report("webvitals.cls", { value: Math.round(this.cls * 1e3) / 1e3 });
2533
+ }
2534
+ if (this.inp > 0 && !this.flushed.has("inp")) {
2535
+ this.flushed.add("inp");
2536
+ this.report("webvitals.inp", { valueMs: Math.round(this.inp) });
2537
+ }
2538
+ } catch {
2528
2539
  }
2529
2540
  };
2530
2541
  const onHidden = () => {
@@ -3787,6 +3798,8 @@ function buildFrame(input) {
3787
3798
  function isInAppFrame(filename) {
3788
3799
  if (!filename) return true;
3789
3800
  if (/^(?:chrome|moz|safari|webkit)-extension:\/\//.test(filename)) return false;
3801
+ if (/^iabjs:\/\//.test(filename)) return false;
3802
+ if (/^(?:webview|inappbrowser):\/\//i.test(filename)) return false;
3790
3803
  if (/\bcdn\.jsdelivr\.net\b/.test(filename)) return false;
3791
3804
  if (/\bunpkg\.com\b/.test(filename)) return false;
3792
3805
  if (/\bgoogletagmanager\.com\b/.test(filename)) return false;
@@ -3795,7 +3808,18 @@ function isInAppFrame(filename) {
3795
3808
  if (/\/crossdeck\.umd\.min\.js$/.test(filename)) return false;
3796
3809
  return true;
3797
3810
  }
3811
+ var BROWSER_INJECTED_GLOBAL = /(__firefox__|__gCrWeb|zaloJSV2)/;
3812
+ function injectedGlobalName(message) {
3813
+ const m = BROWSER_INJECTED_GLOBAL.exec(message ?? "");
3814
+ return m ? m[1] : null;
3815
+ }
3816
+ function demoteVendorInjectedFrames(frames, message) {
3817
+ if (!injectedGlobalName(message)) return frames;
3818
+ return frames.map((f) => f.in_app ? { ...f, in_app: false } : f);
3819
+ }
3798
3820
  function fingerprintError(message, frames, location2) {
3821
+ const injected = injectedGlobalName(message);
3822
+ if (injected) return djb2Hex(`injected-global:${injected}`);
3799
3823
  const inAppFrames = frames.filter((f) => f.in_app).slice(0, 3);
3800
3824
  const parts = [
3801
3825
  (message || "").slice(0, 200),
@@ -4152,7 +4176,7 @@ var ErrorTracker = class {
4152
4176
  const payload = coerceErrorPayload(err);
4153
4177
  const message = (payload.message || event.message || "Unknown error").slice(0, 1024);
4154
4178
  const stack = err instanceof Error ? err.stack ?? null : null;
4155
- const frames = parseStack(stack);
4179
+ const frames = demoteVendorInjectedFrames(parseStack(stack), message);
4156
4180
  const errorType = payload.errorType ?? null;
4157
4181
  const context = payload.extras ? { ...this.opts.getContext(), __error_extras: payload.extras } : this.opts.getContext();
4158
4182
  return {
@@ -4184,7 +4208,7 @@ var ErrorTracker = class {
4184
4208
  const payload = coerceErrorPayload(err);
4185
4209
  const message = (payload.message || "Unknown error").slice(0, 1024);
4186
4210
  const stack = err instanceof Error ? err.stack ?? null : null;
4187
- const frames = parseStack(stack);
4211
+ const frames = demoteVendorInjectedFrames(parseStack(stack), message);
4188
4212
  const errorType = payload.errorType ?? null;
4189
4213
  const context = payload.extras ? { ...this.opts.getContext(), __error_extras: payload.extras } : this.opts.getContext();
4190
4214
  return {
@@ -4748,6 +4772,9 @@ var CrossdeckClient = class {
4748
4772
  if (opts.autoHeartbeat && !localDevMode) {
4749
4773
  void this.heartbeat().catch(() => void 0);
4750
4774
  }
4775
+ if (!localDevMode) {
4776
+ void this.captureCampaignArrival().catch(() => void 0);
4777
+ }
4751
4778
  if (options.disableContractAssertions !== true) {
4752
4779
  const debugDefault = defaultDebugModeFlag();
4753
4780
  this.verifierCtx = buildVerifierContext({
@@ -4845,6 +4872,32 @@ var CrossdeckClient = class {
4845
4872
  }
4846
4873
  this.init(options);
4847
4874
  }
4875
+ /**
4876
+ * Campaign-arrival connect. If the landing URL carries a Crossdeck tag
4877
+ * (`cd_ref`), post it to the arrival endpoint so the backend binds this
4878
+ * anonymous session to the tagged person and pulls their integration
4879
+ * record (deals, pipeline) onto their journey. Browser-only; fire-and-
4880
+ * forget (never throws); backend-idempotent so a re-fire is harmless.
4881
+ */
4882
+ async captureCampaignArrival() {
4883
+ const s = this.state;
4884
+ if (!s) return;
4885
+ const loc = globalThis.location;
4886
+ if (!loc || typeof loc.search !== "string" || loc.search.length === 0) return;
4887
+ let ref = null;
4888
+ try {
4889
+ ref = new URLSearchParams(loc.search).get("cd_ref");
4890
+ } catch {
4891
+ return;
4892
+ }
4893
+ if (!ref) return;
4894
+ try {
4895
+ await s.http.request("POST", "/integrations/hubspot/arrival", {
4896
+ body: { anonymousId: s.identity.anonymousId, ref }
4897
+ });
4898
+ } catch {
4899
+ }
4900
+ }
4848
4901
  /**
4849
4902
  * Link the anonymous device to a developer-supplied user ID. Cache
4850
4903
  * the resolved Crossdeck customer for follow-up calls.
@@ -5733,9 +5786,17 @@ function installUnloadFlush(onUnload) {
5733
5786
  const doc = globalThis.document;
5734
5787
  if (!w || !doc) return () => void 0;
5735
5788
  const onVisChange = () => {
5736
- if (doc.visibilityState === "hidden") onUnload();
5789
+ try {
5790
+ if (doc.visibilityState === "hidden") onUnload();
5791
+ } catch {
5792
+ }
5793
+ };
5794
+ const onTerminal = () => {
5795
+ try {
5796
+ onUnload();
5797
+ } catch {
5798
+ }
5737
5799
  };
5738
- const onTerminal = () => onUnload();
5739
5800
  doc.addEventListener("visibilitychange", onVisChange);
5740
5801
  w.addEventListener("pagehide", onTerminal);
5741
5802
  w.addEventListener("beforeunload", onTerminal);