@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 CHANGED
@@ -1,51 +1,164 @@
1
- # Usermaven JavaScript SDK (usermaven.js)
1
+ # Usermaven SDK
2
2
 
3
- Usermaven.js is a JavaScript SDK for [Usermaven](https://usermaven.com).
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
- ## Capabilities
5
+ ## Features
6
6
 
7
- - Autocapturing via `autocapture`, `capture_pageview`, `properties_string_max_length` and `property_blacklist` options.
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
- ## Maintainers Guide
15
+ ## Installation
10
16
 
11
- This section is indented only for package maintainers.
17
+ ### NPM or Yarn
12
18
 
13
- ### Building and local debug
19
+ You can install the Usermaven SDK using npm:
14
20
 
15
- * _**ATTENTION**_: Use `yarn` for everything except publishing
16
- * To spin off a local development server run `yarn devserver`, then open [http://localhost:8081](http://localhost:8081)
17
- * The server listens to all changes to src and rebuilds npm and `lib.js` automatically. Open test cases HTML files to see
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
- ### Checking Cross Domain Session locally
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
- sudo nano /etc/hosts
28
+ yarn add @usermaven/sdk-js
39
29
  ```
40
- Add the following lines in the hosts file
41
- ```bash
42
- 127.0.0.1 localhost.com
43
- 127.0.0.1 app.localhost.com
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
- You will be able to access the domains at [localhost domain](http://localhost.com:8081/test-case/embed.html) and [localhost sub-domain](http://app.localhost.com:8081/test-case/embed.html)
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
- ### Publishing new version
162
+ ## Contributing
49
163
 
50
- * Login with your *personal* credentials with `npm login`
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
+ }
@@ -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,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#039;")}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,8 @@
1
+ export declare class MemoryPersistence {
2
+ private storage;
3
+ set(key: string, value: any): void;
4
+ get(key: string): any;
5
+ remove(key: string): void;
6
+ save(): void;
7
+ clear(): void;
8
+ }
@@ -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,3 @@
1
+ export interface Transport {
2
+ send(payload: any | any[]): Promise<void>;
3
+ }
@@ -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
+ }