humanbehavior-js 0.0.5 → 0.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.js +912 -596
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/react/index.js +38 -82
- package/dist/cjs/react/index.js.map +1 -1
- package/dist/esm/index.js +911 -597
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/react/index.js +38 -82
- package/dist/esm/react/index.js.map +1 -1
- package/dist/index.min.js +2 -2
- package/dist/index.min.js.map +1 -1
- package/dist/types/index.d.ts +111 -3
- package/dist/types/react/index.d.ts +1 -1
- package/package.json +3 -14
- package/readme.md +116 -28
- package/rollup.config.js +106 -0
- package/src/api.ts +360 -0
- package/src/index.ts +22 -0
- package/src/react/index.tsx +189 -0
- package/src/redact.ts +474 -0
- package/src/tracker.ts +361 -0
- package/tsconfig.json +24 -0
- package/index.d.ts +0 -2
- package/index.js +0 -3
- package/react.d.ts +0 -2
- package/react.js +0 -2
package/dist/types/index.d.ts
CHANGED
|
@@ -1,3 +1,85 @@
|
|
|
1
|
+
interface RedactionOptions {
|
|
2
|
+
redactedText?: string;
|
|
3
|
+
excludeSelectors?: string[];
|
|
4
|
+
userFields?: string[];
|
|
5
|
+
}
|
|
6
|
+
declare class RedactionManager {
|
|
7
|
+
private redactedText;
|
|
8
|
+
private userSelectedFields;
|
|
9
|
+
private excludeSelectors;
|
|
10
|
+
constructor(options?: RedactionOptions);
|
|
11
|
+
/**
|
|
12
|
+
* Set specific fields to be redacted
|
|
13
|
+
* @param fields Array of CSS selectors for fields to redact
|
|
14
|
+
*/
|
|
15
|
+
setFieldsToRedact(fields: string[]): void;
|
|
16
|
+
/**
|
|
17
|
+
* Check if redaction is currently active (has fields selected)
|
|
18
|
+
*/
|
|
19
|
+
isActive(): boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Get the currently selected fields for redaction
|
|
22
|
+
*/
|
|
23
|
+
getSelectedFields(): string[];
|
|
24
|
+
/**
|
|
25
|
+
* Process an event and redact sensitive data if needed
|
|
26
|
+
*/
|
|
27
|
+
processEvent(event: any): any;
|
|
28
|
+
/**
|
|
29
|
+
* Redact sensitive data in input events
|
|
30
|
+
*/
|
|
31
|
+
private redactInputEvent;
|
|
32
|
+
/**
|
|
33
|
+
* Redact sensitive data in DOM mutation events
|
|
34
|
+
*/
|
|
35
|
+
private redactDOMEvent;
|
|
36
|
+
/**
|
|
37
|
+
* Check if a DOM change should be redacted based on its ID
|
|
38
|
+
*/
|
|
39
|
+
private shouldRedactDOMChange;
|
|
40
|
+
/**
|
|
41
|
+
* Redact sensitive data in mouse/touch interaction events
|
|
42
|
+
*/
|
|
43
|
+
private redactMouseEvent;
|
|
44
|
+
/**
|
|
45
|
+
* Redact sensitive data in full snapshot events
|
|
46
|
+
*/
|
|
47
|
+
private redactFullSnapshot;
|
|
48
|
+
/**
|
|
49
|
+
* Recursively redact sensitive data in DOM nodes
|
|
50
|
+
*/
|
|
51
|
+
private redactNode;
|
|
52
|
+
/**
|
|
53
|
+
* Check if a node should be redacted based on its attributes
|
|
54
|
+
*/
|
|
55
|
+
private shouldRedactNode;
|
|
56
|
+
/**
|
|
57
|
+
* Check if a CSS selector would match a node based on its attributes
|
|
58
|
+
*/
|
|
59
|
+
private selectorMatchesNode;
|
|
60
|
+
/**
|
|
61
|
+
* Basic selector matching for environments where matches() is not available
|
|
62
|
+
*/
|
|
63
|
+
private basicSelectorMatch;
|
|
64
|
+
/**
|
|
65
|
+
* Check if an event is from a field that should be redacted
|
|
66
|
+
*/
|
|
67
|
+
private isFieldSelected;
|
|
68
|
+
/**
|
|
69
|
+
* Check if an element should be redacted based on user-selected fields
|
|
70
|
+
*/
|
|
71
|
+
private shouldRedactElement;
|
|
72
|
+
/**
|
|
73
|
+
* Get the original value of a redacted element (for debugging)
|
|
74
|
+
*/
|
|
75
|
+
getOriginalValue(element: HTMLElement): string | undefined;
|
|
76
|
+
/**
|
|
77
|
+
* Check if an element is currently being redacted
|
|
78
|
+
*/
|
|
79
|
+
isElementRedacted(element: HTMLElement): boolean;
|
|
80
|
+
}
|
|
81
|
+
declare const redactionManager: RedactionManager;
|
|
82
|
+
|
|
1
83
|
declare global {
|
|
2
84
|
interface Window {
|
|
3
85
|
HumanBehaviorTracker: typeof HumanBehaviorTracker;
|
|
@@ -18,13 +100,19 @@ declare class HumanBehaviorTracker {
|
|
|
18
100
|
private apiKey;
|
|
19
101
|
private initialized;
|
|
20
102
|
initializationPromise: Promise<void> | null;
|
|
21
|
-
|
|
103
|
+
private redactionManager;
|
|
104
|
+
constructor(apiKey: string | undefined, ingestionUrl?: string);
|
|
22
105
|
private init;
|
|
23
106
|
private ensureInitialized;
|
|
24
107
|
static logToStorage(message: string): void;
|
|
25
108
|
private setupPageUnloadHandler;
|
|
26
109
|
viewLogs(): void;
|
|
27
|
-
|
|
110
|
+
addUserInfo(userProperties: Record<string, any>): Promise<void>;
|
|
111
|
+
/**
|
|
112
|
+
* Authenticate user using existing userInfo data
|
|
113
|
+
* @param authFields Array of field names to check for existing users (e.g., ['email', 'phoneNumber'])
|
|
114
|
+
*/
|
|
115
|
+
auth(authFields: string[]): Promise<void>;
|
|
28
116
|
customEvent(eventName: string, eventProperties?: Record<string, any>): Promise<void>;
|
|
29
117
|
start(): Promise<void>;
|
|
30
118
|
stop(): Promise<void>;
|
|
@@ -33,6 +121,24 @@ declare class HumanBehaviorTracker {
|
|
|
33
121
|
private flush;
|
|
34
122
|
private setCookie;
|
|
35
123
|
private getCookie;
|
|
124
|
+
/**
|
|
125
|
+
* Start redaction functionality for sensitive input fields
|
|
126
|
+
* @param options Optional configuration for redaction behavior
|
|
127
|
+
*/
|
|
128
|
+
redact(options?: RedactionOptions): Promise<void>;
|
|
129
|
+
/**
|
|
130
|
+
* Set specific fields to be redacted during session recording
|
|
131
|
+
* @param fields Array of CSS selectors for fields to redact (e.g., ['input[type="password"]', '#email-field'])
|
|
132
|
+
*/
|
|
133
|
+
setRedactedFields(fields: string[]): void;
|
|
134
|
+
/**
|
|
135
|
+
* Check if redaction is currently active
|
|
136
|
+
*/
|
|
137
|
+
isRedactionActive(): boolean;
|
|
138
|
+
/**
|
|
139
|
+
* Get the currently selected fields for redaction
|
|
140
|
+
*/
|
|
141
|
+
getRedactedFields(): string[];
|
|
36
142
|
}
|
|
37
143
|
|
|
38
144
|
declare const MAX_CHUNK_SIZE_BYTES: number;
|
|
@@ -52,6 +158,7 @@ declare class HumanBehaviorAPI {
|
|
|
52
158
|
sendEvents(events: any[], sessionId: string, userId: string): Promise<void>;
|
|
53
159
|
sendEventsChunked(events: any[], sessionId: string): Promise<any[]>;
|
|
54
160
|
sendUserData(userId: string, userData: Record<string, any>, sessionId: string): Promise<any>;
|
|
161
|
+
sendUserAuth(userId: string, userData: Record<string, any>, sessionId: string, authFields: string[]): Promise<any>;
|
|
55
162
|
sendSessionComplete(sessionId: string): Promise<void>;
|
|
56
163
|
sendCustomEvent(eventName: string, eventProperties: Record<string, any>, sessionId: string): Promise<any>;
|
|
57
164
|
sendCustomEvents(events: any[], sessionId: string): Promise<any>;
|
|
@@ -61,4 +168,5 @@ declare class HumanBehaviorAPI {
|
|
|
61
168
|
sendBeaconCustomEvents(events: any[], sessionId: string): boolean;
|
|
62
169
|
}
|
|
63
170
|
|
|
64
|
-
export { HumanBehaviorAPI, HumanBehaviorTracker, MAX_CHUNK_SIZE_BYTES, HumanBehaviorTracker as default, isChunkSizeExceeded, validateSingleEventSize };
|
|
171
|
+
export { HumanBehaviorAPI, HumanBehaviorTracker, MAX_CHUNK_SIZE_BYTES, RedactionManager, HumanBehaviorTracker as default, isChunkSizeExceeded, redactionManager, validateSingleEventSize };
|
|
172
|
+
export type { RedactionOptions };
|
|
@@ -3,7 +3,7 @@ import { HumanBehaviorTracker } from '..';
|
|
|
3
3
|
|
|
4
4
|
interface HumanBehaviorInterface {
|
|
5
5
|
addEvent: (event: any) => void;
|
|
6
|
-
|
|
6
|
+
addUserInfo: (userProperties: Record<string, any>) => Promise<void>;
|
|
7
7
|
start: () => void;
|
|
8
8
|
stop: () => void;
|
|
9
9
|
viewLogs: () => void;
|
package/package.json
CHANGED
|
@@ -1,19 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "humanbehavior-js",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.8",
|
|
4
4
|
"description": "SDK for HumanBehavior session and event recording",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/cjs/index.js",
|
|
7
7
|
"module": "./dist/esm/index.js",
|
|
8
8
|
"types": "./dist/types/index.d.ts",
|
|
9
9
|
"unpkg": "dist/index.min.js",
|
|
10
|
-
"files": [
|
|
11
|
-
"dist",
|
|
12
|
-
"react.js",
|
|
13
|
-
"react.d.ts",
|
|
14
|
-
"index.js",
|
|
15
|
-
"index.d.ts"
|
|
16
|
-
],
|
|
17
10
|
"exports": {
|
|
18
11
|
".": {
|
|
19
12
|
"import": "./dist/esm/index.js",
|
|
@@ -45,15 +38,11 @@
|
|
|
45
38
|
"@rollup/plugin-node-resolve": "^16.0.1",
|
|
46
39
|
"@rollup/plugin-terser": "^0.4.4",
|
|
47
40
|
"@rollup/plugin-typescript": "^12.1.2",
|
|
48
|
-
"@types/
|
|
49
|
-
"@types/express": "^5.0.1",
|
|
41
|
+
"@types/node": "^24.0.3",
|
|
50
42
|
"rollup": "^4.36.0",
|
|
51
43
|
"rollup-plugin-dts": "^6.2.1",
|
|
52
|
-
"ts-loader": "^9.5.2",
|
|
53
44
|
"tslib": "^2.8.1",
|
|
54
|
-
"typescript": "^5.8.2"
|
|
55
|
-
"webpack": "^5.98.0",
|
|
56
|
-
"webpack-cli": "^6.0.1"
|
|
45
|
+
"typescript": "^5.8.2"
|
|
57
46
|
},
|
|
58
47
|
"publishConfig": {
|
|
59
48
|
"access": "public"
|
package/readme.md
CHANGED
|
@@ -1,57 +1,145 @@
|
|
|
1
|
-
|
|
1
|
+
# HumanBehavior SDK
|
|
2
2
|
|
|
3
|
+
A JavaScript SDK for session recording and user behavior analytics.
|
|
3
4
|
|
|
4
|
-
|
|
5
|
+
## Installation
|
|
5
6
|
|
|
6
|
-
|
|
7
|
+
```bash
|
|
8
|
+
npm install humanbehavior-js
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
### Vanilla JavaScript
|
|
14
|
+
|
|
15
|
+
```html
|
|
16
|
+
<script src="https://unpkg.com/humanbehavior-js@0.0.7/dist/index.min.js"></script>
|
|
17
|
+
<script>
|
|
18
|
+
const tracker = new HumanBehaviorTracker("your-api-key-here");
|
|
19
|
+
tracker.start();
|
|
20
|
+
|
|
21
|
+
// Set up redaction for sensitive fields
|
|
22
|
+
tracker.setRedactedFields(['#password', 'input[type="password"]']);
|
|
23
|
+
</script>
|
|
24
|
+
```
|
|
7
25
|
|
|
8
|
-
|
|
9
|
-
|
|
26
|
+
### Next.js
|
|
27
|
+
|
|
28
|
+
Add the following to your `providers.tsx` file:
|
|
29
|
+
|
|
30
|
+
```tsx
|
|
10
31
|
"use client"
|
|
11
32
|
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
33
|
+
import { HumanBehaviorTracker } from "humanbehavior-js";
|
|
34
|
+
import { HumanBehaviorProvider } from "humanbehavior-js/react";
|
|
14
35
|
import { useEffect, useState } from "react";
|
|
15
36
|
|
|
16
|
-
export function
|
|
17
|
-
const [
|
|
37
|
+
export function HumanBehaviorProviderWrapper({ children }: { children: React.ReactNode }) {
|
|
38
|
+
const [tracker, setTracker] = useState<HumanBehaviorTracker | null>(null);
|
|
18
39
|
|
|
19
40
|
useEffect(() => {
|
|
20
|
-
const apiKey =
|
|
21
|
-
|
|
22
|
-
|
|
41
|
+
const apiKey = process.env.NEXT_PUBLIC_HUMANBEHAVIOR_API_KEY;
|
|
42
|
+
if (apiKey) {
|
|
43
|
+
const tracker = new HumanBehaviorTracker(apiKey);
|
|
44
|
+
setTracker(tracker);
|
|
45
|
+
}
|
|
23
46
|
}, []);
|
|
24
47
|
|
|
25
48
|
return (
|
|
26
|
-
<
|
|
49
|
+
<HumanBehaviorProvider client={tracker}>
|
|
50
|
+
{children}
|
|
51
|
+
</HumanBehaviorProvider>
|
|
52
|
+
)
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Or use the simpler approach with just an API key:
|
|
57
|
+
|
|
58
|
+
```tsx
|
|
59
|
+
"use client"
|
|
60
|
+
|
|
61
|
+
import { HumanBehaviorProvider } from "humanbehavior-js/react";
|
|
62
|
+
|
|
63
|
+
export function HumanBehaviorProviderWrapper({ children }: { children: React.ReactNode }) {
|
|
64
|
+
return (
|
|
65
|
+
<HumanBehaviorProvider apiKey={process.env.NEXT_PUBLIC_HUMANBEHAVIOR_API_KEY}>
|
|
27
66
|
{children}
|
|
28
|
-
</
|
|
67
|
+
</HumanBehaviorProvider>
|
|
29
68
|
)
|
|
30
69
|
}
|
|
31
70
|
```
|
|
32
71
|
|
|
33
|
-
Next, add the provider to your root app layout
|
|
34
|
-
|
|
72
|
+
Next, add the provider to your root app layout:
|
|
73
|
+
|
|
74
|
+
```tsx
|
|
35
75
|
export default async function RootLayout({
|
|
36
76
|
children
|
|
37
77
|
}: {
|
|
38
78
|
children: React.ReactNode;
|
|
39
79
|
}) {
|
|
40
|
-
const session = await auth();
|
|
41
80
|
return (
|
|
42
|
-
<html lang='en'
|
|
43
|
-
<body
|
|
44
|
-
<
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
<Providers session={session}>
|
|
48
|
-
<Toaster />
|
|
49
|
-
{children}
|
|
50
|
-
</Providers>
|
|
51
|
-
</NuqsAdapter>
|
|
52
|
-
</KoalawareProvider>
|
|
81
|
+
<html lang='en' suppressHydrationWarning>
|
|
82
|
+
<body>
|
|
83
|
+
<HumanBehaviorProviderWrapper>
|
|
84
|
+
{children}
|
|
85
|
+
</HumanBehaviorProviderWrapper>
|
|
53
86
|
</body>
|
|
54
87
|
</html>
|
|
55
88
|
);
|
|
56
89
|
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Using the Hook
|
|
93
|
+
|
|
94
|
+
In any component within the provider:
|
|
95
|
+
|
|
96
|
+
```tsx
|
|
97
|
+
import { useHumanBehavior } from "humanbehavior-js/react";
|
|
98
|
+
|
|
99
|
+
export function MyComponent() {
|
|
100
|
+
const humanBehavior = useHumanBehavior();
|
|
101
|
+
|
|
102
|
+
const handleUserAction = async () => {
|
|
103
|
+
// Add user information
|
|
104
|
+
await humanBehavior.addUserInfo({
|
|
105
|
+
email: "user@example.com",
|
|
106
|
+
name: "John Doe"
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
// Track custom events
|
|
110
|
+
humanBehavior.addEvent({
|
|
111
|
+
type: "custom",
|
|
112
|
+
name: "button_clicked",
|
|
113
|
+
data: { buttonId: "submit" }
|
|
114
|
+
});
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
return <button onClick={handleUserAction}>Click me</button>;
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Environment Variables
|
|
122
|
+
|
|
123
|
+
For security, store your API key in environment variables:
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
# .env.local
|
|
127
|
+
NEXT_PUBLIC_HUMANBEHAVIOR_API_KEY=your-api-key-here
|
|
128
|
+
NEXT_PUBLIC_INGESTION_URL=https://ingestion.humanbehavior.ai
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## Features
|
|
132
|
+
|
|
133
|
+
- **Session Recording**: Automatic recording of user interactions
|
|
134
|
+
- **Data Redaction**: Protect sensitive information in recordings
|
|
135
|
+
- **User Identification**: Track users across sessions
|
|
136
|
+
- **Custom Events**: Send custom analytics events
|
|
137
|
+
- **React Integration**: Hooks and providers for React applications
|
|
138
|
+
|
|
139
|
+
## Build
|
|
140
|
+
|
|
141
|
+
To build the SDK locally:
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
npm run build
|
|
57
145
|
```
|
package/rollup.config.js
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import typescript from '@rollup/plugin-typescript';
|
|
2
|
+
import resolve from '@rollup/plugin-node-resolve';
|
|
3
|
+
import commonjs from '@rollup/plugin-commonjs';
|
|
4
|
+
import terser from '@rollup/plugin-terser';
|
|
5
|
+
import dts from 'rollup-plugin-dts';
|
|
6
|
+
|
|
7
|
+
// Only React should be external since it's typically provided by the host application
|
|
8
|
+
const external = ['react', 'react-dom'];
|
|
9
|
+
|
|
10
|
+
// Global variables for UMD build
|
|
11
|
+
const globals = {
|
|
12
|
+
react: 'React',
|
|
13
|
+
'react-dom': 'ReactDOM'
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export default [
|
|
17
|
+
// Main SDK bundle
|
|
18
|
+
{
|
|
19
|
+
input: 'src/index.ts',
|
|
20
|
+
output: [
|
|
21
|
+
{
|
|
22
|
+
file: 'dist/cjs/index.js',
|
|
23
|
+
format: 'cjs',
|
|
24
|
+
name: 'HumanBehaviorTracker',
|
|
25
|
+
globals,
|
|
26
|
+
exports: 'named',
|
|
27
|
+
sourcemap: true
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
file: 'dist/esm/index.js',
|
|
31
|
+
format: 'es',
|
|
32
|
+
sourcemap: true
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
file: 'dist/index.min.js',
|
|
36
|
+
format: 'umd',
|
|
37
|
+
name: 'HumanBehaviorTracker',
|
|
38
|
+
globals,
|
|
39
|
+
exports: 'auto',
|
|
40
|
+
sourcemap: true,
|
|
41
|
+
plugins: [terser()]
|
|
42
|
+
}
|
|
43
|
+
],
|
|
44
|
+
plugins: [
|
|
45
|
+
resolve(),
|
|
46
|
+
commonjs(),
|
|
47
|
+
typescript({
|
|
48
|
+
tsconfig: './tsconfig.json',
|
|
49
|
+
declaration: false
|
|
50
|
+
})
|
|
51
|
+
],
|
|
52
|
+
external
|
|
53
|
+
},
|
|
54
|
+
|
|
55
|
+
// React component bundle
|
|
56
|
+
{
|
|
57
|
+
input: './src/react/index.tsx',
|
|
58
|
+
output: [
|
|
59
|
+
{
|
|
60
|
+
file: 'dist/cjs/react/index.js',
|
|
61
|
+
format: 'cjs',
|
|
62
|
+
name: 'HumanBehaviorReact',
|
|
63
|
+
globals: {
|
|
64
|
+
...globals,
|
|
65
|
+
'..': 'HumanBehaviorTracker'
|
|
66
|
+
},
|
|
67
|
+
exports: 'named',
|
|
68
|
+
sourcemap: true
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
file: 'dist/esm/react/index.js',
|
|
72
|
+
format: 'es',
|
|
73
|
+
sourcemap: true
|
|
74
|
+
}
|
|
75
|
+
],
|
|
76
|
+
plugins: [
|
|
77
|
+
resolve(),
|
|
78
|
+
commonjs(),
|
|
79
|
+
typescript({
|
|
80
|
+
tsconfig: './tsconfig.json',
|
|
81
|
+
declaration: false
|
|
82
|
+
})
|
|
83
|
+
],
|
|
84
|
+
external: [...external, '..']
|
|
85
|
+
},
|
|
86
|
+
|
|
87
|
+
// Type definition bundles - generate these separately
|
|
88
|
+
{
|
|
89
|
+
input: 'src/index.ts',
|
|
90
|
+
output: {
|
|
91
|
+
file: 'dist/types/index.d.ts',
|
|
92
|
+
format: 'es'
|
|
93
|
+
},
|
|
94
|
+
plugins: [dts()],
|
|
95
|
+
external
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
input: 'src/react/index.tsx',
|
|
99
|
+
output: {
|
|
100
|
+
file: 'dist/types/react/index.d.ts',
|
|
101
|
+
format: 'es'
|
|
102
|
+
},
|
|
103
|
+
plugins: [dts()],
|
|
104
|
+
external: [...external, '..']
|
|
105
|
+
}
|
|
106
|
+
];
|