@indiebob/tracker 0.3.0 → 0.4.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/dist/server.js CHANGED
@@ -2,12 +2,24 @@
2
2
 
3
3
  // src/core/config.ts
4
4
  var DEFAULT_ENDPOINT = "https://www.indiebob.com/api/collect";
5
+ var OPTIONS = "projectId endpoint debug respectDnt respectGpc autoDetect hashMode persistence";
6
+ var AUTO_OPTIONS = "signupPaths loginPaths pricingPaths checkoutPaths successPaths onboardingPaths contactPaths dataAttributes formSubmit outboundClicks fileDownloads";
7
+ function warnUnknown(obj, known, where) {
8
+ for (const k of Object.keys(obj)) {
9
+ if (!known.split(" ").includes(k)) console.warn(`[IndieBob] Unknown option ${where}"${k}" ignored`);
10
+ }
11
+ }
5
12
  function resolveConfig(input) {
6
13
  if (!input.projectId || !input.projectId.startsWith("proj_")) {
7
14
  throw new Error(
8
15
  `[IndieBob] Invalid projectId "${input.projectId}". Must start with "proj_".`
9
16
  );
10
17
  }
18
+ warnUnknown(input, OPTIONS, "");
19
+ if (typeof input.autoDetect === "object") warnUnknown(input.autoDetect, AUTO_OPTIONS, "autoDetect.");
20
+ if (input.persistence !== void 0 && input.persistence !== "local" && input.persistence !== "none") {
21
+ console.warn(`[IndieBob] persistence "${String(input.persistence)}" is not 'none' or 'local'; using 'none'`);
22
+ }
11
23
  return {
12
24
  projectId: input.projectId,
13
25
  endpoint: input.endpoint ?? DEFAULT_ENDPOINT,
@@ -15,7 +27,8 @@ function resolveConfig(input) {
15
27
  respectDnt: input.respectDnt ?? true,
16
28
  respectGpc: input.respectGpc ?? true,
17
29
  autoDetect: input.autoDetect ?? true,
18
- hashMode: input.hashMode ?? false
30
+ hashMode: input.hashMode ?? false,
31
+ persistence: input.persistence === "local" ? "local" : "none"
19
32
  };
20
33
  }
21
34
 
@@ -78,7 +91,7 @@ var IndieBobServer = class _IndieBobServer {
78
91
  device: { width: 0, height: 0, type: "desktop" },
79
92
  locale: "en",
80
93
  timezone: "UTC",
81
- sdkVersion: "0.3.0"
94
+ sdkVersion: "0.4.1"
82
95
  },
83
96
  event: extras.event,
84
97
  properties: extras.properties,
package/dist/server.mjs CHANGED
@@ -1,11 +1,23 @@
1
1
  // src/core/config.ts
2
2
  var DEFAULT_ENDPOINT = "https://www.indiebob.com/api/collect";
3
+ var OPTIONS = "projectId endpoint debug respectDnt respectGpc autoDetect hashMode persistence";
4
+ var AUTO_OPTIONS = "signupPaths loginPaths pricingPaths checkoutPaths successPaths onboardingPaths contactPaths dataAttributes formSubmit outboundClicks fileDownloads";
5
+ function warnUnknown(obj, known, where) {
6
+ for (const k of Object.keys(obj)) {
7
+ if (!known.split(" ").includes(k)) console.warn(`[IndieBob] Unknown option ${where}"${k}" ignored`);
8
+ }
9
+ }
3
10
  function resolveConfig(input) {
4
11
  if (!input.projectId || !input.projectId.startsWith("proj_")) {
5
12
  throw new Error(
6
13
  `[IndieBob] Invalid projectId "${input.projectId}". Must start with "proj_".`
7
14
  );
8
15
  }
16
+ warnUnknown(input, OPTIONS, "");
17
+ if (typeof input.autoDetect === "object") warnUnknown(input.autoDetect, AUTO_OPTIONS, "autoDetect.");
18
+ if (input.persistence !== void 0 && input.persistence !== "local" && input.persistence !== "none") {
19
+ console.warn(`[IndieBob] persistence "${String(input.persistence)}" is not 'none' or 'local'; using 'none'`);
20
+ }
9
21
  return {
10
22
  projectId: input.projectId,
11
23
  endpoint: input.endpoint ?? DEFAULT_ENDPOINT,
@@ -13,7 +25,8 @@ function resolveConfig(input) {
13
25
  respectDnt: input.respectDnt ?? true,
14
26
  respectGpc: input.respectGpc ?? true,
15
27
  autoDetect: input.autoDetect ?? true,
16
- hashMode: input.hashMode ?? false
28
+ hashMode: input.hashMode ?? false,
29
+ persistence: input.persistence === "local" ? "local" : "none"
17
30
  };
18
31
  }
19
32
 
@@ -76,7 +89,7 @@ var IndieBobServer = class _IndieBobServer {
76
89
  device: { width: 0, height: 0, type: "desktop" },
77
90
  locale: "en",
78
91
  timezone: "UTC",
79
- sdkVersion: "0.3.0"
92
+ sdkVersion: "0.4.1"
80
93
  },
81
94
  event: extras.event,
82
95
  properties: extras.properties,
package/dist/vue.cjs CHANGED
@@ -2,6 +2,13 @@
2
2
 
3
3
  // src/core/config.ts
4
4
  var DEFAULT_ENDPOINT = "https://www.indiebob.com/api/collect";
5
+ var OPTIONS = "projectId endpoint debug respectDnt respectGpc autoDetect hashMode persistence";
6
+ var AUTO_OPTIONS = "signupPaths loginPaths pricingPaths checkoutPaths successPaths onboardingPaths contactPaths dataAttributes formSubmit outboundClicks fileDownloads";
7
+ function warnUnknown(obj, known, where) {
8
+ for (const k of Object.keys(obj)) {
9
+ if (!known.split(" ").includes(k)) console.warn(`[IndieBob] Unknown option ${where}"${k}" ignored`);
10
+ }
11
+ }
5
12
  function resolveConfig(input) {
6
13
  var _a, _b, _c, _d, _e, _f;
7
14
  if (!input.projectId || !input.projectId.startsWith("proj_")) {
@@ -9,6 +16,11 @@ function resolveConfig(input) {
9
16
  `[IndieBob] Invalid projectId "${input.projectId}". Must start with "proj_".`
10
17
  );
11
18
  }
19
+ warnUnknown(input, OPTIONS, "");
20
+ if (typeof input.autoDetect === "object") warnUnknown(input.autoDetect, AUTO_OPTIONS, "autoDetect.");
21
+ if (input.persistence !== void 0 && input.persistence !== "local" && input.persistence !== "none") {
22
+ console.warn(`[IndieBob] persistence "${String(input.persistence)}" is not 'none' or 'local'; using 'none'`);
23
+ }
12
24
  return {
13
25
  projectId: input.projectId,
14
26
  endpoint: (_a = input.endpoint) != null ? _a : DEFAULT_ENDPOINT,
@@ -16,7 +28,8 @@ function resolveConfig(input) {
16
28
  respectDnt: (_c = input.respectDnt) != null ? _c : true,
17
29
  respectGpc: (_d = input.respectGpc) != null ? _d : true,
18
30
  autoDetect: (_e = input.autoDetect) != null ? _e : true,
19
- hashMode: (_f = input.hashMode) != null ? _f : false
31
+ hashMode: (_f = input.hashMode) != null ? _f : false,
32
+ persistence: input.persistence === "local" ? "local" : "none"
20
33
  };
21
34
  }
22
35
 
@@ -279,7 +292,6 @@ async function sendBatch(payload, config, isUnloading = false) {
279
292
  var OFFLINE_KEY = "_ib_queue";
280
293
  var MAX_BATCH = 10;
281
294
  var FLUSH_INTERVAL_MS = 5e3;
282
- var MAX_OFFLINE = 50;
283
295
  var EventQueue = class {
284
296
  /**
285
297
  * @param beforeHide runs right before the hide flush, so an event that
@@ -287,7 +299,9 @@ var EventQueue = class {
287
299
  */
288
300
  constructor(config, beforeHide) {
289
301
  this.b = [];
290
- this.i = false;
302
+ /** Failed events awaiting a retry, when nothing may be stored ('none'). */
303
+ this.j = [];
304
+ this.k = false;
291
305
  this.a = config;
292
306
  setInterval(() => {
293
307
  if (this.b.length > 0) void this.flush();
@@ -302,10 +316,10 @@ var EventQueue = class {
302
316
  });
303
317
  window.addEventListener("pagehide", hide);
304
318
  window.addEventListener("online", () => {
305
- void this.m();
319
+ void this.o();
306
320
  });
307
321
  if (navigator.onLine) {
308
- void this.m();
322
+ void this.o();
309
323
  }
310
324
  }
311
325
  push(event) {
@@ -315,32 +329,49 @@ var EventQueue = class {
315
329
  }
316
330
  }
317
331
  async flush(isUnloading = false) {
318
- if (this.i && !isUnloading) return;
332
+ if (this.k && !isUnloading) return;
319
333
  if (this.b.length === 0) return;
320
- this.i = true;
334
+ this.k = true;
321
335
  const batch = this.b.splice(0);
322
336
  const payload = { batch };
323
337
  const ok = await sendBatch(payload, this.a, isUnloading);
324
338
  if (!ok) {
325
- try {
326
- const trimmed = [...this.n(), ...batch].slice(-MAX_OFFLINE);
327
- localStorage.setItem(OFFLINE_KEY, JSON.stringify(trimmed));
328
- } catch (e) {
329
- }
339
+ this.t([...this.p(), ...batch].slice(-50));
330
340
  }
331
- this.i = false;
341
+ this.k = false;
332
342
  }
333
- async m() {
334
- const stored = this.n();
343
+ async o() {
344
+ const stored = this.p();
335
345
  if (stored.length === 0) return;
346
+ this.clearStored();
347
+ const payload = { batch: stored };
348
+ await sendBatch(payload, this.a);
349
+ }
350
+ /** Give events still waiting the ids they lacked (storage was just allowed). */
351
+ stamp(anonymousId, sessionId) {
352
+ for (const e of this.b) if (!e.anonymousId) Object.assign(e, { anonymousId, sessionId });
353
+ }
354
+ /** Drop the retry queue, wherever it is kept. */
355
+ clearStored() {
356
+ this.j = [];
336
357
  try {
337
358
  localStorage.removeItem(OFFLINE_KEY);
338
359
  } catch (e) {
339
360
  }
340
- const payload = { batch: stored };
341
- await sendBatch(payload, this.a);
342
361
  }
343
- n() {
362
+ /** In localStorage only with persistence 'local'; in memory otherwise. */
363
+ t(events) {
364
+ if (this.a.persistence !== "local") {
365
+ this.j = events;
366
+ return;
367
+ }
368
+ try {
369
+ localStorage.setItem(OFFLINE_KEY, JSON.stringify(events));
370
+ } catch (e) {
371
+ }
372
+ }
373
+ p() {
374
+ if (this.a.persistence !== "local") return this.j;
344
375
  try {
345
376
  const raw = localStorage.getItem(OFFLINE_KEY);
346
377
  if (!raw) return [];
@@ -351,9 +382,40 @@ var EventQueue = class {
351
382
  }
352
383
  };
353
384
 
385
+ // src/core/url.ts
386
+ var KEEP = /^(utm_\w+|ref)$/;
387
+ function cleanSearch(search) {
388
+ const out = new URLSearchParams();
389
+ new URLSearchParams(search).forEach((v, k) => {
390
+ if (KEEP.test(k)) out.append(k, v);
391
+ });
392
+ const s = out.toString();
393
+ return s ? "?" + s : "";
394
+ }
395
+ function cleanHash(hash) {
396
+ const route = hash.split("?")[0];
397
+ return route.includes("=") ? "" : route;
398
+ }
399
+ function cleanUrl(href, hashMode) {
400
+ try {
401
+ const u = new URL(href);
402
+ return u.origin + u.pathname + cleanSearch(u.search) + (hashMode ? cleanHash(u.hash) : "");
403
+ } catch (e) {
404
+ return "";
405
+ }
406
+ }
407
+ function cleanReferrer(ref) {
408
+ try {
409
+ const u = new URL(ref);
410
+ return u.origin + u.pathname;
411
+ } catch (e) {
412
+ return "";
413
+ }
414
+ }
415
+
354
416
  // src/collectors/page.ts
355
417
  function pagePath(loc, hashMode) {
356
- return loc.pathname + loc.search + (hashMode ? loc.hash : "");
418
+ return loc.pathname + cleanSearch(loc.search) + (hashMode ? cleanHash(loc.hash) : "");
357
419
  }
358
420
  function patchHistory(onNavigate, hashMode) {
359
421
  if (typeof window === "undefined") return () => {
@@ -379,9 +441,9 @@ function patchHistory(onNavigate, hashMode) {
379
441
 
380
442
  // src/collectors/context.ts
381
443
  var PAYMENT_HOST = /^https?:\/\/[^/]*(stripe\.com|paypal\.com|paddle\.com|lemonsqueezy\.com|gumroad\.com)(\/|$)/i;
382
- function buildContext(overrides, hashMode) {
383
- var _a, _b, _c, _d, _e, _f, _g, _h, _i;
384
- const sdkVersion = "0.3.0" ;
444
+ function buildContext(overrides, hashMode, local) {
445
+ var _a, _b, _c, _d, _e, _f, _g, _h;
446
+ const sdkVersion = "0.4.1" ;
385
447
  if (typeof window === "undefined") {
386
448
  return {
387
449
  page: { path: (_a = overrides == null ? void 0 : overrides.path) != null ? _a : "", url: "", title: (_b = overrides == null ? void 0 : overrides.title) != null ? _b : "", referrer: (_c = overrides == null ? void 0 : overrides.referrer) != null ? _c : "" },
@@ -396,18 +458,19 @@ function buildContext(overrides, hashMode) {
396
458
  return {
397
459
  page: {
398
460
  path: (_e = overrides == null ? void 0 : overrides.path) != null ? _e : pagePath(location, hashMode),
399
- url: location.href,
461
+ url: cleanUrl(location.href, hashMode),
400
462
  title: (_f = overrides == null ? void 0 : overrides.title) != null ? _f : document.title,
401
463
  // First touch survives the round trip: a /thanks page reached from Stripe
402
- // reports the referrer and UTM the visit STARTED with, not checkout.stripe.com
403
- // — otherwise every sale files itself under the payment host.
404
- referrer: liveReferrer === "" || PAYMENT_HOST.test(liveReferrer) ? (_g = getStoredReferrer()) != null ? _g : liveReferrer : liveReferrer
464
+ // reports the referrer the visit STARTED with (stored with 'local'), and
465
+ // never checkout.stripe.com — otherwise every sale files itself under the
466
+ // payment host. Without storage the server's visit already holds it.
467
+ referrer: cleanReferrer(liveReferrer === "" || PAYMENT_HOST.test(liveReferrer) ? local && getStoredReferrer() || "" : liveReferrer)
405
468
  },
406
469
  // Device class from the viewport width; still required by /api/collect
407
470
  device: { width, height: innerHeight, type: width <= 768 ? "mobile" : width <= 1024 ? "tablet" : "desktop" },
408
- utm: (_h = parseUtm(location.search)) != null ? _h : getStoredFirstUtm(),
471
+ utm: (_g = parseUtm(location.search)) != null ? _g : local ? getStoredFirstUtm() : void 0,
409
472
  locale: navigator.language,
410
- timezone: (_i = Intl.DateTimeFormat().resolvedOptions().timeZone) != null ? _i : "UTC",
473
+ timezone: (_h = Intl.DateTimeFormat().resolvedOptions().timeZone) != null ? _h : "UTC",
411
474
  sdkVersion
412
475
  };
413
476
  }
@@ -578,9 +641,9 @@ function trackEngagement() {
578
641
  window.addEventListener("scroll", sample);
579
642
  reset();
580
643
  return {
581
- r: sample,
582
- s: reset,
583
- t(measure) {
644
+ u: sample,
645
+ w: reset,
646
+ x(measure) {
584
647
  if (measure) sample();
585
648
  tick();
586
649
  if (!shouldSendEngagement(ms, scroll, sent)) return null;
@@ -599,17 +662,17 @@ function unseen() {
599
662
  }
600
663
  var IndieBob = class _IndieBob {
601
664
  constructor(config) {
602
- this.f = null;
603
- this.k = null;
604
665
  this.g = null;
666
+ this.m = null;
667
+ this.h = null;
605
668
  /** Engagement meter for the current page (browser only). */
606
- this.d = null;
669
+ this.e = null;
607
670
  /** Context of the page last counted — what an engagement event describes. */
608
- this.l = null;
671
+ this.n = null;
609
672
  /** A first pageview waiting for the tab to become visible. */
610
- this.h = false;
673
+ this.i = false;
611
674
  this.a = config;
612
- this.b = new EventQueue(config, () => this.q(true));
675
+ this.b = new EventQueue(config, () => this.s(true));
613
676
  if (typeof window !== "undefined") {
614
677
  try {
615
678
  if (applyIgnore(window.location.search, localStorage)) {
@@ -617,17 +680,17 @@ var IndieBob = class _IndieBob {
617
680
  }
618
681
  } catch (e) {
619
682
  }
620
- initAttribution(window.location.search, document.referrer);
621
- this.d = trackEngagement();
683
+ if (this.c && isTrackingAllowed(config)) initAttribution(window.location.search, document.referrer);
684
+ this.e = trackEngagement();
622
685
  window.addEventListener("pageshow", (e) => {
623
- if (e.persisted && this.e !== void 0) {
624
- this.e = void 0;
625
- this.page(this.o);
686
+ if (e.persisted && this.f !== void 0) {
687
+ this.f = void 0;
688
+ this.page(this.q);
626
689
  }
627
690
  });
628
691
  if (config.autoDetect !== false) {
629
692
  const opts = typeof config.autoDetect === "object" ? config.autoDetect : {};
630
- this.k = initClickTracking(
693
+ this.m = initClickTracking(
631
694
  (event, properties) => this.track(event, properties),
632
695
  opts.dataAttributes !== false,
633
696
  opts.fileDownloads !== false,
@@ -662,14 +725,14 @@ var IndieBob = class _IndieBob {
662
725
  page(overrides) {
663
726
  var _a;
664
727
  if (!isTrackingAllowed(this.a)) return;
665
- if (this.e === void 0 && unseen()) {
666
- this.p = overrides;
667
- if (!this.h) {
668
- this.h = true;
728
+ if (this.f === void 0 && unseen()) {
729
+ this.r = overrides;
730
+ if (!this.i) {
731
+ this.i = true;
669
732
  const go = () => {
670
- if (this.h && !unseen()) {
671
- this.h = false;
672
- this.page(this.p);
733
+ if (this.i && !unseen()) {
734
+ this.i = false;
735
+ this.page(this.r);
673
736
  }
674
737
  };
675
738
  document.addEventListener("visibilitychange", go);
@@ -677,34 +740,34 @@ var IndieBob = class _IndieBob {
677
740
  }
678
741
  return;
679
742
  }
680
- const ctx = buildContext(overrides, this.a.hashMode);
681
- if (ctx.page.path === this.e) return;
682
- this.q(false);
683
- this.e = ctx.page.path;
684
- this.o = overrides;
685
- this.l = ctx;
686
- if (this.d) {
687
- this.d.s();
688
- setTimeout(this.d.r, 1e3);
743
+ const ctx = buildContext(overrides, this.a.hashMode, this.c);
744
+ if (ctx.page.path === this.f) return;
745
+ this.s(false);
746
+ this.f = ctx.page.path;
747
+ this.q = overrides;
748
+ this.n = ctx;
749
+ if (this.e) {
750
+ this.e.w();
751
+ setTimeout(this.e.u, 1e3);
689
752
  }
690
- this.b.push(this.c("page", { context: ctx }));
753
+ this.b.push(this.d("page", { context: ctx }));
691
754
  if (this.a.autoDetect !== false) {
692
755
  const path = ctx.page.path;
693
756
  const opts = typeof this.a.autoDetect === "object" ? this.a.autoDetect : {};
694
757
  const intent = detectIntent(path, opts);
695
758
  if (intent) {
696
- this.b.push(this.c("track", {
759
+ this.b.push(this.d("track", {
697
760
  event: intent,
698
761
  properties: { auto: true },
699
762
  context: ctx
700
763
  }));
701
764
  log(this.a, `auto-detected: ${intent} on ${path}`);
702
765
  if (opts.formSubmit !== false) {
703
- (_a = this.g) == null ? void 0 : _a.call(this);
766
+ (_a = this.h) == null ? void 0 : _a.call(this);
704
767
  const submitEvent = intentToSubmitEvent(intent);
705
768
  if (submitEvent) {
706
- this.g = observeFormSubmits(submitEvent, (eventName) => {
707
- this.b.push(this.c("track", {
769
+ this.h = observeFormSubmits(submitEvent, (eventName) => {
770
+ this.b.push(this.d("track", {
708
771
  event: eventName,
709
772
  properties: { auto: true }
710
773
  }));
@@ -724,7 +787,7 @@ var IndieBob = class _IndieBob {
724
787
  */
725
788
  track(event, properties) {
726
789
  if (!isTrackingAllowed(this.a)) return;
727
- this.b.push(this.c("track", { event, properties }));
790
+ this.b.push(this.d("track", { event, properties }));
728
791
  }
729
792
  /**
730
793
  * Associate the current anonymous visitor with a known user ID.
@@ -749,18 +812,19 @@ var IndieBob = class _IndieBob {
749
812
  */
750
813
  identify(userId, traits, options) {
751
814
  if (!isTrackingAllowed(this.a)) return;
752
- this.j = userId;
753
- this.b.push(this.c("identify", { traits, userId }));
754
- if (this.a.autoDetect !== false) {
755
- const first = typeof (options == null ? void 0 : options.isNew) === "boolean" ? options.isNew : isFirstIdentify();
815
+ this.l = userId;
816
+ this.b.push(this.d("identify", { traits, userId }));
817
+ const known = typeof (options == null ? void 0 : options.isNew) === "boolean";
818
+ if (this.a.autoDetect !== false && (known || this.c)) {
819
+ const first = known ? options.isNew : isFirstIdentify();
756
820
  const eventName = first ? "signup" : "login";
757
- this.b.push(this.c("track", {
821
+ this.b.push(this.d("track", {
758
822
  event: eventName,
759
823
  // `auto` says where the verdict came from, so a funnel that looks
760
824
  // wrong later can be traced to a guess rather than to the server.
761
- properties: { auto: typeof (options == null ? void 0 : options.isNew) !== "boolean" }
825
+ properties: { auto: !known }
762
826
  }));
763
- markIdentified();
827
+ if (this.c) markIdentified();
764
828
  log(this.a, `${eventName} for ${userId}`);
765
829
  }
766
830
  }
@@ -773,7 +837,7 @@ var IndieBob = class _IndieBob {
773
837
  revenue(data) {
774
838
  var _a;
775
839
  if (!isTrackingAllowed(this.a)) return;
776
- this.b.push(this.c("revenue", {
840
+ this.b.push(this.d("revenue", {
777
841
  revenue: {
778
842
  amount: data.amount,
779
843
  currency: (_a = data.currency) != null ? _a : "USD",
@@ -791,11 +855,11 @@ var IndieBob = class _IndieBob {
791
855
  void this.b.flush();
792
856
  optOut();
793
857
  clearIdentified();
794
- this.j = void 0;
795
- (_a = this.k) == null ? void 0 : _a.call(this);
796
- (_b = this.g) == null ? void 0 : _b.call(this);
797
- this.k = null;
798
- this.g = null;
858
+ this.l = void 0;
859
+ (_a = this.m) == null ? void 0 : _a.call(this);
860
+ (_b = this.h) == null ? void 0 : _b.call(this);
861
+ this.m = null;
862
+ this.h = null;
799
863
  log(this.a, "opted out");
800
864
  }
801
865
  /** Re-enable tracking after optOut(). */
@@ -818,13 +882,42 @@ var IndieBob = class _IndieBob {
818
882
  async flush() {
819
883
  await this.b.flush();
820
884
  }
821
- /** Get the current anonymous ID. */
885
+ /** The stored anonymous ID with `persistence: 'local'`; '' without storage. */
822
886
  getAnonymousId() {
823
- return getAnonymousId();
887
+ return this.c ? getAnonymousId() : "";
824
888
  }
825
- /** Get the current session ID. */
889
+ /** The stored session ID with `persistence: 'local'`; '' without storage. */
826
890
  getSessionId() {
827
- return getSessionId();
891
+ return this.c ? getSessionId() : "";
892
+ }
893
+ /**
894
+ * Switch storage on or off — call it from your consent banner.
895
+ * `'local'` starts storing the visitor id and first-touch attribution from
896
+ * this page on; `'none'` removes everything the tracker stored.
897
+ *
898
+ * @example
899
+ * onConsent(() => bob.setPersistence('local'))
900
+ * onConsentWithdrawn(() => bob.setPersistence('none'))
901
+ */
902
+ setPersistence(mode) {
903
+ if (mode !== "local" && mode !== "none") return;
904
+ this.a.persistence = mode;
905
+ if (mode === "local") {
906
+ if (typeof window !== "undefined" && isTrackingAllowed(this.a)) {
907
+ initAttribution(location.search, document.referrer);
908
+ this.b.stamp(getAnonymousId(), getSessionId());
909
+ }
910
+ } else {
911
+ clearAnonymousId();
912
+ clearSession();
913
+ clearAttribution();
914
+ clearIdentified();
915
+ this.b.clearStored();
916
+ }
917
+ log(this.a, `persistence: ${mode}`);
918
+ }
919
+ get c() {
920
+ return this.a.persistence === "local";
828
921
  }
829
922
  /** Get the resolved configuration (read-only). */
830
923
  getConfig() {
@@ -840,12 +933,12 @@ var IndieBob = class _IndieBob {
840
933
  */
841
934
  enableAutoPage() {
842
935
  var _a;
843
- (_a = this.f) == null ? void 0 : _a.call(this);
844
- this.f = patchHistory(() => this.page(), this.a.hashMode);
936
+ (_a = this.g) == null ? void 0 : _a.call(this);
937
+ this.g = patchHistory(() => this.page(), this.a.hashMode);
845
938
  return () => {
846
939
  var _a2;
847
- (_a2 = this.f) == null ? void 0 : _a2.call(this);
848
- this.f = null;
940
+ (_a2 = this.g) == null ? void 0 : _a2.call(this);
941
+ this.g = null;
849
942
  };
850
943
  }
851
944
  /**
@@ -853,14 +946,14 @@ var IndieBob = class _IndieBob {
853
946
  * worth sending. `measure`: sample the scroll first (false on an SPA
854
947
  * change, when the DOM already shows the next page).
855
948
  */
856
- q(measure) {
949
+ s(measure) {
857
950
  var _a;
858
- const reading = this.l && ((_a = this.d) == null ? void 0 : _a.t(measure));
951
+ const reading = this.n && ((_a = this.e) == null ? void 0 : _a.x(measure));
859
952
  if (reading && isTrackingAllowed(this.a)) {
860
- this.b.push(this.c("engagement", { context: this.l, engagement: reading }));
953
+ this.b.push(this.d("engagement", { context: this.n, engagement: reading }));
861
954
  }
862
955
  }
863
- c(type, extras) {
956
+ d(type, extras) {
864
957
  var _a, _b;
865
958
  return {
866
959
  ...extras,
@@ -868,11 +961,11 @@ var IndieBob = class _IndieBob {
868
961
  id: generateId(),
869
962
  projectId: this.a.projectId,
870
963
  type,
871
- anonymousId: getAnonymousId(),
872
- userId: (_a = this.j) != null ? _a : extras.userId,
873
- sessionId: getSessionId(),
964
+ // Without storage the server derives both from its daily hash
965
+ ...this.c ? { anonymousId: getAnonymousId(), sessionId: getSessionId() } : {},
966
+ userId: (_a = this.l) != null ? _a : extras.userId,
874
967
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
875
- context: (_b = extras.context) != null ? _b : buildContext(void 0, this.a.hashMode)
968
+ context: (_b = extras.context) != null ? _b : buildContext(void 0, this.a.hashMode, this.c)
876
969
  };
877
970
  }
878
971
  };
@@ -1,3 +1,3 @@
1
- var IndieBob=(function(exports){'use strict';var it="https://www.indiebob.com/api/collect";function O(e){if(!e.projectId||!e.projectId.startsWith("proj_"))throw new Error(`[IndieBob] Invalid projectId "${e.projectId}". Must start with "proj_".`);return {projectId:e.projectId,endpoint:e.endpoint??it,debug:e.debug??false,respectDnt:e.respectDnt??true,respectGpc:e.respectGpc??true,autoDetect:e.autoDetect??true,hashMode:e.hashMode??false}}var l="_ib_anon";function u(){let e="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-",t=new Uint8Array(21);if(typeof crypto<"u"&&crypto.getRandomValues)crypto.getRandomValues(t);else for(let o=0;o<21;o++)t[o]=Math.random()*64;let n="";for(let o of t)n+=e[o&63];return n}function b(){try{let e=localStorage.getItem(l);return e||(e=u(),localStorage.setItem(l,e)),e}catch{try{let e=sessionStorage.getItem(l);return e||(e=u(),sessionStorage.setItem(l,e)),e}catch{return u()}}}function A(){try{localStorage.removeItem(l);}catch{}try{sessionStorage.removeItem(l);}catch{}}var I="_ib_session",E="_ib_session_last",st=1800*1e3;function D(){try{return crypto.randomUUID()}catch{return u()}}function S(){try{let e=Date.now(),t=parseInt(sessionStorage.getItem(E)??"0",10),n=sessionStorage.getItem(I),o=t>0&&e-t>st;return (!n||o)&&(n=D(),sessionStorage.setItem(I,n)),sessionStorage.setItem(E,String(e)),n}catch{return D()}}function N(){try{sessionStorage.removeItem(I);}catch{}try{sessionStorage.removeItem(E);}catch{}}var g="_ib_first_utm",M="_ib_last_utm",m="_ib_referrer";function w(e){let t=new URLSearchParams(e),n={},o=false;!t.has("utm_source")&&t.get("ref")&&(n.source=t.get("ref"),o=true);for(let r of ["source","medium","campaign","term","content"])t.has("utm_"+r)&&(n[r]=t.get("utm_"+r),o=true);return o?n:null}function L(e,t){let n=w(e);try{n&&!localStorage.getItem(g)&&localStorage.setItem(g,JSON.stringify(n)),n&&localStorage.setItem(M,JSON.stringify(n)),t&&!localStorage.getItem(m)&&localStorage.setItem(m,t);}catch{}}function U(){try{let e=localStorage.getItem(g);return e?JSON.parse(e):void 0}catch{return}}function F(){try{return localStorage.getItem(m)??void 0}catch{return}}function j(){try{localStorage.removeItem(g);}catch{}try{localStorage.removeItem(M);}catch{}try{localStorage.removeItem(m);}catch{}}var f="ib_ignore";function K(e,t){let n=new URLSearchParams(e).get(f);return n==="1"?t.setItem(f,"1"):n==="0"&&t.removeItem(f),t.getItem(f)==="1"}function _(){try{return localStorage.getItem(f)==="1"}catch{return false}}function B(){return typeof navigator<"u"&&navigator.webdriver===true||_()}var h="_ib_optout",at="_ib_queue";function d(e){if(B())return false;try{if(localStorage.getItem(h))return !1}catch{}return !(e.respectDnt&&typeof navigator<"u"&&(navigator.doNotTrack==="1"||navigator.msDoNotTrack==="1")||e.respectGpc&&typeof navigator<"u"&&navigator.globalPrivacyControl===true)}function Y(){try{localStorage.setItem(h,"1");}catch{}A(),N(),j();try{localStorage.removeItem(at);}catch{}}function z(){try{localStorage.removeItem(h);}catch{}}function $(){try{return !!localStorage.getItem(h)}catch{return false}}function a(e,...t){e.debug&&console.log("[IndieBob]",...t);}async function x(e,t,n=false){let o=JSON.stringify(e);if(n&&typeof navigator<"u"&&navigator.sendBeacon){let r=new Blob([o],{type:"text/plain;charset=UTF-8"}),i=navigator.sendBeacon(t.endpoint,r);return a(t,"sendBeacon:",i,e.batch.length,"events"),i}for(let r=0;r<3;r++){try{let i=await fetch(t.endpoint,{method:"POST",headers:{"Content-Type":"application/json"},body:o,keepalive:!0});if(i.ok)return a(t,"sent:",e.batch.length,"events"),!0;if(i.status>=400&&i.status<500)return a(t,"4xx error, not retrying:",i.status),!1}catch(i){a(t,"fetch error (attempt",r+1,"):",i);}r<2&&await new Promise(i=>setTimeout(i,1e3<<r));}return a(t,"failed to send after",3,"attempts"),false}var k="_ib_queue",ct=10,ut=5e3,lt=50,v=class{constructor(t,n){this.e=[];this.c=false;if(this.t=t,setInterval(()=>{this.e.length>0&&this.flush();},ut),typeof window>"u")return;let o=()=>{n?.(),this.flush(true);};document.addEventListener("visibilitychange",()=>{document.visibilityState==="hidden"&&o();}),window.addEventListener("pagehide",o),window.addEventListener("online",()=>{this.p();}),navigator.onLine&&this.p();}push(t){this.e.push(t),this.e.length>=ct&&this.flush();}async flush(t=false){if(this.c&&!t||this.e.length===0)return;this.c=true;let n=this.e.splice(0);if(!await x({batch:n},this.t,t))try{let i=[...this.f(),...n].slice(-lt);localStorage.setItem(k,JSON.stringify(i));}catch{}this.c=false;}async p(){let t=this.f();if(t.length===0)return;try{localStorage.removeItem(k);}catch{}await x({batch:t},this.t);}f(){try{let t=localStorage.getItem(k);return t?JSON.parse(t):[]}catch{return []}}};function X(e,t){return e.pathname+e.search+(t?e.hash:"")}function H(e,t){if(typeof window>"u")return ()=>{};let n=history.pushState.bind(history),o=history.replaceState.bind(history);return history.pushState=function(...r){n(...r),e();},history.replaceState=function(...r){o(...r);},window.addEventListener("popstate",e),t&&window.addEventListener("hashchange",e),()=>{history.pushState=n,history.replaceState=o,window.removeEventListener("popstate",e),window.removeEventListener("hashchange",e);}}var dt=/^https?:\/\/[^/]*(stripe\.com|paypal\.com|paddle\.com|lemonsqueezy\.com|gumroad\.com)(\/|$)/i;function T(e,t){let n="0.3.0";if(typeof window>"u")return {page:{path:e?.path??"",url:"",title:e?.title??"",referrer:e?.referrer??""},device:{width:0,height:0,type:"desktop"},locale:"en",timezone:"UTC",sdkVersion:n};let o=e?.referrer??document.referrer,r=innerWidth;return {page:{path:e?.path??X(location,t),url:location.href,title:e?.title??document.title,referrer:o===""||dt.test(o)?F()??o:o},device:{width:r,height:innerHeight,type:r<=768?"mobile":r<=1024?"tablet":"desktop"},utm:w(location.search)??U(),locale:navigator.language,timezone:Intl.DateTimeFormat().resolvedOptions().timeZone??"UTC",sdkVersion:n}}var pt=[["signup","signup_start",/\/(sign-?up|register|join|create-?account|get-?started|onboard|registro|inscription|s-?inscrire|anmeldung|registrieren|cadastro|registrazione|aanmelden|inschrijven)/i],["login","login_view",/\/(log-?in|sign-?in|auth(\/login)?|iniciar-?sesion|connexion|se-?connecter|anmelden|einloggen|entrar|accesso|accedi|inloggen)/i],["pricing","pricing_view",/\/(pricing|plans|upgrade|subscribe|precios|tarifs|preise|precos|prezzi|prijzen)/i],["checkout","checkout_view",/\/(checkout|cart|basket|pay(ment)?|order|comprar|pagar|panier|caisse|warenkorb|kasse|carrinho|carrello|winkelwagen)/i],["success","success_view",/\/(success|thank-?you|thanks|confirmation|confirmed|complete[d]?|gracias|merci|danke|obrigado|grazie|bedankt)/i],["onboarding","onboarding_view",/\/(onboarding|welcome|getting-?started|setup|bienvenido|bienvenue|willkommen|benvenuto|welkom)/i],["contact","contact_view",/\/(contact|contacto|kontakt|contato|contatto|nous-?contacter)/i]];function ft(e,t){return e instanceof RegExp?e.test(t):t.includes(e)}function V(e,t){for(let[n,o,r]of pt)if((t?.[`${n}Paths`]??[r]).some(c=>ft(c,e)))return o;return null}function G(e){let t=/^(signup|login|checkout)_/.exec(e);return t?t[1]+"_submit":null}function J(e,t){if(typeof document>"u")return ()=>{};let n=o=>{o.target instanceof HTMLFormElement&&t(e);};return document.addEventListener("submit",n,true),()=>document.removeEventListener("submit",n,true)}var R="ib_identified";function W(){return typeof localStorage>"u"?true:!localStorage.getItem(R)}function q(){typeof localStorage>"u"||localStorage.setItem(R,"1");}function Q(){typeof localStorage>"u"||localStorage.removeItem(R);}var Z="data-ib-event",tt="data-ib-";function et(e){for(;e&&e!==document.body;){let t=e.getAttribute(Z);if(t){let n={auto:true};for(let o of e.attributes)o.name.startsWith(tt)&&o.name!==Z&&(n[o.name.slice(tt.length)]=o.value);return [t,n]}e=e.parentElement;}return null}var gt=/\.(pdf|zip|dmg|exe|msi|pkg|apk|ipa|deb|rpm|appimage|t?gz|bz2|xz|tar|7z|rar|csv|xlsx?|docx?|pptx?|txt|epub|mp3|wav|mp4|mov|iso)$/i;function mt(e){let t=gt.exec(e);return t?t[1].toLowerCase():null}function ht(e,t,n,o){if(!/^https?:\/\//i.test(e))return null;try{let r=new URL(e),i=n&&mt(r.pathname);if(i)return ["file_download",{auto:!0,url:r.origin+r.pathname,path:r.pathname,ext:i}];if(o&&r.hostname!==t)return ["outbound_click",{auto:!0,url:e,hostname:r.hostname}]}catch{}return null}function nt(e,t,n,o){if(typeof document>"u")return ()=>{};let r=i=>{let c=i.target,s=c?.closest?.("a");for(let p of [t&&et(c),s&&ht(s.href,location.hostname,n,o)])p&&e(p[0],p[1]);};return document.addEventListener("click",r,true),()=>document.removeEventListener("click",r,true)}function vt(e,t,n){return t>n||e>=3e3}function yt(e,t,n){return n>0?Math.min(100,Math.round((e+t)/n*100)):0}function ot(){let e=0,t=0,n=0,o=0,r=()=>{let s=Date.now();t&&(e+=s-t),t=document.visibilityState==="visible"&&document.hasFocus()?s:0;},i=()=>{n=Math.max(n,yt(scrollY,innerHeight,Math.max(document.documentElement.scrollHeight,document.body?.scrollHeight??0)));},c=()=>{e=n=o=t=0,r();};for(let s of ["focus","blur"])window.addEventListener(s,r);return document.addEventListener("visibilitychange",r),window.addEventListener("scroll",i),c(),{y:i,b:c,I(s){if(s&&i(),r(),!vt(e,n,o))return null;let p={ms:Math.min(e,864e5),scroll:n};return e=0,o=n,p}}}var C={};function rt(){return typeof document<"u"&&(document.visibilityState==="hidden"||document.prerendering===true)}var y=class e{constructor(t){this.i=null;this.l=null;this.s=null;this.o=null;this.d=null;this.a=false;if(this.t=t,this.e=new v(t,()=>this.h(true)),typeof window<"u"){try{K(window.location.search,localStorage)&&console.info("IndieBob: this browser is excluded from analytics (ib_ignore)");}catch{}if(L(window.location.search,document.referrer),this.o=ot(),window.addEventListener("pageshow",n=>{n.persisted&&this.r!==void 0&&(this.r=void 0,this.page(this.g));}),t.autoDetect!==false){let n=typeof t.autoDetect=="object"?t.autoDetect:{};this.l=nt((o,r)=>this.track(o,r),n.dataAttributes!==false,n.fileDownloads!==false,n.outboundClicks!==false);}}}static init(t){var o;let n=O(t);return typeof window>"u"?new e(n):C[o=n.projectId]??(C[o]=new e(n))}page(t){if(!d(this.t))return;if(this.r===void 0&&rt()){if(this.m=t,!this.a){this.a=true;let o=()=>{this.a&&!rt()&&(this.a=false,this.page(this.m));};document.addEventListener("visibilitychange",o),document.addEventListener("prerenderingchange",o);}return}let n=T(t,this.t.hashMode);if(n.page.path!==this.r&&(this.h(false),this.r=n.page.path,this.g=t,this.d=n,this.o&&(this.o.b(),setTimeout(this.o.y,1e3)),this.e.push(this.n("page",{context:n})),this.t.autoDetect!==false)){let o=n.page.path,r=typeof this.t.autoDetect=="object"?this.t.autoDetect:{},i=V(o,r);if(i&&(this.e.push(this.n("track",{event:i,properties:{auto:true},context:n})),a(this.t,`auto-detected: ${i} on ${o}`),r.formSubmit!==false)){this.s?.();let c=G(i);c&&(this.s=J(c,s=>{this.e.push(this.n("track",{event:s,properties:{auto:true}})),a(this.t,`auto-detected: ${s}`);}));}}}track(t,n){d(this.t)&&this.e.push(this.n("track",{event:t,properties:n}));}identify(t,n,o){if(d(this.t)&&(this.u=t,this.e.push(this.n("identify",{traits:n,userId:t})),this.t.autoDetect!==false)){let i=(typeof o?.isNew=="boolean"?o.isNew:W())?"signup":"login";this.e.push(this.n("track",{event:i,properties:{auto:typeof o?.isNew!="boolean"}})),q(),a(this.t,`${i} for ${t}`);}}revenue(t){d(this.t)&&this.e.push(this.n("revenue",{revenue:{amount:t.amount,currency:t.currency??"USD",plan:t.plan,type:t.type}}));}optOut(){this.e.flush(),Y(),Q(),this.u=void 0,this.l?.(),this.s?.(),this.l=null,this.s=null,a(this.t,"opted out");}optIn(){z(),a(this.t,"opted in");}isOptedOut(){return $()}isIgnored(){return _()}async flush(){await this.e.flush();}getAnonymousId(){return b()}getSessionId(){return S()}getConfig(){return Object.freeze({...this.t})}enableAutoPage(){return this.i?.(),this.i=H(()=>this.page(),this.t.hashMode),()=>{this.i?.(),this.i=null;}}h(t){let n=this.d&&this.o?.I(t);n&&d(this.t)&&this.e.push(this.n("engagement",{context:this.d,engagement:n}));}n(t,n){return {...n,v:1,id:u(),projectId:this.t.projectId,type:t,anonymousId:b(),userId:this.u??n.userId,sessionId:S(),timestamp:new Date().toISOString(),context:n.context??T(void 0,this.t.hashMode)}}};var bt=Symbol("indiebob"),P=null,re={install(e,t){let n=y.init(t);P=n,e.provide(bt,n),e.config.globalProperties.$bob=n;let o=e.config.globalProperties.$router;o&&o.afterEach(()=>{n.page();});}};function ie(){if(P)return P;throw new Error("[IndieBob] useTracker() called before IndieBobPlugin was installed.")}
2
- exports.IndieBob=y;exports.IndieBobPlugin=re;exports.useTracker=ie;return exports;})({});
1
+ var IndieBob=(function(exports){'use strict';var lt="https://www.indiebob.com/api/collect",dt="projectId endpoint debug respectDnt respectGpc autoDetect hashMode persistence",pt="signupPaths loginPaths pricingPaths checkoutPaths successPaths onboardingPaths contactPaths dataAttributes formSubmit outboundClicks fileDownloads";function j(e,t,n){for(let o of Object.keys(e))t.split(" ").includes(o)||console.warn(`[IndieBob] Unknown option ${n}"${o}" ignored`);}function F(e){if(!e.projectId||!e.projectId.startsWith("proj_"))throw new Error(`[IndieBob] Invalid projectId "${e.projectId}". Must start with "proj_".`);return j(e,dt,""),typeof e.autoDetect=="object"&&j(e.autoDetect,pt,"autoDetect."),e.persistence!==void 0&&e.persistence!=="local"&&e.persistence!=="none"&&console.warn(`[IndieBob] persistence "${String(e.persistence)}" is not 'none' or 'local'; using 'none'`),{projectId:e.projectId,endpoint:e.endpoint??lt,debug:e.debug??false,respectDnt:e.respectDnt??true,respectGpc:e.respectGpc??true,autoDetect:e.autoDetect??true,hashMode:e.hashMode??false,persistence:e.persistence==="local"?"local":"none"}}var d="_ib_anon";function l(){let e="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-",t=new Uint8Array(21);if(typeof crypto<"u"&&crypto.getRandomValues)crypto.getRandomValues(t);else for(let o=0;o<21;o++)t[o]=Math.random()*64;let n="";for(let o of t)n+=e[o&63];return n}function g(){try{let e=localStorage.getItem(d);return e||(e=l(),localStorage.setItem(d,e)),e}catch{try{let e=sessionStorage.getItem(d);return e||(e=l(),sessionStorage.setItem(d,e)),e}catch{return l()}}}function m(){try{localStorage.removeItem(d);}catch{}try{sessionStorage.removeItem(d);}catch{}}var _="_ib_session",x="_ib_session_last",ft=1800*1e3;function B(){try{return crypto.randomUUID()}catch{return l()}}function h(){try{let e=Date.now(),t=parseInt(sessionStorage.getItem(x)??"0",10),n=sessionStorage.getItem(_),o=t>0&&e-t>ft;return (!n||o)&&(n=B(),sessionStorage.setItem(_,n)),sessionStorage.setItem(x,String(e)),n}catch{return B()}}function v(){try{sessionStorage.removeItem(_);}catch{}try{sessionStorage.removeItem(x);}catch{}}var y="_ib_first_utm",K="_ib_last_utm",b="_ib_referrer";function k(e){let t=new URLSearchParams(e),n={},o=false;!t.has("utm_source")&&t.get("ref")&&(n.source=t.get("ref"),o=true);for(let r of ["source","medium","campaign","term","content"])t.has("utm_"+r)&&(n[r]=t.get("utm_"+r),o=true);return o?n:null}function R(e,t){let n=k(e);try{n&&!localStorage.getItem(y)&&localStorage.setItem(y,JSON.stringify(n)),n&&localStorage.setItem(K,JSON.stringify(n)),t&&!localStorage.getItem(b)&&localStorage.setItem(b,t);}catch{}}function $(){try{let e=localStorage.getItem(y);return e?JSON.parse(e):void 0}catch{return}}function Y(){try{return localStorage.getItem(b)??void 0}catch{return}}function I(){try{localStorage.removeItem(y);}catch{}try{localStorage.removeItem(K);}catch{}try{localStorage.removeItem(b);}catch{}}var f="ib_ignore";function z(e,t){let n=new URLSearchParams(e).get(f);return n==="1"?t.setItem(f,"1"):n==="0"&&t.removeItem(f),t.getItem(f)==="1"}function T(){try{return localStorage.getItem(f)==="1"}catch{return false}}function H(){return typeof navigator<"u"&&navigator.webdriver===true||T()}var E="_ib_optout",gt="_ib_queue";function u(e){if(H())return false;try{if(localStorage.getItem(E))return !1}catch{}return !(e.respectDnt&&typeof navigator<"u"&&(navigator.doNotTrack==="1"||navigator.msDoNotTrack==="1")||e.respectGpc&&typeof navigator<"u"&&navigator.globalPrivacyControl===true)}function X(){try{localStorage.setItem(E,"1");}catch{}m(),v(),I();try{localStorage.removeItem(gt);}catch{}}function G(){try{localStorage.removeItem(E);}catch{}}function V(){try{return !!localStorage.getItem(E)}catch{return false}}function c(e,...t){e.debug&&console.log("[IndieBob]",...t);}async function P(e,t,n=false){let o=JSON.stringify(e);if(n&&typeof navigator<"u"&&navigator.sendBeacon){let r=new Blob([o],{type:"text/plain;charset=UTF-8"}),i=navigator.sendBeacon(t.endpoint,r);return c(t,"sendBeacon:",i,e.batch.length,"events"),i}for(let r=0;r<3;r++){try{let i=await fetch(t.endpoint,{method:"POST",headers:{"Content-Type":"application/json"},body:o,keepalive:!0});if(i.ok)return c(t,"sent:",e.batch.length,"events"),!0;if(i.status>=400&&i.status<500)return c(t,"4xx error, not retrying:",i.status),!1}catch(i){c(t,"fetch error (attempt",r+1,"):",i);}r<2&&await new Promise(i=>setTimeout(i,1e3<<r));}return c(t,"failed to send after",3,"attempts"),false}var C="_ib_queue",mt=10,ht=5e3,S=class{constructor(t,n){this.e=[];this.u=[];this.l=false;if(this.t=t,setInterval(()=>{this.e.length>0&&this.flush();},ht),typeof window>"u")return;let o=()=>{n?.(),this.flush(true);};document.addEventListener("visibilitychange",()=>{document.visibilityState==="hidden"&&o();}),window.addEventListener("pagehide",o),window.addEventListener("online",()=>{this.g();}),navigator.onLine&&this.g();}push(t){this.e.push(t),this.e.length>=mt&&this.flush();}async flush(t=false){if(this.l&&!t||this.e.length===0)return;this.l=true;let n=this.e.splice(0);await P({batch:n},this.t,t)||this.I([...this.m(),...n].slice(-50)),this.l=false;}async g(){let t=this.m();if(t.length===0)return;this.clearStored(),await P({batch:t},this.t);}stamp(t,n){for(let o of this.e)o.anonymousId||Object.assign(o,{anonymousId:t,sessionId:n});}clearStored(){this.u=[];try{localStorage.removeItem(C);}catch{}}I(t){if(this.t.persistence!=="local"){this.u=t;return}try{localStorage.setItem(C,JSON.stringify(t));}catch{}}m(){if(this.t.persistence!=="local")return this.u;try{let t=localStorage.getItem(C);return t?JSON.parse(t):[]}catch{return []}}};var yt=/^(utm_\w+|ref)$/;function O(e){let t=new URLSearchParams;new URLSearchParams(e).forEach((o,r)=>{yt.test(r)&&t.append(r,o);});let n=t.toString();return n?"?"+n:""}function D(e){let t=e.split("?")[0];return t.includes("=")?"":t}function J(e,t){try{let n=new URL(e);return n.origin+n.pathname+O(n.search)+(t?D(n.hash):"")}catch{return ""}}function W(e){try{let t=new URL(e);return t.origin+t.pathname}catch{return ""}}function q(e,t){return e.pathname+O(e.search)+(t?D(e.hash):"")}function Q(e,t){if(typeof window>"u")return ()=>{};let n=history.pushState.bind(history),o=history.replaceState.bind(history);return history.pushState=function(...r){n(...r),e();},history.replaceState=function(...r){o(...r);},window.addEventListener("popstate",e),t&&window.addEventListener("hashchange",e),()=>{history.pushState=n,history.replaceState=o,window.removeEventListener("popstate",e),window.removeEventListener("hashchange",e);}}var bt=/^https?:\/\/[^/]*(stripe\.com|paypal\.com|paddle\.com|lemonsqueezy\.com|gumroad\.com)(\/|$)/i;function A(e,t,n){let o="0.4.1";if(typeof window>"u")return {page:{path:e?.path??"",url:"",title:e?.title??"",referrer:e?.referrer??""},device:{width:0,height:0,type:"desktop"},locale:"en",timezone:"UTC",sdkVersion:o};let r=e?.referrer??document.referrer,i=innerWidth;return {page:{path:e?.path??q(location,t),url:J(location.href,t),title:e?.title??document.title,referrer:W(r===""||bt.test(r)?n&&Y()||"":r)},device:{width:i,height:innerHeight,type:i<=768?"mobile":i<=1024?"tablet":"desktop"},utm:k(location.search)??(n?$():void 0),locale:navigator.language,timezone:Intl.DateTimeFormat().resolvedOptions().timeZone??"UTC",sdkVersion:o}}var It=[["signup","signup_start",/\/(sign-?up|register|join|create-?account|get-?started|onboard|registro|inscription|s-?inscrire|anmeldung|registrieren|cadastro|registrazione|aanmelden|inschrijven)/i],["login","login_view",/\/(log-?in|sign-?in|auth(\/login)?|iniciar-?sesion|connexion|se-?connecter|anmelden|einloggen|entrar|accesso|accedi|inloggen)/i],["pricing","pricing_view",/\/(pricing|plans|upgrade|subscribe|precios|tarifs|preise|precos|prezzi|prijzen)/i],["checkout","checkout_view",/\/(checkout|cart|basket|pay(ment)?|order|comprar|pagar|panier|caisse|warenkorb|kasse|carrinho|carrello|winkelwagen)/i],["success","success_view",/\/(success|thank-?you|thanks|confirmation|confirmed|complete[d]?|gracias|merci|danke|obrigado|grazie|bedankt)/i],["onboarding","onboarding_view",/\/(onboarding|welcome|getting-?started|setup|bienvenido|bienvenue|willkommen|benvenuto|welkom)/i],["contact","contact_view",/\/(contact|contacto|kontakt|contato|contatto|nous-?contacter)/i]];function Et(e,t){return e instanceof RegExp?e.test(t):t.includes(e)}function Z(e,t){for(let[n,o,r]of It)if((t?.[`${n}Paths`]??[r]).some(s=>Et(s,e)))return o;return null}function tt(e){let t=/^(signup|login|checkout)_/.exec(e);return t?t[1]+"_submit":null}function et(e,t){if(typeof document>"u")return ()=>{};let n=o=>{o.target instanceof HTMLFormElement&&t(e);};return document.addEventListener("submit",n,true),()=>document.removeEventListener("submit",n,true)}var N="ib_identified";function nt(){return typeof localStorage>"u"?true:!localStorage.getItem(N)}function ot(){typeof localStorage>"u"||localStorage.setItem(N,"1");}function U(){typeof localStorage>"u"||localStorage.removeItem(N);}var rt="data-ib-event",it="data-ib-";function st(e){for(;e&&e!==document.body;){let t=e.getAttribute(rt);if(t){let n={auto:true};for(let o of e.attributes)o.name.startsWith(it)&&o.name!==rt&&(n[o.name.slice(it.length)]=o.value);return [t,n]}e=e.parentElement;}return null}var St=/\.(pdf|zip|dmg|exe|msi|pkg|apk|ipa|deb|rpm|appimage|t?gz|bz2|xz|tar|7z|rar|csv|xlsx?|docx?|pptx?|txt|epub|mp3|wav|mp4|mov|iso)$/i;function wt(e){let t=St.exec(e);return t?t[1].toLowerCase():null}function _t(e,t,n,o){if(!/^https?:\/\//i.test(e))return null;try{let r=new URL(e),i=n&&wt(r.pathname);if(i)return ["file_download",{auto:!0,url:r.origin+r.pathname,path:r.pathname,ext:i}];if(o&&r.hostname!==t)return ["outbound_click",{auto:!0,url:e,hostname:r.hostname}]}catch{}return null}function at(e,t,n,o){if(typeof document>"u")return ()=>{};let r=i=>{let s=i.target,a=s?.closest?.("a");for(let p of [t&&st(s),a&&_t(a.href,location.hostname,n,o)])p&&e(p[0],p[1]);};return document.addEventListener("click",r,true),()=>document.removeEventListener("click",r,true)}function xt(e,t,n){return t>n||e>=3e3}function kt(e,t,n){return n>0?Math.min(100,Math.round((e+t)/n*100)):0}function ct(){let e=0,t=0,n=0,o=0,r=()=>{let a=Date.now();t&&(e+=a-t),t=document.visibilityState==="visible"&&document.hasFocus()?a:0;},i=()=>{n=Math.max(n,kt(scrollY,innerHeight,Math.max(document.documentElement.scrollHeight,document.body?.scrollHeight??0)));},s=()=>{e=n=o=t=0,r();};for(let a of ["focus","blur"])window.addEventListener(a,r);return document.addEventListener("visibilitychange",r),window.addEventListener("scroll",i),s(),{E:i,S:s,w(a){if(a&&i(),r(),!xt(e,n,o))return null;let p={ms:Math.min(e,864e5),scroll:n};return e=0,o=n,p}}}var L={};function ut(){return typeof document<"u"&&(document.visibilityState==="hidden"||document.prerendering===true)}var w=class e{constructor(t){this.s=null;this.p=null;this.a=null;this.r=null;this.f=null;this.c=false;if(this.t=t,this.e=new S(t,()=>this.b(true)),typeof window<"u"){try{z(window.location.search,localStorage)&&console.info("IndieBob: this browser is excluded from analytics (ib_ignore)");}catch{}if(this.n&&u(t)&&R(window.location.search,document.referrer),this.r=ct(),window.addEventListener("pageshow",n=>{n.persisted&&this.i!==void 0&&(this.i=void 0,this.page(this.h));}),t.autoDetect!==false){let n=typeof t.autoDetect=="object"?t.autoDetect:{};this.p=at((o,r)=>this.track(o,r),n.dataAttributes!==false,n.fileDownloads!==false,n.outboundClicks!==false);}}}static init(t){var o;let n=F(t);return typeof window>"u"?new e(n):L[o=n.projectId]??(L[o]=new e(n))}page(t){if(!u(this.t))return;if(this.i===void 0&&ut()){if(this.y=t,!this.c){this.c=true;let o=()=>{this.c&&!ut()&&(this.c=false,this.page(this.y));};document.addEventListener("visibilitychange",o),document.addEventListener("prerenderingchange",o);}return}let n=A(t,this.t.hashMode,this.n);if(n.page.path!==this.i&&(this.b(false),this.i=n.page.path,this.h=t,this.f=n,this.r&&(this.r.S(),setTimeout(this.r.E,1e3)),this.e.push(this.o("page",{context:n})),this.t.autoDetect!==false)){let o=n.page.path,r=typeof this.t.autoDetect=="object"?this.t.autoDetect:{},i=Z(o,r);if(i&&(this.e.push(this.o("track",{event:i,properties:{auto:true},context:n})),c(this.t,`auto-detected: ${i} on ${o}`),r.formSubmit!==false)){this.a?.();let s=tt(i);s&&(this.a=et(s,a=>{this.e.push(this.o("track",{event:a,properties:{auto:true}})),c(this.t,`auto-detected: ${a}`);}));}}}track(t,n){u(this.t)&&this.e.push(this.o("track",{event:t,properties:n}));}identify(t,n,o){if(!u(this.t))return;this.d=t,this.e.push(this.o("identify",{traits:n,userId:t}));let r=typeof o?.isNew=="boolean";if(this.t.autoDetect!==false&&(r||this.n)){let s=(r?o.isNew:nt())?"signup":"login";this.e.push(this.o("track",{event:s,properties:{auto:!r}})),this.n&&ot(),c(this.t,`${s} for ${t}`);}}revenue(t){u(this.t)&&this.e.push(this.o("revenue",{revenue:{amount:t.amount,currency:t.currency??"USD",plan:t.plan,type:t.type}}));}optOut(){this.e.flush(),X(),U(),this.d=void 0,this.p?.(),this.a?.(),this.p=null,this.a=null,c(this.t,"opted out");}optIn(){G(),c(this.t,"opted in");}isOptedOut(){return V()}isIgnored(){return T()}async flush(){await this.e.flush();}getAnonymousId(){return this.n?g():""}getSessionId(){return this.n?h():""}setPersistence(t){t!=="local"&&t!=="none"||(this.t.persistence=t,t==="local"?typeof window<"u"&&u(this.t)&&(R(location.search,document.referrer),this.e.stamp(g(),h())):(m(),v(),I(),U(),this.e.clearStored()),c(this.t,`persistence: ${t}`));}get n(){return this.t.persistence==="local"}getConfig(){return Object.freeze({...this.t})}enableAutoPage(){return this.s?.(),this.s=Q(()=>this.page(),this.t.hashMode),()=>{this.s?.(),this.s=null;}}b(t){let n=this.f&&this.r?.w(t);n&&u(this.t)&&this.e.push(this.o("engagement",{context:this.f,engagement:n}));}o(t,n){return {...n,v:1,id:l(),projectId:this.t.projectId,type:t,...this.n?{anonymousId:g(),sessionId:h()}:{},userId:this.d??n.userId,timestamp:new Date().toISOString(),context:n.context??A(void 0,this.t.hashMode,this.n)}}};var Rt=Symbol("indiebob"),M=null,me={install(e,t){let n=w.init(t);M=n,e.provide(Rt,n),e.config.globalProperties.$bob=n;let o=e.config.globalProperties.$router;o&&o.afterEach(()=>{n.page();});}};function he(){if(M)return M;throw new Error("[IndieBob] useTracker() called before IndieBobPlugin was installed.")}
2
+ exports.IndieBob=w;exports.IndieBobPlugin=me;exports.useTracker=he;return exports;})({});
3
3
  ;IndieBob.IndieBob&&(IndieBob=Object.assign(IndieBob.IndieBob,IndieBob));