@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/CHANGELOG.md +89 -0
- package/README.md +112 -389
- package/dist/index.cjs +973 -2
- package/dist/index.d.mts +91 -16
- package/dist/index.d.ts +91 -16
- package/dist/index.global.js +3 -3
- package/dist/index.js +971 -2
- package/dist/server.d.mts +25 -2
- package/dist/server.d.ts +25 -2
- package/dist/server.js +18 -7
- package/dist/server.mjs +18 -7
- package/dist/vue.cjs +997 -2
- package/dist/vue.global.js +3 -3
- package/dist/vue.js +993 -2
- package/package.json +4 -3
- package/dist/chunk-4IK5PET7.js +0 -2
- package/dist/chunk-DZOEO647.js +0 -2
- package/dist/chunk-XKQYO25W.js +0 -2
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
|
|
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
|
-
|
|
136
|
+
/** Absent with `persistence: 'none'`: the server derives the visitor from its daily hash. */
|
|
137
|
+
anonymousId?: string;
|
|
106
138
|
userId?: string;
|
|
107
|
-
|
|
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
|
|
143
|
-
private
|
|
144
|
-
private
|
|
145
|
-
private
|
|
146
|
-
private
|
|
147
|
-
private
|
|
148
|
-
|
|
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
|
-
/**
|
|
274
|
+
/** The stored anonymous ID with `persistence: 'local'`; '' without storage. */
|
|
217
275
|
getAnonymousId(): string;
|
|
218
|
-
/**
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
136
|
+
/** Absent with `persistence: 'none'`: the server derives the visitor from its daily hash. */
|
|
137
|
+
anonymousId?: string;
|
|
106
138
|
userId?: string;
|
|
107
|
-
|
|
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
|
|
143
|
-
private
|
|
144
|
-
private
|
|
145
|
-
private
|
|
146
|
-
private
|
|
147
|
-
private
|
|
148
|
-
|
|
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
|
-
/**
|
|
274
|
+
/** The stored anonymous ID with `persistence: 'local'`; '' without storage. */
|
|
217
275
|
getAnonymousId(): string;
|
|
218
|
-
/**
|
|
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
|
-
|
|
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.global.js
CHANGED
|
@@ -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=
|
|
3
|
-
;
|
|
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));
|