@usermaven/sdk-js 1.4.0 → 1.4.1-rc.59
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/README.md +149 -36
- package/dist/core/client.d.ts +57 -0
- package/dist/core/config.d.ts +37 -0
- package/dist/core/types.d.ts +38 -0
- package/dist/extensions/rage-click.d.ts +15 -0
- package/dist/extensions/scroll-depth.d.ts +19 -0
- package/dist/index.d.ts +6 -0
- package/dist/lib.js +2 -0
- package/dist/persistence/local-storage.d.ts +13 -0
- package/dist/persistence/memory.d.ts +8 -0
- package/dist/tracking/autocapture.d.ts +29 -0
- package/dist/tracking/form-tracking.d.ts +27 -0
- package/dist/tracking/pageviews.d.ts +11 -0
- package/dist/transport/beacon.d.ts +10 -0
- package/dist/transport/fetch.d.ts +13 -0
- package/dist/transport/https.d.ts +11 -0
- package/dist/transport/transport.d.ts +3 -0
- package/dist/transport/xhr.d.ts +12 -0
- package/dist/usermaven.cjs.js +2 -0
- package/dist/usermaven.es.js +1324 -0
- package/dist/utils/autocapture-utils.d.ts +13 -0
- package/dist/utils/common.d.ts +27 -0
- package/dist/utils/cookie.d.ts +14 -0
- package/dist/utils/helpers.d.ts +9 -0
- package/dist/utils/logger.d.ts +15 -0
- package/dist/utils/queue.d.ts +23 -0
- package/package.json +48 -49
- package/LICENSE +0 -23
- package/dist/npm/usermaven.cjs.js +0 -2673
- package/dist/npm/usermaven.d.ts +0 -546
- package/dist/npm/usermaven.es.js +0 -2666
- package/dist/web/lib.js +0 -1
package/README.md
CHANGED
|
@@ -1,51 +1,164 @@
|
|
|
1
|
-
# Usermaven
|
|
1
|
+
# Usermaven SDK
|
|
2
2
|
|
|
3
|
-
Usermaven
|
|
3
|
+
Usermaven SDK is a powerful and flexible JavaScript/TypeScript library for tracking user behavior and events in web applications. It supports both client-side and server-side usage, with a focus on privacy, configurability, and robustness.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Features
|
|
6
6
|
|
|
7
|
-
-
|
|
7
|
+
- Cross-platform compatibility (browser and server-side)
|
|
8
|
+
- Flexible event tracking with custom payloads
|
|
9
|
+
- Automatic tracking of page views, form submissions, and user interactions
|
|
10
|
+
- Privacy-focused with configurable data sanitization
|
|
11
|
+
- Robust error handling and retry mechanisms
|
|
12
|
+
- Extensible architecture for custom tracking features
|
|
13
|
+
- Performance optimizations including event batching and debouncing
|
|
8
14
|
|
|
9
|
-
##
|
|
15
|
+
## Installation
|
|
10
16
|
|
|
11
|
-
|
|
17
|
+
### NPM or Yarn
|
|
12
18
|
|
|
13
|
-
|
|
19
|
+
You can install the Usermaven SDK using npm:
|
|
14
20
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
usermaven in action
|
|
19
|
-
* http://localhost:8081/test-case/embed.html - embedded Usermaven
|
|
20
|
-
- * <http://localhost:8081/test-case/embed_strict_mode.html> - embedded strict mode for Usermaven
|
|
21
|
-
* http://localhost:8081/test-case/autocapture.html - embedded Usermaven with autocapturing events
|
|
22
|
-
* `yarn test` runs [Playwright](https://playwright.dev/) test
|
|
23
|
-
* `yarn build` builds both npm package and `lib.js` browser bundle
|
|
24
|
-
* `npm publish --public` to publish the package (change version in `package.json` manually). You need to run `npm login` with your personal
|
|
25
|
-
npmjs account beforehand (make sure you have access to Usermaven team)
|
|
26
|
-
* In order to check usermaven sdk locally.
|
|
27
|
-
* `cd dist/npm` --- navigate to npm directory
|
|
28
|
-
* `npm link` --- creates a symbolic link to be accessed globally
|
|
29
|
-
* `cd ../../__tests__/sdk/` --- navigate to sdk test project
|
|
30
|
-
* `npm i` --- install npm dependencies
|
|
31
|
-
* `npm link @usermaven/sdk-js` --- use npm package locally whose symlink is just published
|
|
32
|
-
* `npm start` --- start the application and monitor events
|
|
21
|
+
```bash
|
|
22
|
+
npm install @usermaven/sdk-js
|
|
23
|
+
```
|
|
33
24
|
|
|
34
|
-
|
|
35
|
-
Setup a custom domain and sub-domain locally to test cross domain session persistence.
|
|
25
|
+
Or using yarn:
|
|
36
26
|
|
|
37
27
|
```bash
|
|
38
|
-
|
|
28
|
+
yarn add @usermaven/sdk-js
|
|
39
29
|
```
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
30
|
+
|
|
31
|
+
### UMD (Universal Module Definition)
|
|
32
|
+
|
|
33
|
+
For quick integration without a module bundler, you can include the SDK directly in your HTML using a script tag:
|
|
34
|
+
|
|
35
|
+
```html
|
|
36
|
+
<script src="https://cdn.usermaven.com/sdk/v1/lib.js"
|
|
37
|
+
data-key="your-api-key"
|
|
38
|
+
data-tracking-host="https://events.yourdomain.com"
|
|
39
|
+
data-log-level="debug"
|
|
40
|
+
data-autocapture="true"
|
|
41
|
+
data-form-tracking="true"
|
|
42
|
+
data-auto-pageview="true"></script>
|
|
44
43
|
```
|
|
45
44
|
|
|
46
|
-
|
|
45
|
+
Replace `https://cdn.usermaven.com/sdk/v1/lib.js` with the actual URL where the Usermaven SDK is hosted.
|
|
46
|
+
|
|
47
|
+
## Basic Usage
|
|
48
|
+
|
|
49
|
+
### Using as a module
|
|
50
|
+
|
|
51
|
+
```javascript
|
|
52
|
+
import { usermavenClient } from '@usermaven/sdk-js';
|
|
53
|
+
|
|
54
|
+
const client = usermavenClient({
|
|
55
|
+
apiKey: 'your-api-key',
|
|
56
|
+
trackingHost: 'https://events.yourdomain.com',
|
|
57
|
+
// Add other configuration options as needed
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// Track an event
|
|
61
|
+
client.track('button_click', {
|
|
62
|
+
buttonId: 'submit-form',
|
|
63
|
+
pageUrl: window.location.href
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// Identify a user
|
|
67
|
+
client.id({
|
|
68
|
+
id: 'user123',
|
|
69
|
+
email: 'user@example.com',
|
|
70
|
+
name: 'John Doe'
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
// Track a page view
|
|
74
|
+
client.pageview();
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Using via UMD
|
|
78
|
+
|
|
79
|
+
When you include the SDK via a script tag, it automatically initializes with the configuration provided in the data attributes. You can then use the global `usermaven` function to interact with the SDK:
|
|
80
|
+
|
|
81
|
+
```html
|
|
82
|
+
<script>
|
|
83
|
+
// Track an event
|
|
84
|
+
usermaven('track', 'button_click', {
|
|
85
|
+
buttonId: 'submit-form',
|
|
86
|
+
pageUrl: window.location.href
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
// Identify a user
|
|
90
|
+
usermaven('id', {
|
|
91
|
+
id: 'user123',
|
|
92
|
+
email: 'user@example.com',
|
|
93
|
+
name: 'John Doe'
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
// Track a page view (if not set to automatic in the script tag)
|
|
97
|
+
usermaven('pageview');
|
|
98
|
+
</script>
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Advanced Configuration
|
|
102
|
+
|
|
103
|
+
The SDK supports various configuration options to customize its behavior. When using as a module:
|
|
104
|
+
|
|
105
|
+
```javascript
|
|
106
|
+
const client = usermavenClient({
|
|
107
|
+
apiKey: 'your-api-key',
|
|
108
|
+
trackingHost: 'https://events.yourdomain.com',
|
|
109
|
+
cookieDomain: '.yourdomain.com',
|
|
110
|
+
logLevel: 'DEBUG',
|
|
111
|
+
useBeaconApi: true,
|
|
112
|
+
autocapture: true,
|
|
113
|
+
formTracking: 'all',
|
|
114
|
+
autoPageview: true,
|
|
115
|
+
// ... other options
|
|
116
|
+
});
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
When using via UMD, you can set these options using data attributes on the script tag:
|
|
120
|
+
|
|
121
|
+
```html
|
|
122
|
+
<script src="https://cdn.usermaven.com/sdk/v1/lib.js"
|
|
123
|
+
data-key="your-api-key"
|
|
124
|
+
data-tracking-host="https://events.yourdomain.com"
|
|
125
|
+
data-log-level="debug"
|
|
126
|
+
data-autocapture="true"
|
|
127
|
+
data-form-tracking="all"
|
|
128
|
+
data-auto-pageview="true"
|
|
129
|
+
data-use-beacon-api="true"
|
|
130
|
+
data-cookie-domain=".yourdomain.com"></script>
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Refer to the `Config` interface in `src/core/config.ts` for a full list of configuration options.
|
|
134
|
+
|
|
135
|
+
## Server-Side Usage
|
|
136
|
+
|
|
137
|
+
The SDK can also be used in server-side environments:
|
|
138
|
+
|
|
139
|
+
```javascript
|
|
140
|
+
const { usermavenClient } = require('@usermaven/sdk-js');
|
|
141
|
+
|
|
142
|
+
const client = usermavenClient({
|
|
143
|
+
apiKey: 'your-api-key',
|
|
144
|
+
trackingHost: 'https://events.yourdomain.com'
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
client.track('server_event', {
|
|
148
|
+
userId: 'user123',
|
|
149
|
+
action: 'item_purchased'
|
|
150
|
+
});
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Development
|
|
154
|
+
|
|
155
|
+
To set up the project for development:
|
|
156
|
+
|
|
157
|
+
1. Clone the repository
|
|
158
|
+
2. Install dependencies: `npm install`
|
|
159
|
+
3. Run tests: `npm test`
|
|
160
|
+
4. Build the project: `npm run build`
|
|
47
161
|
|
|
48
|
-
|
|
162
|
+
## Contributing
|
|
49
163
|
|
|
50
|
-
|
|
51
|
-
* Run `yarn install && yarn build && yarn test && npm publish --access public`
|
|
164
|
+
Contributions are welcome! Please read our contributing guidelines and code of conduct before submitting pull requests.
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { Config } from './config';
|
|
2
|
+
import { CompanyProps, EventPayload, UserProps } from './types';
|
|
3
|
+
import { Logger } from '../utils/logger';
|
|
4
|
+
export declare class UsermavenClient {
|
|
5
|
+
private config;
|
|
6
|
+
private logger;
|
|
7
|
+
private cookieManager?;
|
|
8
|
+
private transport;
|
|
9
|
+
private persistence;
|
|
10
|
+
private autoCapture?;
|
|
11
|
+
private formTracking?;
|
|
12
|
+
private pageviewTracking?;
|
|
13
|
+
private retryQueue;
|
|
14
|
+
private anonymousId;
|
|
15
|
+
private namespace;
|
|
16
|
+
private rageClick?;
|
|
17
|
+
constructor(config: Config);
|
|
18
|
+
private initializeBrowserFeatures;
|
|
19
|
+
/**
|
|
20
|
+
* Recursively merge the provided configuration with the existing defaultConfig
|
|
21
|
+
* @param config
|
|
22
|
+
* @param defaultConfig
|
|
23
|
+
*/
|
|
24
|
+
mergeConfig(config: Partial<Config>, defaultConfig: Partial<Config>): Config;
|
|
25
|
+
init(config: Config): void;
|
|
26
|
+
private manageCrossDomainLinking;
|
|
27
|
+
private findClosestLink;
|
|
28
|
+
private initializeTransport;
|
|
29
|
+
private initializePersistence;
|
|
30
|
+
private getOrCreateAnonymousId;
|
|
31
|
+
private generateFingerprint;
|
|
32
|
+
private hashString;
|
|
33
|
+
id(userData: UserProps, doNotSendEvent?: boolean): Promise<void>;
|
|
34
|
+
track(typeName: string, payload?: EventPayload, directSend?: boolean): void;
|
|
35
|
+
private trackInternal;
|
|
36
|
+
rawTrack(payload: any): void;
|
|
37
|
+
group(props: CompanyProps, doNotSendEvent?: boolean): Promise<void>;
|
|
38
|
+
private createEventPayload;
|
|
39
|
+
private processAutocaptureAttributes;
|
|
40
|
+
getCookie(name: string): string | null;
|
|
41
|
+
private getThirdPartyIds;
|
|
42
|
+
private getUtmParams;
|
|
43
|
+
pageview(): void;
|
|
44
|
+
private setupPageLeaveTracking;
|
|
45
|
+
getConfig(): Config;
|
|
46
|
+
getLogger(): Logger;
|
|
47
|
+
reset(resetAnonId?: boolean): Promise<void>;
|
|
48
|
+
set(properties: Record<string, any>, opts?: {
|
|
49
|
+
eventType?: string;
|
|
50
|
+
persist?: boolean;
|
|
51
|
+
}): void;
|
|
52
|
+
setUserId(userId: string): void;
|
|
53
|
+
unset(propertyName: string, options?: {
|
|
54
|
+
eventType?: string;
|
|
55
|
+
persist?: boolean;
|
|
56
|
+
}): void;
|
|
57
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { LogLevel } from '../utils/logger';
|
|
2
|
+
export type Policy = 'strict' | 'keep' | 'comply';
|
|
3
|
+
export interface Config {
|
|
4
|
+
key: string;
|
|
5
|
+
trackingHost: string;
|
|
6
|
+
cookieDomain?: string;
|
|
7
|
+
cookieName?: string;
|
|
8
|
+
logLevel?: LogLevel;
|
|
9
|
+
useBeaconApi?: boolean;
|
|
10
|
+
forceUseFetch?: boolean;
|
|
11
|
+
autocapture?: boolean;
|
|
12
|
+
rageClick?: boolean;
|
|
13
|
+
formTracking?: boolean | 'all' | 'tagged' | 'none';
|
|
14
|
+
autoPageview?: boolean;
|
|
15
|
+
disableEventPersistence?: boolean;
|
|
16
|
+
gaHook?: boolean;
|
|
17
|
+
segmentHook?: boolean;
|
|
18
|
+
randomizeUrl?: boolean;
|
|
19
|
+
capture3rdPartyCookies?: string[] | false;
|
|
20
|
+
idMethod?: 'cookie' | 'localStorage';
|
|
21
|
+
privacyPolicy?: 'strict';
|
|
22
|
+
ipPolicy?: Policy;
|
|
23
|
+
cookiePolicy?: Policy;
|
|
24
|
+
customHeaders?: Record<string, string> | (() => Record<string, string>);
|
|
25
|
+
minSendTimeout?: number;
|
|
26
|
+
maxSendTimeout?: number;
|
|
27
|
+
maxSendAttempts?: number;
|
|
28
|
+
propertiesStringMaxLength?: number | null;
|
|
29
|
+
propertyBlacklist?: string[];
|
|
30
|
+
exclude?: string;
|
|
31
|
+
namespace?: string;
|
|
32
|
+
crossDomainLinking?: boolean;
|
|
33
|
+
domains?: string;
|
|
34
|
+
maskAllText?: boolean;
|
|
35
|
+
maskAllElementAttributes?: boolean;
|
|
36
|
+
}
|
|
37
|
+
export declare const defaultConfig: Partial<Config>;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export interface EventPayload {
|
|
2
|
+
[key: string]: any;
|
|
3
|
+
}
|
|
4
|
+
export interface UserProps extends EventPayload {
|
|
5
|
+
id?: string;
|
|
6
|
+
email?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface Transport {
|
|
9
|
+
send(payload: any): Promise<void>;
|
|
10
|
+
}
|
|
11
|
+
export interface UserProps {
|
|
12
|
+
id?: string;
|
|
13
|
+
email?: string;
|
|
14
|
+
[key: string]: any;
|
|
15
|
+
}
|
|
16
|
+
export type Policy = 'strict' | 'keep' | 'comply';
|
|
17
|
+
export interface CompanyProps {
|
|
18
|
+
id: string;
|
|
19
|
+
name: string;
|
|
20
|
+
created_at: string;
|
|
21
|
+
[key: string]: any;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Environment where the event have happened.
|
|
25
|
+
*/
|
|
26
|
+
export type ClientProperties = {
|
|
27
|
+
screen_resolution: string;
|
|
28
|
+
user_agent: string;
|
|
29
|
+
referer: string;
|
|
30
|
+
url: string;
|
|
31
|
+
page_title: string;
|
|
32
|
+
doc_path: string;
|
|
33
|
+
doc_host: string;
|
|
34
|
+
doc_search: string;
|
|
35
|
+
vp_size: string;
|
|
36
|
+
user_language: string;
|
|
37
|
+
doc_encoding: string;
|
|
38
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { UsermavenClient } from '../core/client';
|
|
2
|
+
export declare class RageClick {
|
|
3
|
+
private client;
|
|
4
|
+
private clicks;
|
|
5
|
+
private threshold;
|
|
6
|
+
private timeWindow;
|
|
7
|
+
private distanceThreshold;
|
|
8
|
+
constructor(client: UsermavenClient);
|
|
9
|
+
private initializeEventListener;
|
|
10
|
+
private handleClick;
|
|
11
|
+
private shouldCaptureElement;
|
|
12
|
+
click(x: number, y: number, timestamp: number): void;
|
|
13
|
+
private checkRageClick;
|
|
14
|
+
private sendRageClickEvent;
|
|
15
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { UsermavenClient } from '../core/client';
|
|
2
|
+
export declare class ScrollDepth {
|
|
3
|
+
private client;
|
|
4
|
+
private maxScrollDepth;
|
|
5
|
+
private milestones;
|
|
6
|
+
private lastScrollDepth;
|
|
7
|
+
private documentElement;
|
|
8
|
+
private debouncedHandleScroll;
|
|
9
|
+
constructor(client: UsermavenClient);
|
|
10
|
+
private initializeEventListener;
|
|
11
|
+
track(): void;
|
|
12
|
+
send(eventType?: string): void;
|
|
13
|
+
private handleScroll;
|
|
14
|
+
private getScrollDepth;
|
|
15
|
+
private getWindowHeight;
|
|
16
|
+
private getDocumentHeight;
|
|
17
|
+
private getScrollDistance;
|
|
18
|
+
private checkMilestones;
|
|
19
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { UsermavenClient } from './core/client';
|
|
2
|
+
import { Config } from './core/config';
|
|
3
|
+
import { LogLevel } from './utils/logger';
|
|
4
|
+
import { UserProps, EventPayload, ClientProperties } from './core/types';
|
|
5
|
+
declare function usermavenClient(config: Partial<Config>): UsermavenClient;
|
|
6
|
+
export { usermavenClient, UsermavenClient, Config as UsermavenOptions, UserProps, EventPayload, LogLevel, ClientProperties };
|
package/dist/lib.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
(function(f,g){typeof exports=="object"&&typeof module<"u"?g(exports):typeof define=="function"&&define.amd?define(["exports"],g):(f=typeof globalThis<"u"?globalThis:f||self,g(f.Usermaven={}))})(this,function(f){"use strict";var g=(s=>(s[s.DEBUG=0]="DEBUG",s[s.INFO=1]="INFO",s[s.WARN=2]="WARN",s[s.ERROR=3]="ERROR",s))(g||{});class X{constructor(e){this.level=e}debug(e,...t){this.level<=0&&console.debug("[Usermaven Debug]:",e,...t)}info(e,...t){this.level<=1&&console.info("[Usermaven Info]:",e,...t)}warn(e,...t){this.level<=2&&console.warn("[Usermaven Warning]:",e,...t)}error(e,...t){this.level<=3&&console.error("[Usermaven Error]:",e,...t)}}function h(s=0){return new X(s)}const N={logLevel:g.ERROR,useBeaconApi:!1,forceUseFetch:!1,trackingHost:"t.usermaven.com",autocapture:!1,rageClick:!1,formTracking:!1,autoPageview:!1,disableEventPersistence:!1,gaHook:!1,segmentHook:!1,randomizeUrl:!1,capture3rdPartyCookies:["_ga","_fbp","_ym_uid","ajs_user_id","ajs_anonymous_id"],idMethod:"cookie",ipPolicy:"keep",cookiePolicy:"keep",minSendTimeout:0,maxSendTimeout:2e3,maxSendAttempts:4,propertiesStringMaxLength:null,propertyBlacklist:[],crossDomainLinking:!0,maskAllText:!1,maskAllElementAttributes:!1};class K{constructor(e){this.domain=e,this.cookieDomain=this.getCookieDomain(),console.log(this.cookieDomain)}set(e,t,i=365,n=!0,r=!1){console.log("Setting cookie",e,t,i,n,r);const o=new Date;o.setTime(o.getTime()+i*24*60*60*1e3);const c=`expires=${o.toUTCString()}`,l=n?"; Secure":"",a=r?"; HttpOnly":"";document.cookie=`${e}=${t};${c};path=/;domain=${this.cookieDomain}${l}${a}`}get(e){const t=e+"=",i=document.cookie.split(";");for(let n=0;n<i.length;n++){let r=i[n].trim();if(r.indexOf(t)===0)return decodeURIComponent(r.substring(t.length))}return null}delete(e,t="/"){document.cookie=`${e}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=${t};domain=${this.cookieDomain}`}getCookieDomain(){return typeof window>"u"||this.domain?this.domain||"":this.extractRoot(window.location.hostname)}extractRoot(e){if(this.isIpAddress(e)||e==="localhost")return e;let t=this.extractTopLevelDomain(e);return t||(t=this.extractRootDomain(e)),"."+t}isIpAddress(e){const t=e.split(".");return t.length===4&&t.every(i=>!isNaN(Number(i)))}extractHostname(e){let t;return e.indexOf("//")>-1?t=e.split("/")[2]:t=e.split("/")[0],t=t.split(":")[0],t=t.split("?")[0],t}extractRootDomain(e){let t=this.extractHostname(e);const i=t.split("."),n=i.length;return n>2&&(i[n-1].length==2?(t=i[n-2]+"."+i[n-1],i[n-2].length==2&&(t=i[n-3]+"."+t)):t=i[n-2]+"."+i[n-1]),t}extractTopLevelDomain(e){const t=/[a-z0-9][a-z0-9-]+\.[a-z.]{2,6}$/i,i=e.match(t);return i?i[0]:""}}const Z=Object.prototype.hasOwnProperty,b=Array.prototype.forEach,$={};function G(s,e,t){if(Array.isArray(s)){if(b&&s.forEach===b)s.forEach(e,t);else if("length"in s&&s.length===+s.length){for(let i=0,n=s.length;i<n;i++)if(i in s&&e.call(t,s[i],i)===$)return}}}const T=function(s){return s.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,"")},Y=function(s){for(const e in s)typeof s[e]=="function"&&(s[e]=s[e].bind(s))};function A(s,e,t){if(s!=null){if(b&&Array.isArray(s)&&s.forEach===b)s.forEach(e,t);else if("length"in s&&s.length===+s.length){for(let i=0,n=s.length;i<n;i++)if(i in s&&e.call(t,s[i],i)===$)return}else for(const i in s)if(Z.call(s,i)&&e.call(t,s[i],i)===$)return}}const j=function(s,...e){return G(e,function(t){for(const i in t)t[i]!==void 0&&(s[i]=t[i])}),s};function E(s,e){return s.indexOf(e)!==-1}const O=function(s){try{return/^\s*\bfunction\b/.test(s)}catch{return!1}},ee=function(s){return s===void 0},y=function(){const s=function(i,n,r,o,c){if(!i){h().error("No valid element provided to register_event");return}if(i.addEventListener&&!o)i.addEventListener(n,r,!!c);else{const l="on"+n,a=i[l];i[l]=e(i,r,a)}};function e(i,n,r){return function(o){if(o=o||t(window.event),!o)return;let c=!0,l;O(r)&&(l=r(o));const a=n.call(i,o);return(l===!1||a===!1)&&(c=!1),c}}function t(i){return i&&(i.preventDefault=t.preventDefault,i.stopPropagation=t.stopPropagation),i}return t.preventDefault=function(){this.returnValue=!1},t.stopPropagation=function(){this.cancelBubble=!0},s}(),te=function(s){return function(...e){try{return s.apply(this,e)}catch(t){h().error("Implementation error. Please turn on debug and contact support@usermaven.com.",t)}}},L=function(s){for(const e in s)typeof s[e]=="function"&&(s[e]=te(s[e]))};function U(s){for(let e in s)(s[e]===""||s[e]===null||s[e]===void 0||typeof s[e]=="object"&&Object.keys(s[e]).length===0)&&delete s[e];return s}function u(){try{return typeof window<"u"&&window.document!==void 0&&window.document.createElement!==void 0}catch{return h().warn("window is not available"),!1}}function m(s=5){const e=new Uint8Array(s);return crypto.getRandomValues(e),Array.from(e,t=>t.toString(36).padStart(2,"0")).join("").slice(0,s)}function ie(s){return s.replace(/([-_][a-z])/g,e=>e.toUpperCase().replace("-","").replace("_",""))}function S(s){return typeof s!="object"||s===null?s:Array.isArray(s)?s.map(S):Object.keys(s).reduce((e,t)=>{const i=ie(t);return e[i]=S(s[t]),e},{})}function P(s){switch(typeof s.className){case"string":return s.className;case"object":return("baseVal"in s.className?s.className.baseVal:null)||s.getAttribute("class")||"";default:return""}}function I(s){let e="";return z(s)&&!M(s)&&s.childNodes&&s.childNodes.length&&A(s.childNodes,function(t){D(t)&&t.textContent&&(e+=T(t.textContent).split(/(\s+)/).filter(H).join("").replace(/[\r\n]/g," ").replace(/[ ]+/g," ").substring(0,255))}),T(e)}function C(s){return!!s&&s.nodeType===1}function p(s,e){return!!s&&!!s.tagName&&s.tagName.toLowerCase()===e.toLowerCase()}function D(s){return!!s&&s.nodeType===3}function F(s){return!!s&&s.nodeType===11}const x=["a","button","form","input","select","textarea","label"];function se(s,e){if(!s||p(s,"html")||!C(s)||s.classList&&s.classList.contains("um-no-capture"))return!1;let t=!1;const i=[s];let n=!0,r=s;for(;r.parentNode&&!p(r,"body");){if(F(r.parentNode)){i.push(r.parentNode.host),r=r.parentNode.host;continue}if(n=r.parentNode||!1,!n)break;if(x.indexOf(n.tagName.toLowerCase())>-1)t=!0;else{const l=window.getComputedStyle(n);l&&l.getPropertyValue("cursor")==="pointer"&&(t=!0)}i.push(n),r=n}const o=window.getComputedStyle(s);if(o&&o.getPropertyValue("cursor")==="pointer"&&e.type==="click")return!0;const c=s.tagName.toLowerCase();switch(c){case"html":return!1;case"form":return e.type==="submit";case"input":return e.type==="change"||e.type==="click";case"select":case"textarea":return e.type==="change"||e.type==="click";default:return t?e.type==="click":e.type==="click"&&(x.indexOf(c)>-1||s.getAttribute("contenteditable")==="true")}}function z(s){if(!s||!C(s))return!1;if(typeof s.hasAttribute=="function"){if(s.hasAttribute(w.FORCE_CAPTURE_ATTR))return!0;if(s.hasAttribute(w.PREVENT_CAPTURE_ATTR))return!1}let e=s;for(;e&&e.parentElement&&!p(e,"body");){const n=P(e).split(" ");if(E(n,"ph-sensitive")||E(n,"ph-no-capture"))return!1;e=e.parentElement}if(E(P(s).split(" "),"ph-include"))return!0;const t=s.type;if(typeof t=="string")switch(t.toLowerCase()){case"hidden":case"password":return!1}const i=s.name||s.id||"";return!(typeof i=="string"&&/^cc|cardnum|ccnum|creditcard|csc|cvc|cvv|exp|pass|pwd|routing|seccode|securitycode|securitynum|socialsec|socsec|ssn/i.test(i.replace(/[^a-zA-Z0-9]/g,"")))}function M(s){const e=["button","checkbox","submit","reset"];return!!(p(s,"input")&&!e.includes(s.type)||p(s,"select")||p(s,"textarea")||s.getAttribute("contenteditable")==="true")}function H(s){return!(s===null||ee(s)||typeof s=="string"&&(s=T(s),/^(?:(4[0-9]{12}(?:[0-9]{3})?)|(5[1-5][0-9]{14})|(6(?:011|5[0-9]{2})[0-9]{12})|(3[47][0-9]{13})|(3(?:0[0-5]|[68][0-9])[0-9]{11})|((?:2131|1800|35[0-9]{3})[0-9]{11}))$/.test((s||"").replace(/[- ]/g,""))||/(^\d{3}-?\d{2}-?\d{4}$)/.test(s)))}function ne(s){return typeof s=="string"?s.substring(0,10)==="_ngcontent"||s.substring(0,7)==="_nghost":!1}function R(){return m(10)}function re(s){return/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(String(s).toLowerCase())}function oe(s,e){let t;return function(...i){const n=()=>{clearTimeout(t),s(...i)};clearTimeout(t),t=setTimeout(n,e)}}function ae(s){const e={},t=s.replace(/^\?/,"").split("&");for(let i=0;i<t.length;i++){const n=t[i].split("=");n[0]!==""&&(e[decodeURIComponent(n[0])]=decodeURIComponent(n[1]||""))}return e}function B(s){return typeof s=="string"||s instanceof String}function _(s){return s!==null&&typeof s=="object"&&s.constructor===Object}function ce(s){if(s===null)return g.ERROR;const e=s.toUpperCase(),t=g[e];return t||t===0?t:g.ERROR}class le{constructor(e){this.maxScrollDepth=0,this.milestones=[25,50,75,90],this.lastScrollDepth=0,this.client=e,this.documentElement=document.documentElement,this.debouncedHandleScroll=oe(this.handleScroll.bind(this),250),this.initializeEventListener()}initializeEventListener(){window.addEventListener("scroll",this.debouncedHandleScroll)}track(){const e=this.getScrollDepth();e>this.lastScrollDepth&&(this.lastScrollDepth=e,this.checkMilestones(e))}send(e="$scroll"){const t={percent:this.lastScrollDepth,window_height:this.getWindowHeight(),document_height:this.getDocumentHeight(),scroll_distance:this.getScrollDistance()};this.client.track(e,t)}handleScroll(){this.track()}getScrollDepth(){const e=this.getWindowHeight(),t=this.getDocumentHeight(),i=this.getScrollDistance(),n=t-e;return Math.min(100,Math.floor(i/n*100))}getWindowHeight(){return window.innerHeight||this.documentElement.clientHeight||document.body.clientHeight||0}getDocumentHeight(){return Math.max(document.body.scrollHeight||0,this.documentElement.scrollHeight||0,document.body.offsetHeight||0,this.documentElement.offsetHeight||0,document.body.clientHeight||0,this.documentElement.clientHeight||0)}getScrollDistance(){return window.pageYOffset||this.documentElement.scrollTop||document.body.scrollTop||0}checkMilestones(e){this.milestones.filter(i=>e>=i).forEach(i=>{this.send(),this.milestones=this.milestones.filter(n=>n!==i)})}}const v=class v{constructor(e,t,i=h()){this.logger=i,this.scrollDepth=null,this.client=e,this.options=t,this.scrollDepth=new le(e),Y(this),L(this)}init(){if(!(document&&document.body)){this.logger.debug("Document not ready yet, trying again in 500 milliseconds..."),setTimeout(()=>this.init(),500);return}this.addDomEventHandlers()}addDomEventHandlers(){const e=t=>{t=t||window.event,this.captureEvent(t)};y(document,"submit",e,!1,!0),y(document,"change",e,!1,!0),y(document,"click",e,!1,!0),y(document,"visibilitychange",e,!1,!0),y(document,"scroll",e,!1,!0),y(window,"popstate",e,!1,!0)}isPageRefresh(){if("PerformanceNavigationTiming"in window){const e=performance.getEntriesByType("navigation");if(e.length>0)return e[0].type==="reload"}return performance.navigation&&performance.navigation.type===1}captureEvent(e){var i,n;let t=this.getEventTarget(e);if(D(t)&&(t=t.parentNode||null),e.type==="scroll")return(i=this.scrollDepth)==null||i.track(),!0;if(e.type==="visibilitychange"&&document.visibilityState==="hidden"||e.type==="popstate")return this.isPageRefresh()||(n=this.scrollDepth)==null||n.send(),!0;if(t&&this.shouldCaptureElement(t,e)){const r=this.getElementList(t),o=this.getElementsJson(r,e),c=j(this.getDefaultProperties(e.type),{$elements:o});return this.client.track("$autocapture",c),!0}}shouldCaptureElement(e,t){return!e||typeof e.hasAttribute!="function"?!1:e.hasAttribute(v.FORCE_CAPTURE_ATTR)?!0:e.hasAttribute(v.PREVENT_CAPTURE_ATTR)?!1:se(e,t)}getEventTarget(e){var t;return typeof e.target>"u"?e.srcElement||null:(t=e.target)!=null&&t.shadowRoot?e.composedPath()[0]||null:e.target||null}getElementList(e){const t=[e];let i=e;for(;i.parentNode&&!p(i,"body");)F(i.parentNode)?(t.push(i.parentNode.host),i=i.parentNode.host):(t.push(i.parentNode),i=i.parentNode);return t}getElementsJson(e,t){const i=[];let n=null,r=!1;return A(e,o=>{if(p(o,"a")){const l=o.getAttribute("href");l!==null&&z(o)&&H(l)&&(n=l)}const c=P(o).split(" ");E(c,"ph-no-capture")&&(r=!0),i.push(this.getPropertiesFromElement(o))}),this.options.maskAllText||(i[0].$el_text=this.sanitizeText(I(e[0]))),n!==null&&(i[0].attr__href=n),r?[]:i}getPropertiesFromElement(e){const t={tag_name:e.tagName.toLowerCase()};x.indexOf(t.tag_name)>-1&&!this.options.maskAllText&&(t.$el_text=this.sanitizeText(I(e)));const i=P(e);i.length>0&&(t.classes=i.split(" ").filter(c=>c!=="")),A(e.attributes,c=>{M(e)&&["name","id","class"].indexOf(c.name)===-1||!this.options.maskAllElementAttributes&&H(c.value)&&!ne(c.name)&&(t["attr__"+c.name]=this.sanitizeAttributeValue(c.name,c.value))});let n=1,r=1,o=e;for(;o=this.previousElementSibling(o);)n++,o.tagName===e.tagName&&r++;return t.nth_child=n,t.nth_of_type=r,t}previousElementSibling(e){if(e.previousElementSibling)return e.previousElementSibling;do e=e.previousSibling;while(e&&!C(e));return e}getDefaultProperties(e){return{$event_type:e,$ce_version:1}}sanitizeText(e){e=e.replace(/<[^>]*?>/g,""),e=this.encodeHtml(e);const t=this.options.propertiesStringMaxLength||255;return e.length>t&&(e=e.substring(0,t)+"..."),e}sanitizeUrl(e){if(!e)return"";try{const t=new URL(e,window.location.href);return t.protocol!=="http:"&&t.protocol!=="https:"?"":encodeURI(t.toString())}catch{return this.encodeHtml(e)}}sanitizeAttributeValue(e,t){switch(e.toLowerCase()){case"href":case"src":return this.sanitizeUrl(t);default:return this.encodeHtml(t)}}encodeHtml(e){return e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}static enabledForProject(e,t=10,i=10){if(!e)return!1;let n=0;for(let r=0;r<e.length;r++)n+=e.charCodeAt(r);return n%t<i}static isBrowserSupported(){return O(document.querySelectorAll)}};v.FORCE_CAPTURE_ATTR="data-um-force-capture",v.PREVENT_CAPTURE_ATTR="data-um-no-capture";let w=v;class ue{constructor(e){this.client=e,this.lastPageUrl=window.location.href,this.trackInitialPageview(),this.initializePageviewTracking()}trackInitialPageview(){this.trackPageview()}initializePageviewTracking(){window.addEventListener("popstate",this.handlePageview.bind(this));const e=history.pushState;history.pushState=(...t)=>{e.apply(history,t),this.handlePageview()},window.addEventListener("hashchange",this.handlePageview.bind(this)),setInterval(this.checkForUrlChange.bind(this),1e3)}handlePageview(){this.trackPageview()}checkForUrlChange(){window.location.href!==this.lastPageUrl&&this.trackPageview()}trackPageview(){const e=window.location.href;e!==this.lastPageUrl&&(this.lastPageUrl=e,this.client.track("pageview",{url:e,referrer:document.referrer,title:document.title}))}}class he{constructor(e,t,i=h()){this.trackingHost=e,this.logger=i,this.config=t}async send(e){const t=this.config.key,i=this.constructUrl(t),n=new Blob([JSON.stringify(e)],{type:"application/json"});if(navigator.sendBeacon(i,n))this.logger.debug(`Successfully queued ${e.length} event(s) via Beacon API`);else throw new Error("Failed to queue events via Beacon API")}constructUrl(e){const t=this.config.cookiePolicy!=="keep"?`&cookie_policy=${this.config.cookiePolicy}`:"",i=this.config.ipPolicy!=="keep"?`&ip_policy=${this.config.ipPolicy}`:"",n=u()?"/api/v1/event":"/api/v1/s2s/event";return this.config.randomizeUrl?`${this.trackingHost}/api.${m()}?p_${m()}=${e}${t}${i}`:`${this.trackingHost}${n}?token=${e}${t}${i}`}}class q{constructor(e,t,i=h()){this.trackingHost=e,this.logger=i,this.config=t}async send(e){const t=this.config.key,i=this.constructUrl(t),n=JSON.stringify(e),r={"Content-Type":"application/json",...this.getCustomHeaders()},o=await fetch(i,{method:"POST",headers:r,body:n});if(!o.ok)throw new Error(`HTTP error! status: ${o.status}`);this.logger.debug(`Successfully sent ${e.length} event(s)`),this.postHandle(o.status,await o.text())}constructUrl(e){const t=this.config.cookiePolicy!=="keep"?`&cookie_policy=${this.config.cookiePolicy}`:"",i=this.config.ipPolicy!=="keep"?`&ip_policy=${this.config.ipPolicy}`:"",n=u()?"/api/v1/event":"/api/v1/s2s/event";return this.config.randomizeUrl?`${this.trackingHost}/api.${m()}?p_${m()}=${e}${t}${i}`:`${this.trackingHost}${n}?token=${e}${t}${i}`}getCustomHeaders(){return typeof this.config.customHeaders=="function"?this.config.customHeaders():this.config.customHeaders?this.config.customHeaders:{}}postHandle(e,t){this.logger.debug(`Response received. Status: ${e}, Body: ${t}`)}}class ge{constructor(e,t,i=h()){this.trackingHost=e,this.logger=i,this.config=t}send(e){return new Promise((t,i)=>{const n=new XMLHttpRequest,r=this.config.key,o=this.constructUrl(r);n.open("POST",o,!0),n.setRequestHeader("Content-Type","application/json");const c=this.getCustomHeaders();Object.keys(c).forEach(l=>{n.setRequestHeader(l,c[l])}),n.onload=()=>{n.status>=200&&n.status<300?(this.logger.debug(`Successfully sent ${e.length} event(s)`),t()):i(new Error(`HTTP error! status: ${n.status}`))},n.onerror=()=>{i(new Error("Network error"))},n.send(JSON.stringify(e))})}constructUrl(e){const t=this.config.cookiePolicy!=="keep"?`&cookie_policy=${this.config.cookiePolicy}`:"",i=this.config.ipPolicy!=="keep"?`&ip_policy=${this.config.ipPolicy}`:"",n=u()?"/api/v1/event":"/api/v1/s2s/event";return this.config.randomizeUrl?`${this.trackingHost}/api.${m()}?p_${m()}=${e}${t}${i}`:`${this.trackingHost}${n}?token=${e}${t}${i}`}getCustomHeaders(){return typeof this.config.customHeaders=="function"?this.config.customHeaders():this.config.customHeaders?this.config.customHeaders:{}}postHandle(e,t){this.logger.debug(`Response received. Status: ${e}, Body: ${t}`)}}class V{constructor(e,t){this.storage={},this.prefix=`usermaven_${e}_`,this.load(),this.logger=t||h()}set(e,t){this.storage[e]=t,this.save()}get(e){return this.storage[e]}remove(e){delete this.storage[e],this.save()}clear(){this.storage={},this.save()}save(){if(!u()){this.logger.warn("localStorage is not available in this environment");return}try{localStorage.setItem(this.prefix+"data",JSON.stringify(this.storage))}catch(e){this.logger.error("Error saving to localStorage:",e)}}load(){if(!u()){this.logger.warn("localStorage is not available in this environment");return}try{const e=localStorage.getItem(this.prefix+"data");e&&(this.storage=JSON.parse(e))}catch(e){this.logger.error("Error loading from localStorage:",e)}}}class de{constructor(){this.storage={}}set(e,t){this.storage[e]=t}get(e){return this.storage[e]}remove(e){delete this.storage[e]}save(){}clear(){this.storage={}}}class J{constructor(e,t=3,i=1e3,n=10,r=1e3,o=h()){this.transport=e,this.maxRetries=t,this.retryInterval=i,this.batchSize=n,this.batchInterval=r,this.logger=o,this.queue=[],this.processing=!1,this.batchTimeoutId=null,this.isOnline=!0,this.persistence=new V("offline_queue"),u()&&(this.isOnline=navigator.onLine,this.loadQueueFromStorage(),this.initNetworkListeners(),this.scheduleBatch())}add(e){const t={payload:e,retries:0,timestamp:Date.now()};this.queue.push(t),u()?this.saveQueueToStorage():this.processBatch()}initNetworkListeners(){u()&&(window.addEventListener("online",()=>{this.isOnline=!0,this.processBatch()}),window.addEventListener("offline",()=>{this.isOnline=!1}))}scheduleBatch(){u()&&(this.batchTimeoutId!==null&&clearTimeout(this.batchTimeoutId),this.batchTimeoutId=window.setTimeout(()=>this.processBatch(),this.batchInterval))}async processBatch(){if((!u()||this.isOnline)&&!this.processing&&this.queue.length>0){this.processing=!0;const e=this.queue.splice(0,this.batchSize),t=e.map(i=>i.payload);try{await this.transport.send(t),this.logger.debug(`Successfully sent batch of ${e.length} payloads`),u()&&this.saveQueueToStorage()}catch(i){this.logger.error("Failed to send batch",i),await this.handleBatchFailure(e)}this.processing=!1}u()&&this.scheduleBatch()}async handleBatchFailure(e){for(const t of e)t.retries<this.maxRetries?(t.retries++,this.queue.unshift(t),this.logger.warn(`Retry attempt ${t.retries} for payload`)):this.logger.error("Max retries reached, discarding payload",t.payload);u()&&(this.saveQueueToStorage(),await new Promise(t=>setTimeout(t,this.retryInterval)))}loadQueueFromStorage(){if(u()){const e=this.persistence.get("queue");e&&(this.queue=JSON.parse(e))}}saveQueueToStorage(){u()&&this.persistence.set("queue",JSON.stringify(this.queue))}}class fe{constructor(e){this.clicks=[],this.threshold=3,this.timeWindow=2e3,this.distanceThreshold=30,this.client=e,this.initializeEventListener(),L(this)}initializeEventListener(){document.addEventListener("click",this.handleClick.bind(this))}handleClick(e){const t=e.target;this.shouldCaptureElement(t)&&this.click(e.clientX,e.clientY,Date.now())}shouldCaptureElement(e){return!e.closest(".um-no-capture")}click(e,t,i){const n={x:e,y:t,timestamp:i};this.clicks.push(n),this.clicks=this.clicks.filter(r=>i-r.timestamp<this.timeWindow),this.clicks.length>=this.threshold&&this.checkRageClick()}checkRageClick(){const e=this.clicks[0],i=(this.clicks[this.clicks.length-1].timestamp-e.timestamp)/1e3;this.clicks.every((r,o)=>{if(o===0)return!0;const c=this.clicks[o-1];return Math.sqrt(Math.pow(r.x-c.x,2)+Math.pow(r.y-c.y,2))<this.distanceThreshold})&&this.sendRageClickEvent(i)}sendRageClickEvent(e){const t=this.clicks[this.clicks.length-1];document.elementFromPoint(t.x,t.y)&&this.client.track("$rage_click",{no_of_clicks:this.clicks.length,time:e.toFixed(2)}),this.clicks=[]}}class pe{constructor(e,t,i=h()){this.trackingHost=e,this.logger=i,this.config=t}async send(e){const t=this.config.key,i=new(void 0)(this.constructUrl(t)),n={hostname:i.hostname,port:443,path:`${i.pathname}${i.search}`,method:"POST",headers:{"Content-Type":"application/json",...this.getCustomHeaders()}};return new Promise((r,o)=>{const c=(void 0)(n,l=>{l.on("data",a=>{}),l.on("end",()=>{const a=l.statusCode||0;a>=200&&a<300?(this.logger.debug(`Successfully sent ${e.length} event(s)`),r()):o(new Error(`HTTP error! status: ${a}`))})});c.on("error",l=>{o(l)}),c.write(JSON.stringify(e)),c.end()})}constructUrl(e){const t=this.config.cookiePolicy!=="keep"?`&cookie_policy=${this.config.cookiePolicy}`:"",i=this.config.ipPolicy!=="keep"?`&ip_policy=${this.config.ipPolicy}`:"";return`${this.trackingHost}/api/v1/s2s/event?token=${e}${t}${i}`}getCustomHeaders(){return typeof this.config.customHeaders=="function"?this.config.customHeaders():this.config.customHeaders?this.config.customHeaders:{}}}class k{constructor(e,t="all",i={}){this.instance=e,this.trackingType=t,this.options=i,document.readyState==="loading"?document.addEventListener("DOMContentLoaded",this.initialize.bind(this)):this.initialize()}initialize(){this.trackingType!=="none"&&this.setupFormTracking()}setupFormTracking(){var e;this.formElements=this.trackingType==="tagged"?document.querySelectorAll("form[data-um-form]"):document.querySelectorAll("form"),(e=this.formElements)==null||e.forEach(t=>{t.addEventListener("submit",this.handleFormSubmit.bind(this))})}handleFormSubmit(e){const t=e.target,i=this._getFormDetails(t);this.instance.track("$form",U(i)),this.options.trackFieldChanges&&this.trackFieldChanges(t)}trackFieldChanges(e){e.querySelectorAll("input, select, textarea").forEach(i=>{i.addEventListener("change",n=>{const r=this._getFieldProps(n.target,0);this.instance.track("$form_field_change",U(r))})})}static getInstance(e,t="all",i={}){return k.instance||(k.instance=new k(e,t,i)),k.instance}_getFormDetails(e){const t={form_id:e.id,form_name:e.name||"",form_action:e.action,form_method:e.method,form_class:e.className,form_attributes:this._getElementAttributes(e)},i=e.querySelectorAll("input, select, textarea");return Array.from(i).filter(r=>!r.classList.contains("um-no-capture")).forEach((r,o)=>{const c=this._getFieldProps(r,o);Object.assign(t,c)}),t}_getFieldProps(e,t){const i=Object.keys(e.dataset).length?JSON.stringify(e.dataset):void 0,n=this.getSafeText(e);return{[`field_${t+1}_tag`]:e.tagName.toLowerCase(),[`field_${t+1}_type`]:e instanceof HTMLInputElement?e.type:void 0,[`field_${t+1}_data_attributes`]:i,[`field_${t+1}_id`]:e.id,[`field_${t+1}_value`]:n,[`field_${t+1}_class`]:e.className,[`field_${t+1}_name`]:e.name,[`field_${t+1}_attributes`]:this._getElementAttributes(e)}}_getElementAttributes(e){const t={};for(let i=0;i<e.attributes.length;i++){const n=e.attributes[i];n.name!=="value"&&!n.name.startsWith("data-")&&(t[n.name]=n.value)}return t}getSafeText(e){let t="";return"value"in e&&e.type!=="password"?t=e.value:e.hasChildNodes()?t=Array.from(e.childNodes).filter(n=>n.nodeType===Node.TEXT_NODE).map(n=>n.textContent).join(""):t=e.textContent||"",this._scrubPotentiallySensitiveValues(t)}_scrubPotentiallySensitiveValues(e){return this._shouldCaptureValue(e)?e:"<redacted>"}_shouldCaptureValue(e){return!(this._isNullish(e)||this._isString(e)&&(e=this._trim(e),/^(?:(4[0-9]{12}(?:[0-9]{3})?)|(5[1-5][0-9]{14})|(6(?:011|5[0-9]{2})[0-9]{12})|(3[47][0-9]{13})|(3(?:0[0-5]|[68][0-9])[0-9]{11})|((?:2131|1800|35[0-9]{3})[0-9]{11}))$/.test((e||"").replace(/[- ]/g,""))||/(^\d{3}-?\d{2}-?\d{4}$)/.test(e)))}_isNullish(e){return e==null}_isString(e){return typeof e=="string"||e instanceof String}_trim(e){if(typeof String.prototype.trim=="function")return e.trim();let t=0,i=e.length-1;const n=[" ",`
|
|
2
|
+
`,"\r"," ","\f","\v"," "," "," "," "," "," "," "," "," "," "," "," "," ","\u2028","\u2029"," "," "," "].join("");for(;t<=i&&n.indexOf(e[t])>-1;)t++;for(;i>=t&&n.indexOf(e[i])>-1;)i--;return e.slice(t,i+1)}}class Q{constructor(e){this.config=this.mergeConfig(e,N),this.logger=h(this.config.logLevel),this.namespace=e.namespace||"usermaven",this.transport=this.initializeTransport(this.config),this.persistence=this.initializePersistence(),this.retryQueue=new J(this.transport,this.config.maxSendAttempts||3,this.config.minSendTimeout||1e3,10,200,this.logger),u()&&this.initializeBrowserFeatures(),this.anonymousId=this.getOrCreateAnonymousId(),this.logger.info(`Usermaven client initialized for namespace: ${this.namespace}`)}initializeBrowserFeatures(){if(this.cookieManager=new K(this.config.cookieDomain),this.config.autocapture&&w.enabledForProject(this.config.key)&&(this.autoCapture=new w(this,this.config,this.logger),this.autoCapture.init()),this.config.formTracking){const e=this.config.formTracking===!0?"all":this.config.formTracking;this.formTracking=k.getInstance(this,e||"none",{trackFieldChanges:!1})}this.config.autoPageview&&(this.pageviewTracking=new ue(this)),this.config.crossDomainLinking&&this.manageCrossDomainLinking(),this.config.rageClick&&(this.rageClick=new fe(this)),this.setupPageLeaveTracking()}mergeConfig(e,t){const i=JSON.parse(JSON.stringify(e));let n={...t,...i};return Object.keys(t).forEach(r=>{_(t[r])&&(n[r]=this.mergeConfig(e[r],t[r]))}),n}init(e){this.config={...this.config,...e},this.logger=h(this.config.logLevel),this.namespace=e.namespace||this.namespace,this.transport=this.initializeTransport(e),this.persistence=this.initializePersistence(),this.retryQueue=new J(this.transport,this.config.maxSendAttempts||3,this.config.minSendTimeout||1e3,10,250,this.logger),u()&&this.initializeBrowserFeatures(),this.anonymousId=this.getOrCreateAnonymousId(),this.logger.info(`Usermaven client reinitialized for namespace: ${this.namespace}`)}manageCrossDomainLinking(){if(!this.config.crossDomainLinking||!this.config.domains)return;const e=this.config.domains.split(",").map(i=>i.trim()),t=this.config.cookieName||`${this.namespace}_id_${this.config.key}`;document.addEventListener("click",i=>{var c;const n=this.findClosestLink(i.target);if(!n)return;const r=n.getAttribute("href");if(!r||!r.startsWith("http"))return;const o=new URL(r);if(o.hostname!==window.location.hostname&&e.includes(o.hostname)){const l=(c=this.cookieManager)==null?void 0:c.get(t);l&&(o.searchParams.append("_um",l),n.setAttribute("href",o.toString()))}}),this.logger.debug("Cross-domain linking initialized")}findClosestLink(e){for(;e&&e.tagName!=="A";)e=e.parentElement;return e}initializeTransport(e){if(!u())return new pe(e.trackingHost,e);const t="XMLHttpRequest"in window,i=typeof fetch<"u",n=typeof navigator<"u"&&"sendBeacon"in navigator;if(e.useBeaconApi&&n)return new he(e.trackingHost,e,this.logger);if(e.forceUseFetch&&i)return new q(e.trackingHost,e,this.logger);if(t)return new ge(e.trackingHost,e,this.logger);if(i)return new q(e.trackingHost,e,this.logger);throw new Error("No suitable transport method available")}initializePersistence(){return this.config.disableEventPersistence||!u()?new de:new V(`${this.namespace}_${this.config.key}`,this.logger)}getOrCreateAnonymousId(){var i,n;if(!u())return R();if(this.config.privacyPolicy==="strict"||this.config.cookiePolicy==="strict")return this.generateFingerprint();const e=this.config.cookieName||`${this.namespace}_id_${this.config.key}`;let t=(i=this.cookieManager)==null?void 0:i.get(e);if(!t){if(this.config.crossDomainLinking){const c=new URLSearchParams(window.location.search).get("_um"),a=window.location.hash.substring(1).split("~"),d=a.length>1?a[1]:void 0;t=c||d||R()}t||(t=R());const r=365*10;(n=this.cookieManager)==null||n.set(e,t,r,document.location.protocol!=="http:",!1)}return t}generateFingerprint(){const e=navigator.userAgent,t=`${screen.width}x${screen.height}`,i=screen.colorDepth,n=Intl.DateTimeFormat().resolvedOptions().timeZone,r=`${e}|${t}|${i}|${n}`;return this.hashString(r)}hashString(e){let t=0;for(let i=0;i<e.length;i++){const n=e.charCodeAt(i);t=(t<<5)-t+n,t=t&t}return t.toString(36)}async id(e,t=!1){if(!_(e))throw new Error("User data must be an object");if(e.email&&!re(e.email))throw new Error("Invalid email provided");if(!e.id||!B(e.id))throw new Error("User ID must be a string");const i=e.id;if(this.persistence.set("userId",i),this.persistence.set("userProps",e),!t){const n={...e,anonymous_id:this.anonymousId};await this.track("user_identify",n)}this.logger.info("User identified:",e)}track(e,t,i=!1){this.trackInternal(e,t,i)}trackInternal(e,t,i=!1){if(!B(e))throw new Error("Event name must be a string");if(t!==void 0&&(typeof t!="object"||t===null||Array.isArray(t)))throw new Error("Event payload must be a non-null object and not an array");const n=this.createEventPayload(e,t);try{if(i){this.transport.send(n),this.logger.debug(`Event sent: ${e}`,[n]);return}this.retryQueue.add(n),this.logger.debug(`Event tracked: ${e}`,[n])}catch(r){throw this.logger.error(`Failed to track event: ${e}`,r),new Error(`Failed to track event: ${e}`)}}rawTrack(e){if(!_(e))throw new Error("Event payload must be an object");this.track("raw",e)}async group(e,t=!1){if(!_(e))throw new Error("Company properties must be an object");if(!e.id||!e.name||!e.created_at)throw new Error("Company properties must include id, name, and created_at");this.persistence.set("companyProps",e),t||await this.track("group",e),this.logger.info("Company identified:",e)}createEventPayload(e,t){const i=this.persistence.get("userProps")||{},n=this.persistence.get("companyProps")||void 0,r=this.persistence.get("userId"),o=this.persistence.get("global_props")||{},c=this.persistence.get(`props_${e}`)||{};let l=t||{};const a={event_id:"",user:{anonymous_id:this.anonymousId,id:r,...i},...n&&{company:n},ids:this.getThirdPartyIds(),utc_time:new Date().toISOString(),local_tz_offset:new Date().getTimezoneOffset(),api_key:this.config.key,src:"usermaven",event_type:e,namespace:this.namespace,...o,...c};if(e==="$autocapture"){const d=this.processAutocaptureAttributes(t||{});a.autocapture_attributes=d}else Array.isArray(this.config.propertyBlacklist)&&this.config.propertyBlacklist.forEach(d=>{delete l[d]}),a.event_attributes=l;return u()&&(a.referer=document.referrer,a.url=window.location.href,a.page_title=document.title,a.doc_path=window.location.pathname,a.doc_host=window.location.hostname,a.doc_search=window.location.search,a.screen_resolution=`${window.screen.width}x${window.screen.height}`,a.vp_size=`${window.innerWidth}x${window.innerHeight}`,a.user_agent=navigator.userAgent,a.user_language=navigator.language,a.doc_encoding=document.characterSet,a.utm=this.getUtmParams()),a}processAutocaptureAttributes(e){let t={};const i=e.$elements||[];return i.length&&(t={...i[0]}),t.el_text=t.$el_text||"",t.event_type=e.$event_type||"",["$ce_version","$event_type","$initial_referrer","$initial_referring_domain","$referrer","$referring_domain","$elements"].forEach(n=>{delete t[n]}),delete t.$el_text,delete t.nth_child,delete t.nth_of_type,t}getCookie(e){var t;return((t=this.cookieManager)==null?void 0:t.get(e))||null}getThirdPartyIds(){const e={};if(u()){const t=this.getCookie("_fbp");t&&(e.fbp=t)}return e}getUtmParams(){const e={},t=ae(window.location.search);return["utm_source","utm_medium","utm_campaign","utm_term","utm_content"].forEach(n=>{t[n]&&(e[n.replace("utm_","")]=t[n])}),e}pageview(){u()?this.track("pageview",{url:window.location.href,referrer:document.referrer,title:document.title},!0):this.logger.warn("Pageview tracking is not available in server-side environments")}setupPageLeaveTracking(){if(!u())return;let e=!1,t=!1;const i=()=>{!e&&!t&&(e=!0,this.track("$pageleave",{url:window.location.href,referrer:document.referrer,title:document.title}))};window.addEventListener("beforeunload",r=>{t=!0,setTimeout(()=>{t=!1},100)}),document.addEventListener("visibilitychange",()=>{document.visibilityState==="hidden"&&!t&&i()});const n=history.pushState;history.pushState=function(){return i(),n.apply(this,arguments)},window.addEventListener("popstate",i)}getConfig(){return this.config}getLogger(){return this.logger}async reset(e=!1){if(this.persistence.clear(),e&&this.cookieManager){const t=this.config.cookieName||`${this.namespace}_id_${this.config.key}`;this.cookieManager.delete(t),this.anonymousId=this.getOrCreateAnonymousId()}this.logger.info("core state reset",{resetAnonId:e,namespace:this.namespace})}set(e,t){if(!_(e))throw new Error("Properties must be an object");const i=t==null?void 0:t.eventType,n=(t==null?void 0:t.persist)??!0;if(i){let r=this.persistence.get(`props_${i}`)||{};r={...r,...e},this.persistence.set(`props_${i}`,r)}else{let r=this.persistence.get("global_props")||{};r={...r,...e},this.persistence.set("global_props",r)}n&&this.persistence.save(),this.logger.debug("Properties set",{properties:e,eventType:i||"global",persist:n})}setUserId(e){this.persistence.set("userId",e);let t=this.persistence.get("userProps")||{};t.id=e,this.persistence.set("userProps",t),this.persistence.save()}unset(e,t){const i=t==null?void 0:t.eventType,n=(t==null?void 0:t.persist)??!0;if(i){let r=this.persistence.get(`props_${i}`)||{};delete r[e],this.persistence.set(`props_${i}`,r)}else{let r=this.persistence.get("global_props")||{};delete r[e],this.persistence.set("global_props",r)}n&&this.persistence.save(),this.logger.debug(`Property unset: ${e}`,`Event type: ${i||"global"}`)}}function W(s){const e=JSON.parse(JSON.stringify(s)),t=S(e),i={...N,...t};if(!i.key)throw new Error("API key is required!");if(!i.trackingHost)throw new Error("Tracking host is required!");return new Q(i)}function me(s){var n;const e={key:s.getAttribute("data-key")||void 0,trackingHost:s.getAttribute("data-tracking-host")||"https://events.usermaven.com",logLevel:ce(s.getAttribute("data-log-level")),autocapture:s.getAttribute("data-autocapture")==="true",formTracking:s.getAttribute("data-form-tracking")==="true"?"all":!1,autoPageview:s.getAttribute("data-auto-pageview")==="true",useBeaconApi:s.getAttribute("data-use-beacon-api")==="true",forceUseFetch:s.getAttribute("data-force-use-fetch")==="true",gaHook:s.getAttribute("data-ga-hook")==="true",segmentHook:s.getAttribute("data-segment-hook")==="true",randomizeUrl:s.getAttribute("data-randomize-url")==="true",capture3rdPartyCookies:s.getAttribute("data-capture-3rd-party-cookies")==="false"?!1:void 0,idMethod:s.getAttribute("data-id-method")||void 0,privacyPolicy:s.getAttribute("data-privacy-policy")==="strict"?"strict":void 0,ipPolicy:s.getAttribute("data-ip-policy")||void 0,cookiePolicy:s.getAttribute("data-cookie-policy")||void 0,minSendTimeout:parseInt(s.getAttribute("data-min-send-timeout")||"",10)||void 0,maxSendTimeout:parseInt(s.getAttribute("data-max-send-timeout")||"",10)||void 0,maxSendAttempts:parseInt(s.getAttribute("data-max-send-attempts")||"",10)||void 0,propertiesStringMaxLength:parseInt(s.getAttribute("data-properties-string-max-length")||"",10)||null,propertyBlacklist:((n=s.getAttribute("data-property-blacklist"))==null?void 0:n.split(","))||void 0,exclude:s.getAttribute("data-exclude")||void 0,namespace:s.getAttribute("data-namespace")||void 0,crossDomainLinking:s.getAttribute("data-cross-domain-linking")!=="false",domains:s.getAttribute("data-domains")||void 0,maskAllText:s.getAttribute("data-mask-all-text")==="true",maskAllElementAttributes:s.getAttribute("data-mask-all-element-attributes")==="true"},t=W(e),i=e.namespace||"usermaven";u()&&t.pageview(),ye(i,t)}function ye(s,e){let t=!1;const i=[],n=[];function r(){for(;i.length>0;){const a=i.shift();a&&window[s].apply(null,a)}}function o(){n.forEach(a=>a()),n.length=0}window[s]=function(...a){const d=a[0];if(d==="onLoad"){typeof a[1]=="function"&&(t?a[1]():n.push(a[1]));return}if(!t){i.push(a);return}if(typeof e[d]=="function")return e[d].apply(e,a.slice(1));console.error(`Method ${d} not found on UsermavenClient`)};const c=`${s}Q`,l=window[c]||[];for(window[c]=l,l.push=function(...a){return window[s].apply(null,a),Array.prototype.push.apply(this,a)},setTimeout(()=>{t=!0,r(),o(),console.log(`Usermaven client for namespace ${s} is ready`)},0);l.length>0;){const a=l.shift();a&&i.push(a)}}u()&&function(s,e){const t=s.currentScript;function i(){t&&t.src.includes("lib.js")&&me(t)}typeof e<"u"&&(s.readyState==="loading"?s.addEventListener("DOMContentLoaded",i):i())}(document,window),f.LogLevel=g,f.UsermavenClient=Q,f.usermavenClient=W,Object.defineProperty(f,Symbol.toStringTag,{value:"Module"})});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Logger } from '../utils/logger';
|
|
2
|
+
export declare class LocalStoragePersistence {
|
|
3
|
+
private storage;
|
|
4
|
+
private prefix;
|
|
5
|
+
private logger;
|
|
6
|
+
constructor(apiKey: string, logger?: Logger);
|
|
7
|
+
set(key: string, value: any): void;
|
|
8
|
+
get(key: string): any;
|
|
9
|
+
remove(key: string): void;
|
|
10
|
+
clear(): void;
|
|
11
|
+
save(): void;
|
|
12
|
+
private load;
|
|
13
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { UsermavenClient } from '../core/client';
|
|
2
|
+
import { Config } from '../core/config';
|
|
3
|
+
declare class AutoCapture {
|
|
4
|
+
private logger;
|
|
5
|
+
private client;
|
|
6
|
+
private options;
|
|
7
|
+
private scrollDepth;
|
|
8
|
+
static readonly FORCE_CAPTURE_ATTR = "data-um-force-capture";
|
|
9
|
+
static readonly PREVENT_CAPTURE_ATTR = "data-um-no-capture";
|
|
10
|
+
constructor(client: UsermavenClient, options: Config, logger?: import('../utils/logger').Logger);
|
|
11
|
+
init(): void;
|
|
12
|
+
private addDomEventHandlers;
|
|
13
|
+
private isPageRefresh;
|
|
14
|
+
private captureEvent;
|
|
15
|
+
private shouldCaptureElement;
|
|
16
|
+
private getEventTarget;
|
|
17
|
+
private getElementList;
|
|
18
|
+
private getElementsJson;
|
|
19
|
+
private getPropertiesFromElement;
|
|
20
|
+
private previousElementSibling;
|
|
21
|
+
private getDefaultProperties;
|
|
22
|
+
private sanitizeText;
|
|
23
|
+
private sanitizeUrl;
|
|
24
|
+
private sanitizeAttributeValue;
|
|
25
|
+
private encodeHtml;
|
|
26
|
+
static enabledForProject(token: string, numBuckets?: number, numEnabledBuckets?: number): boolean;
|
|
27
|
+
static isBrowserSupported(): boolean;
|
|
28
|
+
}
|
|
29
|
+
export default AutoCapture;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { UsermavenClient } from '../core/client';
|
|
2
|
+
export default class FormTracking {
|
|
3
|
+
private instance;
|
|
4
|
+
private formElements?;
|
|
5
|
+
private trackingType;
|
|
6
|
+
private options;
|
|
7
|
+
private static instance;
|
|
8
|
+
private constructor();
|
|
9
|
+
private initialize;
|
|
10
|
+
private setupFormTracking;
|
|
11
|
+
private handleFormSubmit;
|
|
12
|
+
private trackFieldChanges;
|
|
13
|
+
static getInstance(instance: UsermavenClient, trackingType?: 'all' | 'tagged' | 'none', options?: FormTrackingOptions): FormTracking;
|
|
14
|
+
private _getFormDetails;
|
|
15
|
+
private _getFieldProps;
|
|
16
|
+
private _getElementAttributes;
|
|
17
|
+
private getSafeText;
|
|
18
|
+
private _scrubPotentiallySensitiveValues;
|
|
19
|
+
private _shouldCaptureValue;
|
|
20
|
+
private _isNullish;
|
|
21
|
+
private _isString;
|
|
22
|
+
private _trim;
|
|
23
|
+
}
|
|
24
|
+
interface FormTrackingOptions {
|
|
25
|
+
trackFieldChanges?: boolean;
|
|
26
|
+
}
|
|
27
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { UsermavenClient } from '../core/client';
|
|
2
|
+
export declare class PageviewTracking {
|
|
3
|
+
private client;
|
|
4
|
+
private lastPageUrl;
|
|
5
|
+
constructor(client: UsermavenClient);
|
|
6
|
+
private trackInitialPageview;
|
|
7
|
+
private initializePageviewTracking;
|
|
8
|
+
private handlePageview;
|
|
9
|
+
private checkForUrlChange;
|
|
10
|
+
private trackPageview;
|
|
11
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Transport } from '../core/types';
|
|
2
|
+
import { Config } from '../core/config';
|
|
3
|
+
export declare class BeaconTransport implements Transport {
|
|
4
|
+
private trackingHost;
|
|
5
|
+
private logger;
|
|
6
|
+
private config;
|
|
7
|
+
constructor(trackingHost: string, config: Config, logger?: import('../utils/logger').Logger);
|
|
8
|
+
send(payloads: any[]): Promise<void>;
|
|
9
|
+
private constructUrl;
|
|
10
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Transport } from '../core/types';
|
|
2
|
+
import { Logger } from '../utils/logger';
|
|
3
|
+
import { Config } from '../core/config';
|
|
4
|
+
export declare class FetchTransport implements Transport {
|
|
5
|
+
private trackingHost;
|
|
6
|
+
private logger;
|
|
7
|
+
private config;
|
|
8
|
+
constructor(trackingHost: string, config: Config, logger?: Logger);
|
|
9
|
+
send(payloads: any[]): Promise<void>;
|
|
10
|
+
private constructUrl;
|
|
11
|
+
private getCustomHeaders;
|
|
12
|
+
private postHandle;
|
|
13
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Transport } from '../core/types';
|
|
2
|
+
import { Config } from '../core/config';
|
|
3
|
+
export declare class HttpsTransport implements Transport {
|
|
4
|
+
private trackingHost;
|
|
5
|
+
private logger;
|
|
6
|
+
private config;
|
|
7
|
+
constructor(trackingHost: string, config: Config, logger?: import('../utils/logger').Logger);
|
|
8
|
+
send(payloads: any[]): Promise<void>;
|
|
9
|
+
private constructUrl;
|
|
10
|
+
private getCustomHeaders;
|
|
11
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Transport } from '../core/types';
|
|
2
|
+
import { Config } from '../core/config';
|
|
3
|
+
export declare class XhrTransport implements Transport {
|
|
4
|
+
private trackingHost;
|
|
5
|
+
private logger;
|
|
6
|
+
private config;
|
|
7
|
+
constructor(trackingHost: string, config: Config, logger?: import('../utils/logger').Logger);
|
|
8
|
+
send(payloads: any[]): Promise<void>;
|
|
9
|
+
private constructUrl;
|
|
10
|
+
private getCustomHeaders;
|
|
11
|
+
private postHandle;
|
|
12
|
+
}
|