@indiebob/tracker 0.2.4 → 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/index.d.mts CHANGED
@@ -4,13 +4,13 @@
4
4
  interface TrackerConfig {
5
5
  /** Your SDK project ID from the IndieBob dashboard. Format: 'proj_...' */
6
6
  projectId: string;
7
- /** Ingestion endpoint URL. Default: 'https://indiebob.com/api/collect' */
7
+ /** Ingestion endpoint URL. Default: 'https://www.indiebob.com/api/collect' */
8
8
  endpoint?: string;
9
9
  /** Log all events to the browser console. Default: false */
10
10
  debug?: boolean;
11
11
  /** Honor the browser Do Not Track header. Default: true */
12
12
  respectDnt?: boolean;
13
- /** Honor Global Privacy Control signal (legally binding in CA/GDPR). Default: true */
13
+ /** Honor Global Privacy Control signal (legally binding under CCPA in California). Default: true */
14
14
  respectGpc?: boolean;
15
15
  /**
16
16
  * Auto-detect user intent from URL patterns and identify() calls.
@@ -42,8 +42,31 @@ interface TrackerConfig {
42
42
  formSubmit?: boolean;
43
43
  /** Track clicks on outbound links. Default: true */
44
44
  outboundClicks?: boolean;
45
+ /** Track clicks on links to files (pdf, zip, dmg, …) as `file_download`. Default: true */
46
+ fileDownloads?: boolean;
45
47
  };
48
+ /**
49
+ * Treat the URL hash as part of the page path (for `/#/route` routers):
50
+ * a hash-only change becomes a pageview and the hash is reported in the
51
+ * path. Default: false (a hash-only change is not a new page).
52
+ */
53
+ hashMode?: boolean;
54
+ /**
55
+ * What the tracker keeps in the visitor's browser.
56
+ *
57
+ * - `'none'` (default): nothing. No id, no stored UTM or referrer, no offline
58
+ * queue. IndieBob counts the visitor on its server from a hash of a daily
59
+ * salt, the site, the IP address and the user agent; the salt is deleted
60
+ * after a day and the IP is never stored. No consent needed.
61
+ * - `'local'`: a random visitor id, first-touch UTM and referrer in
62
+ * localStorage, so a visitor is recognised across days. Storing an id on
63
+ * the visitor's device needs their consent in the EU (ePrivacy Art. 5(3)):
64
+ * switch to it from your consent banner with `bob.setPersistence('local')`.
65
+ */
66
+ persistence?: Persistence;
46
67
  }
68
+ /** Where the tracker may store anything: nowhere, or localStorage. */
69
+ type Persistence = 'none' | 'local';
47
70
  /** Resolved config with all defaults applied. */
48
71
  interface ResolvedConfig {
49
72
  projectId: string;
@@ -62,10 +85,13 @@ interface ResolvedConfig {
62
85
  dataAttributes?: boolean;
63
86
  formSubmit?: boolean;
64
87
  outboundClicks?: boolean;
88
+ fileDownloads?: boolean;
65
89
  };
90
+ hashMode: boolean;
91
+ persistence: Persistence;
66
92
  }
67
93
  /** The tracking event type. */
68
- type EventType = 'page' | 'track' | 'identify' | 'revenue';
94
+ type EventType = 'page' | 'track' | 'identify' | 'revenue' | 'engagement';
69
95
  /** Device category. */
70
96
  type DeviceType = 'desktop' | 'mobile' | 'tablet';
71
97
  /** Revenue event type. */
@@ -100,11 +126,18 @@ interface EventContext {
100
126
  interface TrackerEvent {
101
127
  /** Schema version. Always 1 for this SDK. Enables server-side backwards compat. */
102
128
  v: 1;
129
+ /**
130
+ * Random url-safe id (21 chars), unique per event. Stays the same across
131
+ * retries and offline replays so the server can store each event once.
132
+ */
133
+ id: string;
103
134
  projectId: string;
104
135
  type: EventType;
105
- anonymousId: string;
136
+ /** Absent with `persistence: 'none'`: the server derives the visitor from its daily hash. */
137
+ anonymousId?: string;
106
138
  userId?: string;
107
- sessionId: string;
139
+ /** Absent with `persistence: 'none'`: the server groups visits on its own. */
140
+ sessionId?: string;
108
141
  timestamp: string;
109
142
  context: EventContext;
110
143
  event?: string;
@@ -116,6 +149,12 @@ interface TrackerEvent {
116
149
  plan?: string;
117
150
  type?: RevenueType;
118
151
  };
152
+ engagement?: {
153
+ /** Visible-and-focused milliseconds on the page since the last engagement event. */
154
+ ms: number;
155
+ /** Deepest point of the page seen, as a percentage of its height (0–100). */
156
+ scroll: number;
157
+ };
119
158
  }
120
159
  /** Overrides for manual page() calls. */
121
160
  interface PageOverrides {
@@ -139,17 +178,31 @@ interface RevenueData {
139
178
  * bob.page()
140
179
  */
141
180
  declare class IndieBob {
142
- private config;
143
- private queue;
144
- private userId;
145
- private cleanupHistory;
146
- private cleanupAttributes;
147
- private cleanupOutbound;
148
- private cleanupFormSubmit;
181
+ private _config;
182
+ private _queue;
183
+ private _userId;
184
+ private _cleanupHistory;
185
+ private _cleanupClicks;
186
+ private _cleanupFormSubmit;
187
+ /** Engagement meter for the current page (browser only). */
188
+ private _eng;
189
+ /** Context of the page last counted — what an engagement event describes. */
190
+ private _pageCtx;
191
+ /** Path of the page last counted; undefined until the first pageview. */
192
+ private _lastPath;
193
+ /** Overrides of the page last counted, reused for a bfcache restore. */
194
+ private _lastOverrides;
195
+ /** A first pageview waiting for the tab to become visible. */
196
+ private _waiting;
197
+ private _waitingOverrides;
149
198
  private constructor();
150
199
  /**
151
200
  * Create a tracker instance. Call once at app startup.
152
201
  *
202
+ * In the browser, calling it again for the same projectId returns the
203
+ * instance already running (its first config wins) — so a `data-project`
204
+ * script tag plus a manual init() never doubles the events.
205
+ *
153
206
  * @example
154
207
  * const bob = IndieBob.init({ projectId: 'proj_your16charId' })
155
208
  */
@@ -211,12 +264,28 @@ declare class IndieBob {
211
264
  optIn(): void;
212
265
  /** Returns true if the user has explicitly opted out. */
213
266
  isOptedOut(): boolean;
267
+ /**
268
+ * Returns true if this browser excluded itself with `?ib_ignore=1`
269
+ * (the owner's own visits). `?ib_ignore=0` undoes it.
270
+ */
271
+ isIgnored(): boolean;
214
272
  /** Force-send all queued events immediately. Useful in tests. */
215
273
  flush(): Promise<void>;
216
- /** Get the current anonymous ID. */
274
+ /** The stored anonymous ID with `persistence: 'local'`; '' without storage. */
217
275
  getAnonymousId(): string;
218
- /** Get the current session ID. */
276
+ /** The stored session ID with `persistence: 'local'`; '' without storage. */
219
277
  getSessionId(): string;
278
+ /**
279
+ * Switch storage on or off — call it from your consent banner.
280
+ * `'local'` starts storing the visitor id and first-touch attribution from
281
+ * this page on; `'none'` removes everything the tracker stored.
282
+ *
283
+ * @example
284
+ * onConsent(() => bob.setPersistence('local'))
285
+ * onConsentWithdrawn(() => bob.setPersistence('none'))
286
+ */
287
+ setPersistence(mode: Persistence): void;
288
+ private get _local();
220
289
  /** Get the resolved configuration (read-only). */
221
290
  getConfig(): Readonly<ResolvedConfig>;
222
291
  /**
@@ -228,7 +297,13 @@ declare class IndieBob {
228
297
  * // Later: cleanup()
229
298
  */
230
299
  enableAutoPage(): () => void;
231
- private buildEvent;
300
+ /**
301
+ * Queue an engagement event for the page last counted, if its reading is
302
+ * worth sending. `measure`: sample the scroll first (false on an SPA
303
+ * change, when the DOM already shows the next page).
304
+ */
305
+ private _leave;
306
+ private _buildEvent;
232
307
  }
233
308
 
234
- export { type DeviceType, type EventContext, type EventType, IndieBob, type PageOverrides, type RevenueData, type RevenueType, type TrackerConfig, type TrackerEvent, type UtmData };
309
+ export { type DeviceType, type EventContext, type EventType, IndieBob, type PageOverrides, type Persistence, type RevenueData, type RevenueType, type TrackerConfig, type TrackerEvent, type UtmData };
package/dist/index.d.ts CHANGED
@@ -4,13 +4,13 @@
4
4
  interface TrackerConfig {
5
5
  /** Your SDK project ID from the IndieBob dashboard. Format: 'proj_...' */
6
6
  projectId: string;
7
- /** Ingestion endpoint URL. Default: 'https://indiebob.com/api/collect' */
7
+ /** Ingestion endpoint URL. Default: 'https://www.indiebob.com/api/collect' */
8
8
  endpoint?: string;
9
9
  /** Log all events to the browser console. Default: false */
10
10
  debug?: boolean;
11
11
  /** Honor the browser Do Not Track header. Default: true */
12
12
  respectDnt?: boolean;
13
- /** Honor Global Privacy Control signal (legally binding in CA/GDPR). Default: true */
13
+ /** Honor Global Privacy Control signal (legally binding under CCPA in California). Default: true */
14
14
  respectGpc?: boolean;
15
15
  /**
16
16
  * Auto-detect user intent from URL patterns and identify() calls.
@@ -42,8 +42,31 @@ interface TrackerConfig {
42
42
  formSubmit?: boolean;
43
43
  /** Track clicks on outbound links. Default: true */
44
44
  outboundClicks?: boolean;
45
+ /** Track clicks on links to files (pdf, zip, dmg, …) as `file_download`. Default: true */
46
+ fileDownloads?: boolean;
45
47
  };
48
+ /**
49
+ * Treat the URL hash as part of the page path (for `/#/route` routers):
50
+ * a hash-only change becomes a pageview and the hash is reported in the
51
+ * path. Default: false (a hash-only change is not a new page).
52
+ */
53
+ hashMode?: boolean;
54
+ /**
55
+ * What the tracker keeps in the visitor's browser.
56
+ *
57
+ * - `'none'` (default): nothing. No id, no stored UTM or referrer, no offline
58
+ * queue. IndieBob counts the visitor on its server from a hash of a daily
59
+ * salt, the site, the IP address and the user agent; the salt is deleted
60
+ * after a day and the IP is never stored. No consent needed.
61
+ * - `'local'`: a random visitor id, first-touch UTM and referrer in
62
+ * localStorage, so a visitor is recognised across days. Storing an id on
63
+ * the visitor's device needs their consent in the EU (ePrivacy Art. 5(3)):
64
+ * switch to it from your consent banner with `bob.setPersistence('local')`.
65
+ */
66
+ persistence?: Persistence;
46
67
  }
68
+ /** Where the tracker may store anything: nowhere, or localStorage. */
69
+ type Persistence = 'none' | 'local';
47
70
  /** Resolved config with all defaults applied. */
48
71
  interface ResolvedConfig {
49
72
  projectId: string;
@@ -62,10 +85,13 @@ interface ResolvedConfig {
62
85
  dataAttributes?: boolean;
63
86
  formSubmit?: boolean;
64
87
  outboundClicks?: boolean;
88
+ fileDownloads?: boolean;
65
89
  };
90
+ hashMode: boolean;
91
+ persistence: Persistence;
66
92
  }
67
93
  /** The tracking event type. */
68
- type EventType = 'page' | 'track' | 'identify' | 'revenue';
94
+ type EventType = 'page' | 'track' | 'identify' | 'revenue' | 'engagement';
69
95
  /** Device category. */
70
96
  type DeviceType = 'desktop' | 'mobile' | 'tablet';
71
97
  /** Revenue event type. */
@@ -100,11 +126,18 @@ interface EventContext {
100
126
  interface TrackerEvent {
101
127
  /** Schema version. Always 1 for this SDK. Enables server-side backwards compat. */
102
128
  v: 1;
129
+ /**
130
+ * Random url-safe id (21 chars), unique per event. Stays the same across
131
+ * retries and offline replays so the server can store each event once.
132
+ */
133
+ id: string;
103
134
  projectId: string;
104
135
  type: EventType;
105
- anonymousId: string;
136
+ /** Absent with `persistence: 'none'`: the server derives the visitor from its daily hash. */
137
+ anonymousId?: string;
106
138
  userId?: string;
107
- sessionId: string;
139
+ /** Absent with `persistence: 'none'`: the server groups visits on its own. */
140
+ sessionId?: string;
108
141
  timestamp: string;
109
142
  context: EventContext;
110
143
  event?: string;
@@ -116,6 +149,12 @@ interface TrackerEvent {
116
149
  plan?: string;
117
150
  type?: RevenueType;
118
151
  };
152
+ engagement?: {
153
+ /** Visible-and-focused milliseconds on the page since the last engagement event. */
154
+ ms: number;
155
+ /** Deepest point of the page seen, as a percentage of its height (0–100). */
156
+ scroll: number;
157
+ };
119
158
  }
120
159
  /** Overrides for manual page() calls. */
121
160
  interface PageOverrides {
@@ -139,17 +178,31 @@ interface RevenueData {
139
178
  * bob.page()
140
179
  */
141
180
  declare class IndieBob {
142
- private config;
143
- private queue;
144
- private userId;
145
- private cleanupHistory;
146
- private cleanupAttributes;
147
- private cleanupOutbound;
148
- private cleanupFormSubmit;
181
+ private _config;
182
+ private _queue;
183
+ private _userId;
184
+ private _cleanupHistory;
185
+ private _cleanupClicks;
186
+ private _cleanupFormSubmit;
187
+ /** Engagement meter for the current page (browser only). */
188
+ private _eng;
189
+ /** Context of the page last counted — what an engagement event describes. */
190
+ private _pageCtx;
191
+ /** Path of the page last counted; undefined until the first pageview. */
192
+ private _lastPath;
193
+ /** Overrides of the page last counted, reused for a bfcache restore. */
194
+ private _lastOverrides;
195
+ /** A first pageview waiting for the tab to become visible. */
196
+ private _waiting;
197
+ private _waitingOverrides;
149
198
  private constructor();
150
199
  /**
151
200
  * Create a tracker instance. Call once at app startup.
152
201
  *
202
+ * In the browser, calling it again for the same projectId returns the
203
+ * instance already running (its first config wins) — so a `data-project`
204
+ * script tag plus a manual init() never doubles the events.
205
+ *
153
206
  * @example
154
207
  * const bob = IndieBob.init({ projectId: 'proj_your16charId' })
155
208
  */
@@ -211,12 +264,28 @@ declare class IndieBob {
211
264
  optIn(): void;
212
265
  /** Returns true if the user has explicitly opted out. */
213
266
  isOptedOut(): boolean;
267
+ /**
268
+ * Returns true if this browser excluded itself with `?ib_ignore=1`
269
+ * (the owner's own visits). `?ib_ignore=0` undoes it.
270
+ */
271
+ isIgnored(): boolean;
214
272
  /** Force-send all queued events immediately. Useful in tests. */
215
273
  flush(): Promise<void>;
216
- /** Get the current anonymous ID. */
274
+ /** The stored anonymous ID with `persistence: 'local'`; '' without storage. */
217
275
  getAnonymousId(): string;
218
- /** Get the current session ID. */
276
+ /** The stored session ID with `persistence: 'local'`; '' without storage. */
219
277
  getSessionId(): string;
278
+ /**
279
+ * Switch storage on or off — call it from your consent banner.
280
+ * `'local'` starts storing the visitor id and first-touch attribution from
281
+ * this page on; `'none'` removes everything the tracker stored.
282
+ *
283
+ * @example
284
+ * onConsent(() => bob.setPersistence('local'))
285
+ * onConsentWithdrawn(() => bob.setPersistence('none'))
286
+ */
287
+ setPersistence(mode: Persistence): void;
288
+ private get _local();
220
289
  /** Get the resolved configuration (read-only). */
221
290
  getConfig(): Readonly<ResolvedConfig>;
222
291
  /**
@@ -228,7 +297,13 @@ declare class IndieBob {
228
297
  * // Later: cleanup()
229
298
  */
230
299
  enableAutoPage(): () => void;
231
- private buildEvent;
300
+ /**
301
+ * Queue an engagement event for the page last counted, if its reading is
302
+ * worth sending. `measure`: sample the scroll first (false on an SPA
303
+ * change, when the DOM already shows the next page).
304
+ */
305
+ private _leave;
306
+ private _buildEvent;
232
307
  }
233
308
 
234
- export { type DeviceType, type EventContext, type EventType, IndieBob, type PageOverrides, type RevenueData, type RevenueType, type TrackerConfig, type TrackerEvent, type UtmData };
309
+ export { type DeviceType, type EventContext, type EventType, IndieBob, type PageOverrides, type Persistence, type RevenueData, type RevenueType, type TrackerConfig, type TrackerEvent, type UtmData };
@@ -1,3 +1,3 @@
1
- var IndieBob=(function(exports){'use strict';var dt=Object.defineProperty,ft=Object.defineProperties;var pt=Object.getOwnPropertyDescriptors;var D=Object.getOwnPropertySymbols;var gt=Object.prototype.hasOwnProperty,mt=Object.prototype.propertyIsEnumerable;var N=(e,t,n)=>t in e?dt(e,t,{enumerable:true,configurable:true,writable:true,value:n}):e[t]=n,p=(e,t)=>{for(var n in t||(t={}))gt.call(t,n)&&N(e,n,t[n]);if(D)for(var n of D(t))mt.call(t,n)&&N(e,n,t[n]);return e},F=(e,t)=>ft(e,pt(t));var l=(e,t,n)=>new Promise((o,i)=>{var r=a=>{try{s(n.next(a));}catch(u){i(u);}},c=a=>{try{s(n.throw(a));}catch(u){i(u);}},s=a=>a.done?o(a.value):Promise.resolve(a.value).then(r,c);s((n=n.apply(e,t)).next());});var ht="https://www.indiebob.com/api/collect";function U(e){var t,n,o,i,r;if(!e.projectId||!e.projectId.startsWith("proj_"))throw new Error(`[IndieBob] Invalid projectId "${e.projectId}". Must start with "proj_".`);return {projectId:e.projectId,endpoint:(t=e.endpoint)!=null?t:ht,debug:(n=e.debug)!=null?n:false,respectDnt:(o=e.respectDnt)!=null?o:true,respectGpc:(i=e.respectGpc)!=null?i:true,autoDetect:(r=e.autoDetect)!=null?r:true}}var d="_ib_anon";function y(){let e="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-",t="";if(typeof crypto!="undefined"&&crypto.getRandomValues){let n=new Uint8Array(21);crypto.getRandomValues(n);for(let o of n)t+=e[o%e.length];}else for(let n=0;n<21;n++)t+=e[Math.floor(Math.random()*e.length)];return t}function b(){try{let e=localStorage.getItem(d);return e||(e=y(),localStorage.setItem(d,e)),e}catch(e){try{let t=sessionStorage.getItem(d);return t||(t=y(),sessionStorage.setItem(d,t)),t}catch(t){return y()}}}function L(){try{localStorage.removeItem(d);}catch(e){}try{sessionStorage.removeItem(d);}catch(e){}}var I="_ib_session",S="_ib_session_last";function M(){try{return crypto.randomUUID()}catch(e){return Math.random().toString(36).slice(2)+Math.random().toString(36).slice(2)}}function E(){var e;try{let t=Date.now(),n=parseInt((e=sessionStorage.getItem(S))!=null?e:"0",10),o=sessionStorage.getItem(I),i=n>0&&t-n>18e5;return (!o||i)&&(o=M(),sessionStorage.setItem(I,o)),sessionStorage.setItem(S,String(t)),o}catch(t){return M()}}function q(){try{sessionStorage.removeItem(I);}catch(e){}try{sessionStorage.removeItem(S);}catch(e){}}var g="_ib_first_utm",j="_ib_last_utm",m="_ib_referrer";function B(e){let t=new URLSearchParams(e),n={},o=false;return t.has("utm_source")?(n.source=t.get("utm_source"),o=true):t.get("ref")&&(n.source=t.get("ref"),o=true),t.has("utm_medium")&&(n.medium=t.get("utm_medium"),o=true),t.has("utm_campaign")&&(n.campaign=t.get("utm_campaign"),o=true),t.has("utm_term")&&(n.term=t.get("utm_term"),o=true),t.has("utm_content")&&(n.content=t.get("utm_content"),o=true),o?n:null}function Y(e,t){let n=B(e);try{n&&!localStorage.getItem(g)&&localStorage.setItem(g,JSON.stringify(n)),n&&localStorage.setItem(j,JSON.stringify(n)),t&&!localStorage.getItem(m)&&localStorage.setItem(m,t);}catch(o){}}function H(){try{let e=localStorage.getItem(g);return e?JSON.parse(e):void 0}catch(e){return}}function K(){var e;try{return (e=localStorage.getItem(m))!=null?e:void 0}catch(t){return}}function V(e){var t;return (t=B(e))!=null?t:void 0}function Q(){try{localStorage.removeItem(g);}catch(e){}try{localStorage.removeItem(j);}catch(e){}try{localStorage.removeItem(m);}catch(e){}}var h="_ib_optout",vt="_ib_queue";function f(e){try{if(localStorage.getItem(h))return !1}catch(t){}return !(e.respectDnt&&typeof navigator!="undefined"&&(navigator.doNotTrack==="1"||navigator.msDoNotTrack==="1")||e.respectGpc&&typeof navigator!="undefined"&&navigator.globalPrivacyControl===true)}function z(){try{localStorage.setItem(h,"1");}catch(e){}L(),q(),Q();try{localStorage.removeItem(vt);}catch(e){}}function X(){try{localStorage.removeItem(h);}catch(e){}}function J(){try{return !!localStorage.getItem(h)}catch(e){return false}}var yt=[1e3,2e3,4e3];function bt(e){return l(this,null,function*(){return new Promise(t=>setTimeout(t,e))})}function w(e,t,n=false){return l(this,null,function*(){let o=JSON.stringify(e);if(n&&typeof navigator!="undefined"&&navigator.sendBeacon){let i=new Blob([o],{type:"text/plain;charset=UTF-8"}),r=navigator.sendBeacon(t.endpoint,i);return t.debug&&console.log("[IndieBob] sendBeacon:",r,e.batch.length,"events"),r}for(let i=0;i<3;i++){try{let r=yield fetch(t.endpoint,{method:"POST",headers:{"Content-Type":"application/json"},body:o,keepalive:!0});if(r.ok)return t.debug&&console.log("[IndieBob] sent:",e.batch.length,"events"),!0;if(r.status>=400&&r.status<500)return t.debug&&console.warn("[IndieBob] 4xx error, not retrying:",r.status),!1}catch(r){t.debug&&console.warn("[IndieBob] fetch error (attempt",i+1,"):",r);}i<2&&(yield bt(yt[i]));}return t.debug&&console.warn("[IndieBob] failed to send after",3,"attempts"),false})}var _="_ib_queue",It=10,St=5e3,Et=50,v=class{constructor(t){this.queue=[];this.timer=null;this.flushing=false;this.config=t,this.startTimer(),this.setupVisibilityFlush(),this.setupOnlineFlush();}push(t){this.queue.push(t),this.queue.length>=It&&this.flush();}flush(t=false){return l(this,null,function*(){if(this.flushing&&!t||this.queue.length===0)return;this.flushing=true;let n=this.queue.splice(0);(yield w({batch:n},this.config,t))||this.pushToOfflineQueue(n),this.flushing=false;})}flushOfflineQueue(){return l(this,null,function*(){let t=this.getOfflineQueue();if(t.length===0)return;this.clearOfflineQueue(),yield w({batch:t},this.config);})}destroy(){this.timer&&clearInterval(this.timer);}startTimer(){this.timer=setInterval(()=>{this.queue.length>0&&this.flush();},St);}setupVisibilityFlush(){typeof document!="undefined"&&(document.addEventListener("visibilitychange",()=>{document.visibilityState==="hidden"&&this.flush(true);},{passive:true}),window.addEventListener("pagehide",()=>{this.flush(true);},{passive:true}));}setupOnlineFlush(){typeof window!="undefined"&&(window.addEventListener("online",()=>{this.flushOfflineQueue();}),navigator.onLine&&this.flushOfflineQueue());}pushToOfflineQueue(t){try{let i=[...this.getOfflineQueue(),...t].slice(-Et);localStorage.setItem(_,JSON.stringify(i));}catch(n){}}getOfflineQueue(){try{let t=localStorage.getItem(_);return t?JSON.parse(t):[]}catch(t){return []}}clearOfflineQueue(){try{localStorage.removeItem(_);}catch(t){}}};function $(){if(typeof window=="undefined")return "desktop";let e=window.innerWidth;return e<=768?"mobile":e<=1024?"tablet":"desktop"}function G(){return typeof window=="undefined"?{width:0,height:0}:{width:window.innerWidth,height:window.innerHeight}}var wt=/^https?:\/\/[^/]*(stripe\.com|paypal\.com|paddle\.com|lemonsqueezy\.com|gumroad\.com)(\/|$)/i;function T(e){var R,O,x,A,C,P;let t=typeof window=="undefined",n=(R=e==null?void 0:e.path)!=null?R:t?"":window.location.pathname+window.location.search,o=t?"":window.location.href,i=(O=e==null?void 0:e.title)!=null?O:t?"":document.title,r=(x=e==null?void 0:e.referrer)!=null?x:t?"":document.referrer,c=!t&&(r===""||wt.test(r))&&(A=K())!=null?A:r,s=G(),a=$(),u=t?void 0:(C=V(window.location.search))!=null?C:H();return {page:{path:n,url:o,title:i,referrer:c},device:F(p({},s),{type:a}),utm:u,locale:t?"en":navigator.language,timezone:t?"UTC":(P=Intl.DateTimeFormat().resolvedOptions().timeZone)!=null?P:"UTC",sdkVersion:"0.2.4"}}function W(e){if(typeof window=="undefined")return ()=>{};let t=history.pushState.bind(history),n=history.replaceState.bind(history);return history.pushState=function(...o){t(...o),e();},history.replaceState=function(...o){n(...o);},window.addEventListener("popstate",e),()=>{history.pushState=t,history.replaceState=n,window.removeEventListener("popstate",e);}}var _t={signup:[/\/(sign-?up|register|join|create-?account|get-?started|onboard|registro|inscription|s-?inscrire|anmeldung|registrieren|cadastro|registrazione|aanmelden|inschrijven)/i],login:[/\/(log-?in|sign-?in|auth(\/login)?|iniciar-?sesion|connexion|se-?connecter|anmelden|einloggen|entrar|accesso|accedi|inloggen)/i],pricing:[/\/(pricing|plans|upgrade|subscribe|precios|tarifs|preise|precos|prezzi|prijzen)/i],checkout:[/\/(checkout|cart|basket|pay(ment)?|order|comprar|pagar|panier|caisse|warenkorb|kasse|carrinho|carrello|winkelwagen)/i],success:[/\/(success|thank-?you|thanks|confirmation|confirmed|complete[d]?|gracias|merci|danke|obrigado|grazie|bedankt)/i],onboarding:[/\/(onboarding|welcome|getting-?started|setup|bienvenido|bienvenue|willkommen|benvenuto|welkom)/i],contact:[/\/(contact|contacto|kontakt|contato|contatto|nous-?contacter)/i]},Z={signup:"signup_start",login:"login_view",pricing:"pricing_view",checkout:"checkout_view",success:"success_view",onboarding:"onboarding_view",contact:"contact_view"};function Tt(e,t){return e instanceof RegExp?e.test(t):t.includes(e)}function tt(e,t){var n;for(let o of Object.keys(Z))if(((n=t==null?void 0:t[o])!=null?n:_t[o]).some(r=>Tt(r,e)))return Z[o];return null}function et(e){return e==="signup_start"?"signup_submit":e==="login_view"?"login_submit":e==="checkout_view"?"checkout_submit":null}function nt(e,t){if(typeof document=="undefined")return ()=>{};let n=o=>{o.target instanceof HTMLFormElement&&t(e);};return document.addEventListener("submit",n,true),()=>document.removeEventListener("submit",n,true)}var k="ib_identified";function ot(){return typeof localStorage=="undefined"?true:!localStorage.getItem(k)}function it(){typeof localStorage!="undefined"&&localStorage.setItem(k,"1");}function rt(){typeof localStorage!="undefined"&&localStorage.removeItem(k);}var st="data-ib-event",at="data-ib-";function ct(e){if(typeof document=="undefined")return ()=>{};let t=n=>{let o=n.target;for(;o&&o!==document.body;){let i=o.getAttribute(st);if(i){let r={auto:true};for(let c of o.attributes)if(c.name.startsWith(at)&&c.name!==st){let s=c.name.slice(at.length);r[s]=c.value;}e(i,r);return}o=o.parentElement;}};return document.addEventListener("click",t,true),()=>document.removeEventListener("click",t,true)}function ut(e){if(typeof document=="undefined")return ()=>{};let t=n=>{let o=n.target;for(;o&&o!==document.body;){if(o.tagName==="A"){let i=o.href;if(!i||!/^https?:\/\//.test(i))return;try{let r=new URL(i);r.hostname!==window.location.hostname&&e("outbound_click",{auto:!0,url:i,hostname:r.hostname});}catch(r){}return}o=o.parentElement;}};return document.addEventListener("click",t,true),()=>document.removeEventListener("click",t,true)}var lt=class e{constructor(t){this.cleanupHistory=null;this.cleanupAttributes=null;this.cleanupOutbound=null;this.cleanupFormSubmit=null;if(this.config=t,this.queue=new v(t),typeof window!="undefined"&&(Y(window.location.search,document.referrer),t.autoDetect!==false)){let n=typeof t.autoDetect=="object"?t.autoDetect:{};n.dataAttributes!==false&&(this.cleanupAttributes=ct((o,i)=>this.track(o,i))),n.outboundClicks!==false&&(this.cleanupOutbound=ut((o,i)=>this.track(o,i)));}}static init(t){let n=U(t);return new e(n)}page(t){var o;if(!f(this.config))return;let n=T(t);if(this.queue.push(this.buildEvent("page",{context:n})),this.config.autoDetect!==false){let i=n.page.path,r=typeof this.config.autoDetect=="object"?this.config.autoDetect:{},c={signup:r.signupPaths,login:r.loginPaths,pricing:r.pricingPaths,checkout:r.checkoutPaths,success:r.successPaths,onboarding:r.onboardingPaths,contact:r.contactPaths},s=tt(i,c);if(s&&(this.queue.push(this.buildEvent("track",{event:s,properties:{auto:true},context:n})),this.config.debug&&console.log(`[IndieBob] auto-detected: ${s} on ${i}`),r.formSubmit!==false)){(o=this.cleanupFormSubmit)==null||o.call(this);let a=et(s);a&&(this.cleanupFormSubmit=nt(a,u=>{this.queue.push(this.buildEvent("track",{event:u,properties:{auto:true}})),this.config.debug&&console.log(`[IndieBob] auto-detected: ${u}`);}));}}}track(t,n){f(this.config)&&this.queue.push(this.buildEvent("track",{event:t,properties:n}));}identify(t,n,o){if(f(this.config)&&(this.userId=t,this.queue.push(this.buildEvent("identify",{traits:n,userId:t})),this.config.autoDetect!==false)){let r=(typeof(o==null?void 0:o.isNew)=="boolean"?o.isNew:ot())?"signup":"login";this.queue.push(this.buildEvent("track",{event:r,properties:{auto:typeof(o==null?void 0:o.isNew)!="boolean"}})),it(),this.config.debug&&console.log(`[IndieBob] ${r} for ${t}`);}}revenue(t){var n;f(this.config)&&this.queue.push(this.buildEvent("revenue",{revenue:{amount:t.amount,currency:(n=t.currency)!=null?n:"USD",plan:t.plan,type:t.type}}));}optOut(){var t,n,o;this.queue.flush(),z(),rt(),this.userId=void 0,(t=this.cleanupAttributes)==null||t.call(this),(n=this.cleanupOutbound)==null||n.call(this),(o=this.cleanupFormSubmit)==null||o.call(this),this.cleanupAttributes=null,this.cleanupOutbound=null,this.cleanupFormSubmit=null,this.config.debug&&console.log("[IndieBob] opted out");}optIn(){X(),this.config.debug&&console.log("[IndieBob] opted in");}isOptedOut(){return J()}flush(){return l(this,null,function*(){yield this.queue.flush();})}getAnonymousId(){return b()}getSessionId(){return E()}getConfig(){return Object.freeze(p({},this.config))}enableAutoPage(){var t;return (t=this.cleanupHistory)==null||t.call(this),this.cleanupHistory=W(()=>this.page()),()=>{var n;(n=this.cleanupHistory)==null||n.call(this),this.cleanupHistory=null;}}buildEvent(t,n){var o,i;return {v:1,projectId:this.config.projectId,type:t,anonymousId:b(),userId:(o=this.userId)!=null?o:n.userId,sessionId:E(),timestamp:new Date().toISOString(),context:(i=n.context)!=null?i:T(),event:n.event,properties:n.properties,traits:n.traits,revenue:n.revenue}}};
2
- exports.IndieBob=lt;return exports;})({});
3
- ;if(typeof IndieBob!=="undefined"&&IndieBob&&IndieBob.IndieBob){IndieBob=Object.assign(IndieBob.IndieBob,IndieBob);}
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 M(e,t,n){for(let o of Object.keys(e))t.split(" ").includes(o)||console.warn(`[IndieBob] Unknown option ${n}"${o}" ignored`);}function j(e){if(!e.projectId||!e.projectId.startsWith("proj_"))throw new Error(`[IndieBob] Invalid projectId "${e.projectId}". Must start with "proj_".`);return M(e,dt,""),typeof e.autoDetect=="object"&&M(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 F(){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=F(),sessionStorage.setItem(_,n)),sessionStorage.setItem(x,String(e)),n}catch{return F()}}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 T(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 B(){try{let e=localStorage.getItem(y);return e?JSON.parse(e):void 0}catch{return}}function z(){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 Y(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 R(){try{return localStorage.getItem(f)==="1"}catch{return false}}function $(){return typeof navigator<"u"&&navigator.webdriver===true||R()}var E="_ib_optout",gt="_ib_queue";function u(e){if($())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 H(){try{localStorage.setItem(E,"1");}catch{}m(),v(),I();try{localStorage.removeItem(gt);}catch{}}function X(){try{localStorage.removeItem(E);}catch{}}function G(){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 V(e,t){try{let n=new URL(e);return n.origin+n.pathname+O(n.search)+(t?D(n.hash):"")}catch{return ""}}function J(e){try{let t=new URL(e);return t.origin+t.pathname}catch{return ""}}function W(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??W(location,t),url:V(location.href,t),title:e?.title??document.title,referrer:J(r===""||bt.test(r)?n&&z()||"":r)},device:{width:i,height:innerHeight,type:i<=768?"mobile":i<=1024?"tablet":"desktop"},utm:k(location.search)??(n?B():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 Q(e,t){for(let[n,o,r]of It)if((t?.[`${n}Paths`]??[r]).some(s=>Et(s,e)))return o;return null}function Z(e){let t=/^(signup|login|checkout)_/.exec(e);return t?t[1]+"_submit":null}function tt(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 et(){return typeof localStorage>"u"?true:!localStorage.getItem(N)}function nt(){typeof localStorage>"u"||localStorage.setItem(N,"1");}function U(){typeof localStorage>"u"||localStorage.removeItem(N);}var ot="data-ib-event",rt="data-ib-";function it(e){for(;e&&e!==document.body;){let t=e.getAttribute(ot);if(t){let n={auto:true};for(let o of e.attributes)o.name.startsWith(rt)&&o.name!==ot&&(n[o.name.slice(rt.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 st(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&&it(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 at(){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 ct(){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{Y(window.location.search,localStorage)&&console.info("IndieBob: this browser is excluded from analytics (ib_ignore)");}catch{}if(this.n&&u(t)&&T(window.location.search,document.referrer),this.r=at(),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=st((o,r)=>this.track(o,r),n.dataAttributes!==false,n.fileDownloads!==false,n.outboundClicks!==false);}}}static init(t){var o;let n=j(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&&ct()){if(this.y=t,!this.c){this.c=true;let o=()=>{this.c&&!ct()&&(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=Q(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=Z(i);s&&(this.a=tt(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:et())?"signup":"login";this.e.push(this.o("track",{event:s,properties:{auto:!r}})),this.n&&nt(),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(),H(),U(),this.d=void 0,this.p?.(),this.a?.(),this.p=null,this.a=null,c(this.t,"opted out");}optIn(){X(),c(this.t,"opted in");}isOptedOut(){return G()}isIgnored(){return R()}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)&&(T(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)}}};function ut(e){let t=e("data-project");if(!t)return null;let n={projectId:t},o=e("data-api");return o&&(n.endpoint=o),e("data-hash-mode")==="true"&&(n.hashMode=true),e("data-persistence")==="local"&&(n.persistence="local"),{config:n,autoPage:e("data-auto-page")!=="false"}}if(typeof document<"u"){let e=document.currentScript,t=e&&ut(n=>e.getAttribute(n));if(t)try{let n=w.init(t.config);t.autoPage&&(n.page(),n.enableAutoPage());}catch(n){console.error(n);}}
2
+ exports.IndieBob=w;return exports;})({});
3
+ ;IndieBob.IndieBob&&(IndieBob=Object.assign(IndieBob.IndieBob,IndieBob));