humanbehavior-js 0.0.9 → 0.1.0
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 +345 -184
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/react/index.js +51 -77
- package/dist/cjs/react/index.js.map +1 -1
- package/dist/esm/index.js +345 -184
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/react/index.js +48 -77
- 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 +60 -12
- package/dist/types/react/index.d.ts +8 -9
- package/package.json +2 -1
- package/readme.md +127 -105
- package/simple-spa.html +544 -0
- package/src/api.ts +4 -134
- package/src/react/index.tsx +61 -28
- package/src/tracker.ts +404 -87
package/dist/types/index.d.ts
CHANGED
|
@@ -83,6 +83,7 @@ declare const redactionManager: RedactionManager;
|
|
|
83
83
|
declare global {
|
|
84
84
|
interface Window {
|
|
85
85
|
HumanBehaviorTracker: typeof HumanBehaviorTracker;
|
|
86
|
+
__humanBehaviorGlobalTracker?: HumanBehaviorTracker;
|
|
86
87
|
}
|
|
87
88
|
}
|
|
88
89
|
declare class HumanBehaviorTracker {
|
|
@@ -102,11 +103,46 @@ declare class HumanBehaviorTracker {
|
|
|
102
103
|
initializationPromise: Promise<void> | null;
|
|
103
104
|
private redactionManager;
|
|
104
105
|
private originalConsole;
|
|
105
|
-
private originalLogger;
|
|
106
106
|
private consoleTrackingEnabled;
|
|
107
|
+
navigationTrackingEnabled: boolean;
|
|
108
|
+
private currentUrl;
|
|
109
|
+
private previousUrl;
|
|
110
|
+
private originalPushState;
|
|
111
|
+
private originalReplaceState;
|
|
112
|
+
private navigationListeners;
|
|
113
|
+
private _connectionBlocked;
|
|
114
|
+
/**
|
|
115
|
+
* Initialize the HumanBehavior tracker
|
|
116
|
+
* This is the main entry point - call this once per page
|
|
117
|
+
*/
|
|
118
|
+
static init(apiKey: string, options?: {
|
|
119
|
+
ingestionUrl?: string;
|
|
120
|
+
logLevel?: 'none' | 'error' | 'warn' | 'info' | 'debug';
|
|
121
|
+
redactFields?: string[];
|
|
122
|
+
}): HumanBehaviorTracker;
|
|
107
123
|
constructor(apiKey: string | undefined, ingestionUrl?: string);
|
|
108
124
|
private init;
|
|
109
125
|
private ensureInitialized;
|
|
126
|
+
/**
|
|
127
|
+
* Setup navigation event tracking for SPA navigation
|
|
128
|
+
*/
|
|
129
|
+
private setupNavigationTracking;
|
|
130
|
+
/**
|
|
131
|
+
* Track navigation events and send custom events
|
|
132
|
+
*/
|
|
133
|
+
trackNavigationEvent(type: string, fromUrl: string, toUrl: string): Promise<void>;
|
|
134
|
+
/**
|
|
135
|
+
* Track a page view event (PostHog-style)
|
|
136
|
+
*/
|
|
137
|
+
trackPageView(url?: string): Promise<void>;
|
|
138
|
+
/**
|
|
139
|
+
* Track a custom event (PostHog-style)
|
|
140
|
+
*/
|
|
141
|
+
customEvent(eventName: string, properties?: Record<string, any>): Promise<void>;
|
|
142
|
+
/**
|
|
143
|
+
* Cleanup navigation tracking
|
|
144
|
+
*/
|
|
145
|
+
private cleanupNavigationTracking;
|
|
110
146
|
static logToStorage(message: string): void;
|
|
111
147
|
/**
|
|
112
148
|
* Configure logging behavior for the SDK
|
|
@@ -125,9 +161,6 @@ declare class HumanBehaviorTracker {
|
|
|
125
161
|
* Disable console event tracking
|
|
126
162
|
*/
|
|
127
163
|
disableConsoleTracking(): void;
|
|
128
|
-
/**
|
|
129
|
-
* Track console events
|
|
130
|
-
*/
|
|
131
164
|
private trackConsoleEvent;
|
|
132
165
|
private setupPageUnloadHandler;
|
|
133
166
|
viewLogs(): void;
|
|
@@ -137,7 +170,6 @@ declare class HumanBehaviorTracker {
|
|
|
137
170
|
* @param authFields Array of field names to check for existing users (e.g., ['email', 'phoneNumber'])
|
|
138
171
|
*/
|
|
139
172
|
auth(authFields: string[]): Promise<void>;
|
|
140
|
-
customEvent(eventName: string, eventProperties?: Record<string, any>): Promise<void>;
|
|
141
173
|
start(): Promise<void>;
|
|
142
174
|
stop(): Promise<void>;
|
|
143
175
|
addEvent(event: any): Promise<void>;
|
|
@@ -163,6 +195,28 @@ declare class HumanBehaviorTracker {
|
|
|
163
195
|
* Get the currently selected fields for redaction
|
|
164
196
|
*/
|
|
165
197
|
getRedactedFields(): string[];
|
|
198
|
+
/**
|
|
199
|
+
* Get the current session ID
|
|
200
|
+
*/
|
|
201
|
+
getSessionId(): string;
|
|
202
|
+
/**
|
|
203
|
+
* Get the current URL being tracked
|
|
204
|
+
*/
|
|
205
|
+
getCurrentUrl(): string;
|
|
206
|
+
/**
|
|
207
|
+
* Test if the tracker can reach the ingestion server
|
|
208
|
+
*/
|
|
209
|
+
testConnection(): Promise<{
|
|
210
|
+
success: boolean;
|
|
211
|
+
error?: string;
|
|
212
|
+
}>;
|
|
213
|
+
/**
|
|
214
|
+
* Get connection status and recommendations
|
|
215
|
+
*/
|
|
216
|
+
getConnectionStatus(): {
|
|
217
|
+
blocked: boolean;
|
|
218
|
+
recommendations: string[];
|
|
219
|
+
};
|
|
166
220
|
}
|
|
167
221
|
|
|
168
222
|
declare const MAX_CHUNK_SIZE_BYTES: number;
|
|
@@ -183,13 +237,7 @@ declare class HumanBehaviorAPI {
|
|
|
183
237
|
sendEventsChunked(events: any[], sessionId: string): Promise<any[]>;
|
|
184
238
|
sendUserData(userId: string, userData: Record<string, any>, sessionId: string): Promise<any>;
|
|
185
239
|
sendUserAuth(userId: string, userData: Record<string, any>, sessionId: string, authFields: string[]): Promise<any>;
|
|
186
|
-
|
|
187
|
-
sendCustomEvent(eventName: string, eventProperties: Record<string, any>, sessionId: string): Promise<any>;
|
|
188
|
-
sendCustomEvents(events: any[], sessionId: string): Promise<any>;
|
|
189
|
-
sendBeaconEvents(events: any[], sessionId: string, isSessionComplete?: boolean): void;
|
|
190
|
-
sendBeaconSessionComplete(sessionId: string): void;
|
|
191
|
-
sendBeaconCustomEvent(eventName: string, eventProperties: Record<string, any>, sessionId: string): boolean;
|
|
192
|
-
sendBeaconCustomEvents(events: any[], sessionId: string): boolean;
|
|
240
|
+
sendBeaconEvents(events: any[], sessionId: string): void;
|
|
193
241
|
}
|
|
194
242
|
|
|
195
243
|
declare enum LogLevel {
|
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
import React, { ReactNode } from 'react';
|
|
2
2
|
import { HumanBehaviorTracker } from '..';
|
|
3
|
+
export { HumanBehaviorTracker } from '..';
|
|
3
4
|
|
|
4
|
-
interface HumanBehaviorInterface {
|
|
5
|
-
addEvent: (event: any) => void;
|
|
6
|
-
addUserInfo: (userProperties: Record<string, any>) => Promise<void>;
|
|
7
|
-
start: () => void;
|
|
8
|
-
stop: () => void;
|
|
9
|
-
viewLogs: () => void;
|
|
10
|
-
}
|
|
11
5
|
interface HumanBehaviorProviderProps {
|
|
12
6
|
apiKey?: string;
|
|
13
7
|
client?: HumanBehaviorTracker;
|
|
14
8
|
children: ReactNode;
|
|
9
|
+
options?: {
|
|
10
|
+
ingestionUrl?: string;
|
|
11
|
+
logLevel?: 'none' | 'error' | 'warn' | 'info' | 'debug';
|
|
12
|
+
redactFields?: string[];
|
|
13
|
+
};
|
|
15
14
|
}
|
|
16
|
-
declare const HumanBehaviorProvider: ({ apiKey, client, children }: HumanBehaviorProviderProps) => React.JSX.Element;
|
|
17
|
-
declare const useHumanBehavior: () =>
|
|
15
|
+
declare const HumanBehaviorProvider: ({ apiKey, client, children, options }: HumanBehaviorProviderProps) => React.JSX.Element;
|
|
16
|
+
declare const useHumanBehavior: () => HumanBehaviorTracker;
|
|
18
17
|
|
|
19
18
|
export { HumanBehaviorProvider, useHumanBehavior };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "humanbehavior-js",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"description": "SDK for HumanBehavior session and event recording",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/cjs/index.js",
|
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
"license": "ISC",
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"@types/react": "^19.0.12",
|
|
32
|
+
"humanbehavior-js": "^0.0.9",
|
|
32
33
|
"react": "^19.0.0",
|
|
33
34
|
"rrweb": "^2.0.0-alpha.4",
|
|
34
35
|
"uuid": "^11.1.0"
|
package/readme.md
CHANGED
|
@@ -1,145 +1,167 @@
|
|
|
1
1
|
# HumanBehavior SDK
|
|
2
2
|
|
|
3
|
-
A
|
|
3
|
+
A simplified session recording and analytics SDK that maintains session continuity across page navigations.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Quick Start
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
### Single Page Application (Recommended)
|
|
8
|
+
|
|
9
|
+
For the best session continuity experience, use the SPA approach:
|
|
10
|
+
|
|
11
|
+
```html
|
|
12
|
+
<!DOCTYPE html>
|
|
13
|
+
<html>
|
|
14
|
+
<head>
|
|
15
|
+
<script src="dist/index.min.js"></script>
|
|
16
|
+
</head>
|
|
17
|
+
<body>
|
|
18
|
+
<script>
|
|
19
|
+
// Initialize once - session persists across all navigation
|
|
20
|
+
const tracker = HumanBehaviorTracker.init('your-api-key', {
|
|
21
|
+
logLevel: 'debug',
|
|
22
|
+
redactFields: ['password', 'credit_card']
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
// Your SPA navigation logic here
|
|
26
|
+
function navigateToPage(page) {
|
|
27
|
+
// Update content without page reload
|
|
28
|
+
loadPageContent(page);
|
|
29
|
+
|
|
30
|
+
// Track navigation
|
|
31
|
+
tracker.trackNavigationEvent('spa_navigation', currentPage, page);
|
|
32
|
+
}
|
|
33
|
+
</script>
|
|
34
|
+
</body>
|
|
35
|
+
</html>
|
|
9
36
|
```
|
|
10
37
|
|
|
11
|
-
|
|
38
|
+
### Traditional Multi-Page Setup
|
|
12
39
|
|
|
13
|
-
|
|
40
|
+
For traditional HTML pages, the tracker will automatically restore sessions:
|
|
14
41
|
|
|
15
42
|
```html
|
|
16
|
-
|
|
43
|
+
<!-- index.html -->
|
|
44
|
+
<script src="dist/index.min.js"></script>
|
|
17
45
|
<script>
|
|
18
|
-
const tracker =
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
46
|
+
const tracker = HumanBehaviorTracker.init('your-api-key');
|
|
47
|
+
</script>
|
|
48
|
+
|
|
49
|
+
<!-- about.html -->
|
|
50
|
+
<script src="dist/index.min.js"></script>
|
|
51
|
+
<script>
|
|
52
|
+
const tracker = HumanBehaviorTracker.init('your-api-key'); // Reuses existing session
|
|
23
53
|
</script>
|
|
24
54
|
```
|
|
25
55
|
|
|
26
|
-
|
|
56
|
+
## API Reference
|
|
57
|
+
|
|
58
|
+
### Initialization
|
|
27
59
|
|
|
28
|
-
|
|
60
|
+
```javascript
|
|
61
|
+
// Main initialization method
|
|
62
|
+
const tracker = HumanBehaviorTracker.init(apiKey, options);
|
|
63
|
+
```
|
|
29
64
|
|
|
30
|
-
|
|
31
|
-
|
|
65
|
+
**Options:**
|
|
66
|
+
- `ingestionUrl`: Custom ingestion server URL
|
|
67
|
+
- `logLevel`: 'none' | 'error' | 'warn' | 'info' | 'debug'
|
|
68
|
+
- `redactFields`: Array of CSS selectors to redact
|
|
32
69
|
|
|
33
|
-
|
|
34
|
-
import { HumanBehaviorProvider } from "humanbehavior-js/react";
|
|
35
|
-
import { useEffect, useState } from "react";
|
|
70
|
+
### Session Management
|
|
36
71
|
|
|
37
|
-
|
|
38
|
-
|
|
72
|
+
```javascript
|
|
73
|
+
// Get current session ID
|
|
74
|
+
const sessionId = tracker.getSessionId();
|
|
39
75
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
}
|
|
46
|
-
}, []);
|
|
47
|
-
|
|
48
|
-
return (
|
|
49
|
-
<HumanBehaviorProvider client={tracker}>
|
|
50
|
-
{children}
|
|
51
|
-
</HumanBehaviorProvider>
|
|
52
|
-
)
|
|
53
|
-
}
|
|
76
|
+
// Get current URL
|
|
77
|
+
const currentUrl = tracker.getCurrentUrl();
|
|
78
|
+
|
|
79
|
+
// Test connection to ingestion server
|
|
80
|
+
const result = await tracker.testConnection();
|
|
54
81
|
```
|
|
55
82
|
|
|
56
|
-
|
|
83
|
+
### Event Tracking
|
|
57
84
|
|
|
58
|
-
```
|
|
59
|
-
|
|
85
|
+
```javascript
|
|
86
|
+
// Track custom events
|
|
87
|
+
await tracker.customEvent('button_click', { button: 'submit' });
|
|
60
88
|
|
|
61
|
-
|
|
89
|
+
// Track page views
|
|
90
|
+
await tracker.trackPageView();
|
|
62
91
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
<HumanBehaviorProvider apiKey={process.env.NEXT_PUBLIC_HUMANBEHAVIOR_API_KEY}>
|
|
66
|
-
{children}
|
|
67
|
-
</HumanBehaviorProvider>
|
|
68
|
-
)
|
|
69
|
-
}
|
|
92
|
+
// Track navigation (for SPAs)
|
|
93
|
+
await tracker.trackNavigationEvent('pushState', '/home', '/about');
|
|
70
94
|
```
|
|
71
95
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
```tsx
|
|
75
|
-
export default async function RootLayout({
|
|
76
|
-
children
|
|
77
|
-
}: {
|
|
78
|
-
children: React.ReactNode;
|
|
79
|
-
}) {
|
|
80
|
-
return (
|
|
81
|
-
<html lang='en' suppressHydrationWarning>
|
|
82
|
-
<body>
|
|
83
|
-
<HumanBehaviorProviderWrapper>
|
|
84
|
-
{children}
|
|
85
|
-
</HumanBehaviorProviderWrapper>
|
|
86
|
-
</body>
|
|
87
|
-
</html>
|
|
88
|
-
);
|
|
89
|
-
}
|
|
90
|
-
```
|
|
96
|
+
### Data Redaction
|
|
91
97
|
|
|
92
|
-
|
|
98
|
+
```javascript
|
|
99
|
+
// Redact sensitive fields
|
|
100
|
+
tracker.setRedactedFields(['input[type="password"]', '#email']);
|
|
93
101
|
|
|
94
|
-
|
|
102
|
+
// Check if redaction is active
|
|
103
|
+
const isActive = tracker.isRedactedFields();
|
|
104
|
+
```
|
|
95
105
|
|
|
96
|
-
|
|
97
|
-
import { useHumanBehavior } from "humanbehavior-js/react";
|
|
106
|
+
### Debugging
|
|
98
107
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
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
|
-
}
|
|
108
|
+
```javascript
|
|
109
|
+
// View logs
|
|
110
|
+
tracker.viewLogs();
|
|
111
|
+
|
|
112
|
+
// Get connection status
|
|
113
|
+
const status = tracker.getConnectionStatus();
|
|
119
114
|
```
|
|
120
115
|
|
|
121
|
-
##
|
|
116
|
+
## Session Continuity
|
|
122
117
|
|
|
123
|
-
|
|
118
|
+
The SDK automatically handles session continuity:
|
|
124
119
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
120
|
+
1. **Session Restoration**: Automatically restores sessions within 30 minutes
|
|
121
|
+
2. **Activity Tracking**: Updates activity timestamp on user interactions
|
|
122
|
+
3. **Cross-Page Persistence**: Session persists across page navigations
|
|
123
|
+
|
|
124
|
+
## Demo
|
|
125
|
+
|
|
126
|
+
Check out `simple-spa.html` for a complete single-page application demo that shows:
|
|
127
|
+
|
|
128
|
+
- True session continuity across navigation
|
|
129
|
+
- Interactive event tracking
|
|
130
|
+
- Real-time status updates
|
|
131
|
+
- Modern UI with smooth transitions
|
|
130
132
|
|
|
131
|
-
##
|
|
133
|
+
## Troubleshooting
|
|
132
134
|
|
|
133
|
-
|
|
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
|
|
135
|
+
### Ad Blocker Issues
|
|
138
136
|
|
|
139
|
-
|
|
137
|
+
If you see `net::ERR_BLOCKED_BY_CLIENT` errors:
|
|
140
138
|
|
|
141
|
-
|
|
139
|
+
1. Check if ad blockers are active
|
|
140
|
+
2. Use `tracker.getConnectionStatus()` to diagnose
|
|
141
|
+
3. Consider whitelisting your domain
|
|
142
|
+
|
|
143
|
+
### Session Issues
|
|
144
|
+
|
|
145
|
+
- Sessions automatically expire after 30 minutes of inactivity
|
|
146
|
+
- Each page load calls `/init` but reuses existing sessions when possible
|
|
147
|
+
- Check browser console for session restoration logs
|
|
148
|
+
|
|
149
|
+
## Development
|
|
142
150
|
|
|
143
151
|
```bash
|
|
152
|
+
# Build the SDK
|
|
144
153
|
npm run build
|
|
145
|
-
|
|
154
|
+
|
|
155
|
+
# Watch for changes
|
|
156
|
+
npm run dev
|
|
157
|
+
|
|
158
|
+
# Run tests
|
|
159
|
+
npm test
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## Architecture
|
|
163
|
+
|
|
164
|
+
- **Frontend**: TypeScript SDK with session restoration
|
|
165
|
+
- **Backend**: Node.js ingestion server with Redis storage
|
|
166
|
+
- **Archiver**: Processes completed sessions to S3 and Prisma
|
|
167
|
+
- **Session Continuity**: localStorage + cookie-based session management
|