@hanzo/event 0.3.43 → 0.3.48

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.cts CHANGED
@@ -9,6 +9,13 @@ export { scrubText, redactSecrets, scrubPII } from './scrub';
9
9
  export { EVENTS, EXCEPTION, PAGEVIEW } from './events';
10
10
  export { exceptionEntry, exceptionProperties, fingerprint, digest } from './exception';
11
11
  export type { EventName } from './events';
12
+ export { CONSENT_COOKIE, CONSENT_EVENT, acceptAll, asks, gpc, read as readConsent, refused, region, rejectAll, render as renderConsent, save as saveConsent, stored as storedConsent, } from './consent';
13
+ export type { Choice, Region } from './consent';
14
+ export { CLICK_IDS, capture as captureClick, touch } from './touch';
15
+ export { start as startTags, track, mirror, reach, visit, SITE_KEY } from './tags';
16
+ export type { BrowserTag, TagOptions } from './tags';
17
+ export { commerceItem, worth } from './items';
18
+ export type { CommerceItem, PlanLine } from './items';
12
19
  export { GOALS, COHORTS } from './goals';
13
20
  export type { GoalDef, CohortDef } from './goals';
14
21
  export { FUNNELS, PRODUCTS, eventsOf } from './funnels';
package/dist/index.d.ts CHANGED
@@ -9,6 +9,13 @@ export { scrubText, redactSecrets, scrubPII } from './scrub';
9
9
  export { EVENTS, EXCEPTION, PAGEVIEW } from './events';
10
10
  export { exceptionEntry, exceptionProperties, fingerprint, digest } from './exception';
11
11
  export type { EventName } from './events';
12
+ export { CONSENT_COOKIE, CONSENT_EVENT, acceptAll, asks, gpc, read as readConsent, refused, region, rejectAll, render as renderConsent, save as saveConsent, stored as storedConsent, } from './consent';
13
+ export type { Choice, Region } from './consent';
14
+ export { CLICK_IDS, capture as captureClick, touch } from './touch';
15
+ export { start as startTags, track, mirror, reach, visit, SITE_KEY } from './tags';
16
+ export type { BrowserTag, TagOptions } from './tags';
17
+ export { commerceItem, worth } from './items';
18
+ export type { CommerceItem, PlanLine } from './items';
12
19
  export { GOALS, COHORTS } from './goals';
13
20
  export type { GoalDef, CohortDef } from './goals';
14
21
  export { FUNNELS, PRODUCTS, eventsOf } from './funnels';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AASA,OAAO,EACL,SAAS,EACT,eAAe,EACf,YAAY,EACZ,OAAO,EACP,SAAS,EACT,aAAa,GACd,MAAM,QAAQ,CAAA;AACf,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AACrF,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,OAAO,CAAA;AAC1C,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAA;AAClE,YAAY,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAA;AACvC,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,OAAO,CAAA;AACtD,YAAY,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAC7C,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAC5D,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AACtD,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACtF,YAAY,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AACzC,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACxC,YAAY,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AACjD,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AACvD,YAAY,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AAC3E,OAAO,EACL,gBAAgB,EAChB,aAAa,EACb,cAAc,EACd,MAAM,EACN,OAAO,GACR,MAAM,eAAe,CAAA;AACtB,YAAY,EACV,eAAe,EACf,WAAW,EACX,mBAAmB,EACnB,MAAM,EACN,GAAG,EACH,SAAS,EACT,SAAS,EACT,cAAc,EACd,cAAc,EACd,mBAAmB,EACnB,WAAW,EACX,WAAW,EACX,WAAW,EACX,SAAS,EACT,SAAS,GACV,MAAM,SAAS,CAAA;AAEhB;;;kEAGkE;AAClE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,OAAO,CAAA;AACtE,YAAY,EAAE,OAAO,EAAE,MAAM,OAAO,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AASA,OAAO,EACL,SAAS,EACT,eAAe,EACf,YAAY,EACZ,OAAO,EACP,SAAS,EACT,aAAa,GACd,MAAM,QAAQ,CAAA;AACf,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AACrF,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,OAAO,CAAA;AAC1C,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAA;AAClE,YAAY,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAA;AACvC,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,OAAO,CAAA;AACtD,YAAY,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAC7C,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAC5D,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AACtD,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACtF,YAAY,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AACzC,OAAO,EACL,cAAc,EAAE,aAAa,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,IAAI,WAAW,EAAE,OAAO,EAAE,MAAM,EACzF,SAAS,EAAE,MAAM,IAAI,aAAa,EAAE,IAAI,IAAI,WAAW,EAAE,MAAM,IAAI,aAAa,GACjF,MAAM,WAAW,CAAA;AAClB,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,WAAW,CAAA;AAC/C,OAAO,EAAE,SAAS,EAAE,OAAO,IAAI,YAAY,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AACnE,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAA;AAClF,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;AACpD,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAC7C,YAAY,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AACrD,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACxC,YAAY,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AACjD,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AACvD,YAAY,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AAC3E,OAAO,EACL,gBAAgB,EAChB,aAAa,EACb,cAAc,EACd,MAAM,EACN,OAAO,GACR,MAAM,eAAe,CAAA;AACtB,YAAY,EACV,eAAe,EACf,WAAW,EACX,mBAAmB,EACnB,MAAM,EACN,GAAG,EACH,SAAS,EACT,SAAS,EACT,cAAc,EACd,cAAc,EACd,mBAAmB,EACnB,WAAW,EACX,WAAW,EACX,WAAW,EACX,SAAS,EACT,SAAS,GACV,MAAM,SAAS,CAAA;AAEhB;;;kEAGkE;AAClE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,OAAO,CAAA;AACtE,YAAY,EAAE,OAAO,EAAE,MAAM,OAAO,CAAA"}
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { eventsOf, EVENTS, PAGEVIEW, EXCEPTION } from '@hanzo/events';
1
+ import { eventsOf, EVENTS, PAGEVIEW, EXCEPTION, namesOn } from '@hanzo/events';
2
2
  export { EVENTS, EXCEPTION, FUNNELS, PAGEVIEW, PRODUCTS, eventsOf } from '@hanzo/events';
3
3
 
4
4
  // src/attribution.ts
@@ -18,20 +18,20 @@ var SOCIAL_HOSTS = [
18
18
  var SEARCH_HOSTS = ["google.", "bing.", "duckduckgo.", "yahoo.", "baidu.", "ecosia."];
19
19
  function parseAttribution(search, referrer) {
20
20
  const q = new URLSearchParams(search || "");
21
- const get = (k) => {
21
+ const get2 = (k) => {
22
22
  const v = q.get(k);
23
23
  return v ? v.trim() : void 0;
24
24
  };
25
25
  const a = {
26
26
  utm: {
27
- source: get("utm_source"),
28
- medium: get("utm_medium"),
29
- campaign: get("utm_campaign"),
30
- term: get("utm_term"),
31
- content: get("utm_content")
27
+ source: get2("utm_source"),
28
+ medium: get2("utm_medium"),
29
+ campaign: get2("utm_campaign"),
30
+ term: get2("utm_term"),
31
+ content: get2("utm_content")
32
32
  },
33
33
  referrer: referrer ? referrer.trim() : void 0,
34
- refCode: get("ref") || get("refCode") || get("ref_code") || void 0
34
+ refCode: get2("ref") || get2("refCode") || get2("ref_code") || void 0
35
35
  };
36
36
  a.channel = deriveChannel(a);
37
37
  return a;
@@ -288,13 +288,13 @@ var HZ_ANON_ADOPT = ["hz_anon_id", "hz_id"];
288
288
  var HZ_ANON_DOMAIN = "hanzo.ai";
289
289
  var HZ_ANON_MAX_AGE = 2 * 365 * 24 * 60 * 60;
290
290
  var hzAnonMemo;
291
- function hzUuidv7(now) {
291
+ function hzUuidv7(now2) {
292
292
  var b = new Uint8Array(16);
293
293
  var i;
294
294
  var c = typeof crypto !== "undefined" ? crypto : void 0;
295
295
  if (c && typeof c.getRandomValues === "function") c.getRandomValues(b);
296
296
  else for (i = 0; i < 16; i++) b[i] = Math.random() * 256 | 0;
297
- var t = Math.floor(now === void 0 ? Date.now() : now);
297
+ var t = Math.floor(now2 === void 0 ? Date.now() : now2);
298
298
  for (i = 5; i >= 0; i--) {
299
299
  b[i] = t % 256;
300
300
  t = Math.floor(t / 256);
@@ -406,7 +406,7 @@ function uuidv7Time(id) {
406
406
  }
407
407
 
408
408
  // package.json
409
- var version = "0.3.43";
409
+ var version = "0.3.48";
410
410
 
411
411
  // src/version.ts
412
412
  var VERSION = version;
@@ -539,22 +539,22 @@ function coerceTag(v) {
539
539
  return s.length > MAX_TAG_LEN ? s.slice(0, MAX_TAG_LEN) : s;
540
540
  }
541
541
  function buildSentryEvent(input) {
542
- const { error, options = {}, identity, capturePII = false } = input;
542
+ const { error, options: options2 = {}, identity, capturePII = false } = input;
543
543
  const norm = normalizeError(error);
544
- const handled = options.handled !== false;
545
- const level = options.level ?? (handled ? "error" : "fatal");
546
- const tags = { handled: String(handled) };
547
- if (identity.product) tags.product = identity.product;
548
- if (identity.sessionId) tags.session = identity.sessionId;
544
+ const handled = options2.handled !== false;
545
+ const level = options2.level ?? (handled ? "error" : "fatal");
546
+ const tags2 = { handled: String(handled) };
547
+ if (identity.product) tags2.product = identity.product;
548
+ if (identity.sessionId) tags2.session = identity.sessionId;
549
549
  try {
550
- const props = options.properties ?? {};
550
+ const props = options2.properties ?? {};
551
551
  let n = 0;
552
552
  for (const k of Object.keys(props)) {
553
553
  if (n >= MAX_TAGS) break;
554
554
  try {
555
555
  const val = props[k];
556
556
  if (val === void 0 || val === null) continue;
557
- tags[k] = scrubText(coerceTag(val), capturePII);
557
+ tags2[k] = scrubText(coerceTag(val), capturePII);
558
558
  n++;
559
559
  } catch {
560
560
  continue;
@@ -579,7 +579,7 @@ function buildSentryEvent(input) {
579
579
  }
580
580
  ]
581
581
  },
582
- tags,
582
+ tags: tags2,
583
583
  sdk: { name: "@hanzo/event", version: VERSION }
584
584
  };
585
585
  if (identity.userId) event.user = { id: identity.userId };
@@ -709,7 +709,7 @@ function ls() {
709
709
  function anonId() {
710
710
  return hzAnonId() || void 0;
711
711
  }
712
- function sessionId(now = Date.now()) {
712
+ function sessionId(now2 = Date.now()) {
713
713
  const s = ls();
714
714
  if (!s) return void 0;
715
715
  let state = null;
@@ -718,17 +718,17 @@ function sessionId(now = Date.now()) {
718
718
  } catch {
719
719
  state = null;
720
720
  }
721
- if (!state || now - state.last > SESSION_TTL_MS) {
722
- state = { id: hzUuidv7(now), last: now };
721
+ if (!state || now2 - state.last > SESSION_TTL_MS) {
722
+ state = { id: hzUuidv7(now2), last: now2 };
723
723
  } else {
724
- state.last = now;
724
+ state.last = now2;
725
725
  }
726
726
  s.setItem(KEY.session, JSON.stringify(state));
727
727
  return state.id;
728
728
  }
729
- function adoptSession(id, now = Date.now()) {
729
+ function adoptSession(id, now2 = Date.now()) {
730
730
  const s = ls();
731
- if (s) s.setItem(KEY.session, JSON.stringify({ id, last: now }));
731
+ if (s) s.setItem(KEY.session, JSON.stringify({ id, last: now2 }));
732
732
  }
733
733
  function adoptAnonId(id) {
734
734
  hzAnonAdopt(id);
@@ -814,10 +814,10 @@ function linkUrl(url, state, fromHost, base) {
814
814
  }
815
815
  if (u.protocol !== "https:" && u.protocol !== "http:") return url;
816
816
  if (!orgOf(u.hostname) || u.hostname === fromHost) return url;
817
- const set = (k, v) => v && u.searchParams.set(k, v);
818
- if (isId(state.anonId)) set(LINK_PARAMS.anon, state.anonId);
819
- if (isId(state.sessionId)) set(LINK_PARAMS.session, state.sessionId);
820
- if (state.firstTouch) set(LINK_PARAMS.firstTouch, encodeFirstTouch(state.firstTouch));
817
+ const set2 = (k, v) => v && u.searchParams.set(k, v);
818
+ if (isId(state.anonId)) set2(LINK_PARAMS.anon, state.anonId);
819
+ if (isId(state.sessionId)) set2(LINK_PARAMS.session, state.sessionId);
820
+ if (state.firstTouch) set2(LINK_PARAMS.firstTouch, encodeFirstTouch(state.firstTouch));
821
821
  return u.toString();
822
822
  }
823
823
  function readLink(search) {
@@ -1167,11 +1167,11 @@ var Analytics = class {
1167
1167
  * or publishable key is attached here — the two planes authenticate
1168
1168
  * independently. Errors are sent one envelope per event, immediately: batching
1169
1169
  * a crash report is how you lose it. */
1170
- sendError(err, options) {
1170
+ sendError(err, options2) {
1171
1171
  if (!this.cfg.enabled || !this.dsn) return;
1172
1172
  const event = buildSentryEvent({
1173
1173
  error: err,
1174
- options,
1174
+ options: options2,
1175
1175
  identity: this.errorIdentity(),
1176
1176
  capturePII: this.cfg.capturePII ?? false
1177
1177
  });
@@ -1258,16 +1258,16 @@ var Analytics = class {
1258
1258
  };
1259
1259
  var CLIENTS = /* @__PURE__ */ Symbol.for("hanzo.event.clients");
1260
1260
  function registry() {
1261
- const g = globalThis;
1262
- const existing = g[CLIENTS];
1261
+ const g2 = globalThis;
1262
+ const existing = g2[CLIENTS];
1263
1263
  if (existing) return existing;
1264
1264
  const fresh = /* @__PURE__ */ new Map();
1265
- g[CLIENTS] = fresh;
1265
+ g2[CLIENTS] = fresh;
1266
1266
  return fresh;
1267
1267
  }
1268
1268
  function resetClients() {
1269
- const g = globalThis;
1270
- delete g[CLIENTS];
1269
+ const g2 = globalThis;
1270
+ delete g2[CLIENTS];
1271
1271
  }
1272
1272
  function createAnalytics(config) {
1273
1273
  if (!isBrowser() || config.enabled === false) return new Analytics(config);
@@ -1283,6 +1283,455 @@ function createAnalytics(config) {
1283
1283
  return fresh;
1284
1284
  }
1285
1285
 
1286
+ // src/cookie.ts
1287
+ var DAY = 86400;
1288
+ function domain() {
1289
+ const h = window.location.hostname;
1290
+ if (h === "localhost" || /^[\d.]+$/.test(h) || h.includes(":")) return "";
1291
+ const parts = h.split(".");
1292
+ return parts.length > 2 ? `; Domain=.${parts.slice(-2).join(".")}` : `; Domain=.${h}`;
1293
+ }
1294
+ function get(name) {
1295
+ if (typeof document === "undefined") return void 0;
1296
+ const hit = document.cookie.split("; ").find((c) => c.startsWith(`${name}=`));
1297
+ return hit ? decodeURIComponent(hit.slice(name.length + 1)) : void 0;
1298
+ }
1299
+ function set(name, value, days) {
1300
+ if (typeof document === "undefined") return;
1301
+ const secure = window.location.protocol === "https:" ? "; Secure" : "";
1302
+ document.cookie = `${name}=${encodeURIComponent(value)}; Max-Age=${days * DAY}; Path=/; SameSite=Lax${domain()}${secure}`;
1303
+ }
1304
+
1305
+ // src/consent.ts
1306
+ var CONSENT_COOKIE = "hz_consent";
1307
+ var CONSENT_EVENT = "hzconsent";
1308
+ var US = /^(America\/(New_York|Chicago|Denver|Los_Angeles|Phoenix|Anchorage|Adak|Boise|Detroit|Juneau|Sitka|Nome|Yakutat|Menominee|Metlakatla|Indiana\/.*|Kentucky\/.*|North_Dakota\/.*)|Pacific\/Honolulu|US\/.*)$/;
1309
+ function gpc() {
1310
+ if (typeof navigator === "undefined") return false;
1311
+ return navigator.globalPrivacyControl === true;
1312
+ }
1313
+ function refused() {
1314
+ if (typeof window === "undefined") return false;
1315
+ const n = navigator;
1316
+ const dnt = n.doNotTrack ?? window.doNotTrack ?? n.msDoNotTrack;
1317
+ return gpc() || dnt === "1" || dnt === "yes";
1318
+ }
1319
+ function region() {
1320
+ try {
1321
+ const zone = Intl.DateTimeFormat().resolvedOptions().timeZone ?? "";
1322
+ return US.test(zone) ? "opt-out" : "opt-in";
1323
+ } catch {
1324
+ return "opt-in";
1325
+ }
1326
+ }
1327
+ function stored() {
1328
+ return get(CONSENT_COOKIE) !== void 0;
1329
+ }
1330
+ function read2() {
1331
+ const kept = get(CONSENT_COOKIE);
1332
+ const on = kept !== void 0 ? kept.split(",") : region() === "opt-in" || refused() ? [] : ["analytics", "marketing", "ads"];
1333
+ const has = (k) => on.includes(k);
1334
+ return { analytics: has("analytics"), marketing: has("marketing") && !gpc(), ads: has("ads") && !gpc() };
1335
+ }
1336
+ function asks() {
1337
+ return typeof document !== "undefined" && region() === "opt-in" && !stored();
1338
+ }
1339
+ function render(c) {
1340
+ return ["analytics", "marketing", "ads"].filter((k) => c[k]).join(",");
1341
+ }
1342
+ function save(c) {
1343
+ const out = { analytics: c.analytics, marketing: c.marketing && !gpc(), ads: c.ads && !gpc() };
1344
+ set(CONSENT_COOKIE, render(out), 395);
1345
+ if (typeof window !== "undefined") window.dispatchEvent(new Event(CONSENT_EVENT));
1346
+ }
1347
+ var acceptAll = () => save({ analytics: true, marketing: true, ads: true });
1348
+ var rejectAll = () => save({ analytics: false, marketing: false, ads: false });
1349
+
1350
+ // src/touch.ts
1351
+ var CLICK_IDS = ["gclid", "gbraid", "wbraid", "fbclid", "li_fat_id", "twclid", "ttclid"];
1352
+ var DAYS = 90;
1353
+ var now = () => Math.floor(Date.now() / 1e3);
1354
+ var rand = () => Math.floor(Math.random() * 2 ** 31);
1355
+ function capture(c) {
1356
+ if (typeof window === "undefined") return;
1357
+ if (c.marketing) {
1358
+ const q = new URLSearchParams(window.location.search);
1359
+ const click = {};
1360
+ for (const k of CLICK_IDS) {
1361
+ const v = q.get(k)?.trim();
1362
+ if (v) click[k] = v;
1363
+ }
1364
+ if (Object.keys(click).length) {
1365
+ click.clicked = now();
1366
+ set("hz_touch", JSON.stringify(click), DAYS);
1367
+ if (click.fbclid) set("_fbc", `fb.1.${Date.now()}.${click.fbclid}`, DAYS);
1368
+ }
1369
+ if (!get("_fbp")) set("_fbp", `fb.1.${Date.now()}.${rand()}`, DAYS);
1370
+ }
1371
+ if (c.analytics && !get("_ga") && !get("hz_cid")) set("hz_cid", `${rand()}.${now()}`, 730);
1372
+ }
1373
+ function touch(c) {
1374
+ const out = {};
1375
+ if (c.marketing) {
1376
+ try {
1377
+ Object.assign(out, JSON.parse(get("hz_touch") ?? "{}"));
1378
+ } catch {
1379
+ }
1380
+ const fbc = get("_fbc");
1381
+ const fbp = get("_fbp");
1382
+ if (fbc) out.fbc = fbc;
1383
+ if (fbp) out.fbp = fbp;
1384
+ }
1385
+ if (c.analytics) {
1386
+ const ga = get("_ga")?.split(".");
1387
+ const cid = ga && ga.length >= 4 ? ga.slice(-2).join(".") : get("hz_cid");
1388
+ if (cid) out.cid = cid;
1389
+ }
1390
+ return out;
1391
+ }
1392
+ var SITE_KEY = Object.freeze({
1393
+ "hanzo.ai": "pk-CmfLA2K6kvsPflrS9DSkt06H_kSoQB_21sjedt6VJdc",
1394
+ "www.hanzo.ai": "pk-CmfLA2K6kvsPflrS9DSkt06H_kSoQB_21sjedt6VJdc",
1395
+ "hanzo.app": "pk-wlnXN2a9_vmCm60yTFtQ629Q8TyuaxBNZbY1RWT72gQ",
1396
+ "hanzo.team": "pk-NCzD2FiHpZv8KUpkCX4olT1LJOJsMxBC_Z8NkiQsOFQ",
1397
+ "pay.hanzo.ai": "pk-eX6kv7JZNoiYn1WkeJH3tT_8OvkVYScmCXnLMwxTKf8",
1398
+ "platform.hanzo.ai": "pk-My1RpZLEUnTj8vAdPbWKYdDUuhxZJ4dVjHcwjZN4rZ8",
1399
+ "docs.hanzo.ai": "pk-jukhtjMT2ymoeBDAeFjINQWlBv-v9sNn1TPztiCrrwk",
1400
+ "hanzo.bot": "pk-W5d7Mn7ZukT7igyscIy6Pqe8JpA0Ge604Yn4xNR4JCU",
1401
+ "cloud.hanzo.ai": "pk-RAfEGHPoNdCEU9fnA_cPd_Xo9Tci44rlYQV9xuJ1Ob0"
1402
+ });
1403
+ var page = () => window;
1404
+ var tags = [];
1405
+ var configured = false;
1406
+ var options = {};
1407
+ var loaded = /* @__PURE__ */ new Set();
1408
+ var google = "idle";
1409
+ var configAnswered = false;
1410
+ var held = [];
1411
+ var leaving = false;
1412
+ function settled() {
1413
+ return configAnswered && google !== "wait";
1414
+ }
1415
+ function flush() {
1416
+ if (settled() || leaving) held.splice(0).forEach((send) => send());
1417
+ }
1418
+ function script(src, onload, onerror) {
1419
+ const s = document.createElement("script");
1420
+ s.async = true;
1421
+ s.src = src;
1422
+ if (onload) s.onload = onload;
1423
+ if (onerror) s.onerror = onerror;
1424
+ document.head.appendChild(s);
1425
+ }
1426
+ function gtagStub() {
1427
+ const p = page();
1428
+ p.dataLayer = p.dataLayer || [];
1429
+ if (!p.gtag) {
1430
+ p.gtag = function() {
1431
+ p.dataLayer.push(arguments);
1432
+ };
1433
+ }
1434
+ return p.gtag;
1435
+ }
1436
+ var g = (on) => on ? "granted" : "denied";
1437
+ function consentMode(c, first) {
1438
+ const gtag = gtagStub();
1439
+ const state = {
1440
+ analytics_storage: g(c.analytics),
1441
+ ad_storage: g(c.marketing),
1442
+ ad_user_data: g(c.marketing),
1443
+ ad_personalization: g(c.marketing && c.ads)
1444
+ };
1445
+ if (first) {
1446
+ gtag("consent", "default", {
1447
+ analytics_storage: "denied",
1448
+ ad_storage: "denied",
1449
+ ad_user_data: "denied",
1450
+ ad_personalization: "denied",
1451
+ wait_for_update: 500
1452
+ });
1453
+ }
1454
+ gtag("consent", "update", state);
1455
+ }
1456
+ function loadGoogle(ids) {
1457
+ const gtag = gtagStub();
1458
+ const fresh = ids.filter((id) => !loaded.has(id));
1459
+ if (!fresh.length) return;
1460
+ if (google === "idle") {
1461
+ google = "wait";
1462
+ gtag("js", /* @__PURE__ */ new Date());
1463
+ const done = (to) => () => {
1464
+ if (google !== "wait") return;
1465
+ google = to;
1466
+ flush();
1467
+ };
1468
+ script(`https://www.googletagmanager.com/gtag/js?id=${encodeURIComponent(fresh[0])}`, done("loaded"), done("failed"));
1469
+ setTimeout(done("failed"), 8e3);
1470
+ }
1471
+ for (const id of fresh) {
1472
+ loaded.add(id);
1473
+ gtag("config", id, options.domains ? { linker: { domains: options.domains } } : {});
1474
+ }
1475
+ }
1476
+ function loadMeta(id, c) {
1477
+ const p = page();
1478
+ if (!p.fbq) {
1479
+ const n = p.fbq = function(...a) {
1480
+ if (n.callMethod) n.callMethod(...a);
1481
+ else n.queue.push(a);
1482
+ };
1483
+ if (!p._fbq) p._fbq = n;
1484
+ n.push = n;
1485
+ n.loaded = true;
1486
+ n.version = "2.0";
1487
+ n.queue = [];
1488
+ script("https://connect.facebook.net/en_US/fbevents.js");
1489
+ }
1490
+ if (!c.ads) p.fbq("dataProcessingOptions", ["LDU"], 0, 0);
1491
+ p.fbq("init", id);
1492
+ p.fbq("track", "PageView");
1493
+ }
1494
+ function loadLinkedIn(id) {
1495
+ const p = page();
1496
+ p._linkedin_data_partner_ids = p._linkedin_data_partner_ids || [];
1497
+ p._linkedin_data_partner_ids.push(id);
1498
+ if (!p.lintrk) {
1499
+ const l = p.lintrk = function(...a) {
1500
+ l.q.push(a);
1501
+ };
1502
+ l.q = [];
1503
+ }
1504
+ script("https://snap.licdn.com/li.lms-analytics/insight.min.js");
1505
+ }
1506
+ function loadX(id) {
1507
+ const p = page();
1508
+ if (!p.twq) {
1509
+ const s = p.twq = function(...a) {
1510
+ if (s.exe) s.exe(...a);
1511
+ else s.queue.push(a);
1512
+ };
1513
+ s.version = "1.1";
1514
+ s.queue = [];
1515
+ script("https://static.ads-twitter.com/uwt.js");
1516
+ }
1517
+ p.twq("config", id);
1518
+ }
1519
+ var TIKTOK_METHODS = ["page", "track", "identify", "instances", "debug", "on", "off", "once", "ready", "alias", "group", "enableCookie", "disableCookie"];
1520
+ function loadTikTok(id) {
1521
+ const p = page();
1522
+ p.TiktokAnalyticsObject = "ttq";
1523
+ const q = p.ttq = p.ttq || [];
1524
+ if (!q._i) {
1525
+ q.methods = TIKTOK_METHODS;
1526
+ for (const m of TIKTOK_METHODS) q[m] = (...a) => q.push([m, ...a]);
1527
+ q._i = {};
1528
+ q._t = {};
1529
+ q._o = {};
1530
+ q.load = (sdk) => {
1531
+ q._i[sdk] = [];
1532
+ q._t[sdk] = Date.now();
1533
+ script(`https://analytics.tiktok.com/i18n/pixel/events.js?sdkid=${encodeURIComponent(sdk)}&lib=ttq`);
1534
+ };
1535
+ }
1536
+ q.load(id);
1537
+ q.page();
1538
+ }
1539
+ var NEEDS = {
1540
+ ga: "analytics",
1541
+ gads: "marketing",
1542
+ meta: "marketing",
1543
+ linkedin: "marketing",
1544
+ x: "marketing",
1545
+ tiktok: "marketing"
1546
+ };
1547
+ var allowed = (t, c) => t.type === "ga" ? c.analytics || c.marketing : Boolean(NEEDS[t.type] && c[NEEDS[t.type]]);
1548
+ function apply() {
1549
+ if (typeof window === "undefined" || !configured) return;
1550
+ const c = read2();
1551
+ capture(c);
1552
+ const on = tags.filter((t) => allowed(t, c));
1553
+ const ids = on.filter((t) => t.type === "ga" || t.type === "gads").map((t) => t.id);
1554
+ if (ids.length) {
1555
+ consentMode(c, !loaded.has("consent"));
1556
+ loaded.add("consent");
1557
+ loadGoogle(ids);
1558
+ }
1559
+ for (const t of on) {
1560
+ const k = `${t.type}:${t.id}`;
1561
+ if (loaded.has(k)) continue;
1562
+ if (t.type === "meta") loadMeta(t.id, c);
1563
+ else if (t.type === "linkedin") loadLinkedIn(t.id);
1564
+ else if (t.type === "x") loadX(t.id);
1565
+ else if (t.type === "tiktok") loadTikTok(t.id);
1566
+ else continue;
1567
+ loaded.add(k);
1568
+ }
1569
+ flush();
1570
+ }
1571
+ function start(o = {}) {
1572
+ if (typeof window === "undefined") return () => void 0;
1573
+ options = o;
1574
+ addEventListener(CONSENT_EVENT, apply);
1575
+ addEventListener("pagehide", pagehide);
1576
+ if (!configured) {
1577
+ configured = true;
1578
+ const base = (o.base ?? "https://api.hanzo.ai").replace(/\/$/, "");
1579
+ const q = new URLSearchParams();
1580
+ const host = o.host ?? window.location.hostname;
1581
+ const key = o.key ?? SITE_KEY[host];
1582
+ if (key) q.set("key", key);
1583
+ q.set("host", host);
1584
+ const answer = (list) => {
1585
+ tags = list;
1586
+ configAnswered = true;
1587
+ apply();
1588
+ };
1589
+ const cap = setTimeout(() => answer([]), 3e3);
1590
+ fetch(`${base}/v1/project/tags?${q}`).then((r) => r.ok ? r.json() : { tags: [] }).then((j) => {
1591
+ clearTimeout(cap);
1592
+ answer(Array.isArray(j.tags) ? j.tags : []);
1593
+ }).catch(() => {
1594
+ clearTimeout(cap);
1595
+ answer([]);
1596
+ });
1597
+ }
1598
+ return () => {
1599
+ removeEventListener(CONSENT_EVENT, apply);
1600
+ removeEventListener("pagehide", pagehide);
1601
+ };
1602
+ }
1603
+ function pagehide() {
1604
+ leaving = true;
1605
+ flush();
1606
+ }
1607
+ function reach() {
1608
+ const c = read2();
1609
+ const to = [];
1610
+ for (const t of tags) {
1611
+ if (!allowed(t, c)) continue;
1612
+ const running = t.type === "ga" ? google === "loaded" && c.analytics : t.type === "gads" ? google === "loaded" && c.marketing : loaded.has(`${t.type}:${t.id}`);
1613
+ if (running && !to.includes(t.type)) to.push(t.type);
1614
+ }
1615
+ return to.join(",");
1616
+ }
1617
+ var META_STANDARD = /* @__PURE__ */ new Set([
1618
+ "AddPaymentInfo",
1619
+ "AddToCart",
1620
+ "AddToWishlist",
1621
+ "CompleteRegistration",
1622
+ "Contact",
1623
+ "CustomizeProduct",
1624
+ "Donate",
1625
+ "FindLocation",
1626
+ "InitiateCheckout",
1627
+ "Lead",
1628
+ "Purchase",
1629
+ "Schedule",
1630
+ "Search",
1631
+ "StartTrial",
1632
+ "SubmitApplication",
1633
+ "Subscribe",
1634
+ "ViewContent"
1635
+ ]);
1636
+ function shape(platform, p) {
1637
+ const items = Array.isArray(p.items) ? p.items : [];
1638
+ const out = {};
1639
+ if (typeof p.value === "number") out.value = p.value;
1640
+ out.currency = typeof p.currency === "string" ? p.currency : "USD";
1641
+ if (!items.length) return out;
1642
+ if (platform === "meta") {
1643
+ out.content_type = "product";
1644
+ out.content_ids = items.map((i) => i.item_id);
1645
+ out.contents = items.map((i) => ({ id: i.item_id, quantity: i.quantity ?? 1, item_price: i.price }));
1646
+ out.content_name = items[0].item_name;
1647
+ out.num_items = items.reduce((n, i) => n + (i.quantity ?? 1), 0);
1648
+ } else if (platform === "tiktok") {
1649
+ out.content_type = "product";
1650
+ out.contents = items.map((i) => ({ content_id: i.item_id, content_name: i.item_name, quantity: i.quantity ?? 1, price: i.price }));
1651
+ } else {
1652
+ out.contents = items.map((i) => ({ content_id: i.item_id, content_name: i.item_name, content_price: i.price, num_items: i.quantity ?? 1 }));
1653
+ }
1654
+ return out;
1655
+ }
1656
+ function unpriced(p) {
1657
+ const out = { ...p, value: 0 };
1658
+ if (Array.isArray(p.items)) out.items = p.items.map((i) => ({ ...i, price: 0 }));
1659
+ return out;
1660
+ }
1661
+ function mirror(name, params, id, to = reach()) {
1662
+ const p = page();
1663
+ const on = new Set(to.split(",").filter(Boolean));
1664
+ const ga4 = namesOn(name, "ga4");
1665
+ const test = params.test === true;
1666
+ if (test) params = unpriced(params);
1667
+ const transaction = typeof params.order_id === "string" ? { transaction_id: params.order_id } : {};
1668
+ for (const t of tags) {
1669
+ if (!on.has(t.type)) continue;
1670
+ const rule = t.events?.[name];
1671
+ if (t.type === "ga") {
1672
+ for (const n of ga4) {
1673
+ p.gtag?.("event", n, { ...params, ...transaction, event_id: id, transport_type: "beacon", ...test ? { debug_mode: true } : {} });
1674
+ }
1675
+ } else if (t.type === "gads" && rule) {
1676
+ p.gtag?.("event", "conversion", {
1677
+ send_to: rule,
1678
+ value: typeof params.value === "number" ? params.value : void 0,
1679
+ currency: typeof params.currency === "string" ? params.currency : "USD",
1680
+ ...transaction
1681
+ });
1682
+ } else if (t.type === "meta") {
1683
+ for (const n of namesOn(name, "meta")) {
1684
+ p.fbq?.(META_STANDARD.has(n) ? "track" : "trackCustom", n, shape("meta", params), { eventID: id });
1685
+ }
1686
+ } else if (t.type === "tiktok") {
1687
+ for (const n of namesOn(name, "tiktok")) p.ttq?.track?.(n, shape("tiktok", params), { event_id: id });
1688
+ } else if (t.type === "linkedin" && rule && namesOn(name, "linkedin").length) {
1689
+ p.lintrk?.("track", { conversion_id: Number(rule) });
1690
+ } else if (t.type === "x" && rule && namesOn(name, "x").length) {
1691
+ p.twq?.("event", rule, { ...shape("x", params), conversion_id: id });
1692
+ }
1693
+ }
1694
+ }
1695
+ function track(stream, name, params = {}, only) {
1696
+ if (typeof window === "undefined") return;
1697
+ if (!leaving && !settled()) {
1698
+ held.push(() => track(stream, name, params, only));
1699
+ return;
1700
+ }
1701
+ const c = read2();
1702
+ const event_id = typeof params.event_id === "string" && params.event_id ? params.event_id : crypto.randomUUID();
1703
+ const to = reach();
1704
+ mirror(name, params, event_id, to);
1705
+ if (only === "tags") return;
1706
+ stream?.capture(name, {
1707
+ ...params,
1708
+ ...touch(c),
1709
+ event_id,
1710
+ consent: render(c),
1711
+ tags: to,
1712
+ userAgent: navigator.userAgent,
1713
+ url: window.location.href
1714
+ });
1715
+ }
1716
+ function visit() {
1717
+ const c = read2();
1718
+ return { ...touch(c), consent: render(c), tags: reach(), userAgent: navigator.userAgent, url: window.location.href };
1719
+ }
1720
+
1721
+ // src/items.ts
1722
+ function commerceItem(p) {
1723
+ const annual = /^(year|yearly|annual)$/i.test(p.interval);
1724
+ return {
1725
+ item_id: p.id,
1726
+ ...p.name ? { item_name: p.name } : {},
1727
+ item_category: p.team ? "team" : "individual",
1728
+ item_variant: annual ? "annual" : "monthly",
1729
+ price: p.price ?? 0,
1730
+ quantity: p.quantity ?? 1
1731
+ };
1732
+ }
1733
+ var worth = (i) => i.price * i.quantity;
1734
+
1286
1735
  // src/goals.ts
1287
1736
  var GOALS = {
1288
1737
  // Signup: the conversion is signup_completed, along the site signup funnel.
@@ -1343,6 +1792,6 @@ var COHORTS = {
1343
1792
  * curl -fsSL https://unpkg.com/@hanzo/event/src/anon.js -o apps/analytics/anon.js
1344
1793
  */
1345
1794
 
1346
- export { Analytics, COHORTS, GOALS, LINK_PARAMS, ORG_DOMAIN, ORG_KEY, PRODUCT_PROJECT, VERSION, buildEnvelope, buildSentryEvent, createAnalytics, deriveChannel, digest, dsnForProduct, exceptionEntry, exceptionProperties, fingerprint, framesFromStack, getCohort, getFirstTouch, hasAttribution, hostOf, isoWeek, keyFor, keyForPage, linkUrl, orgOf, parseAttribution, parseDsn, readLink, redactSecrets, resetClients, scrubPII, scrubText, stripLink, hzUuidv7 as uuidv7, uuidv7Time };
1795
+ export { Analytics, CLICK_IDS, COHORTS, CONSENT_COOKIE, CONSENT_EVENT, GOALS, LINK_PARAMS, ORG_DOMAIN, ORG_KEY, PRODUCT_PROJECT, SITE_KEY, VERSION, acceptAll, asks, buildEnvelope, buildSentryEvent, capture as captureClick, commerceItem, createAnalytics, deriveChannel, digest, dsnForProduct, exceptionEntry, exceptionProperties, fingerprint, framesFromStack, getCohort, getFirstTouch, gpc, hasAttribution, hostOf, isoWeek, keyFor, keyForPage, linkUrl, mirror, orgOf, parseAttribution, parseDsn, reach, read2 as readConsent, readLink, redactSecrets, refused, region, rejectAll, render as renderConsent, resetClients, save as saveConsent, scrubPII, scrubText, start as startTags, stored as storedConsent, stripLink, touch, track, hzUuidv7 as uuidv7, uuidv7Time, visit, worth };
1347
1796
  //# sourceMappingURL=index.mjs.map
1348
1797
  //# sourceMappingURL=index.mjs.map