@sessionvision/core 0.2.0 → 0.4.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/README.md +14 -11
- package/dist/react/capture/autocapture.d.ts +2 -1
- package/dist/react/capture/deadclick.d.ts +19 -0
- package/dist/react/capture/formfields.d.ts +53 -0
- package/dist/react/capture/rageclick.d.ts +25 -0
- package/dist/react/core/config.d.ts +14 -1
- package/dist/react/core/init.d.ts +25 -0
- package/dist/react/recorder/chunk.d.ts +59 -0
- package/dist/react/recorder/index.d.ts +46 -0
- package/dist/react/recorder/mask.d.ts +13 -0
- package/dist/react/recorder/rrweb.d.ts +19 -0
- package/dist/react/recorder/upload.d.ts +20 -0
- package/dist/react/types.d.ts +119 -4
- package/dist/sessionvision-recorder.js +13041 -0
- package/dist/sessionvision-recorder.js.map +1 -0
- package/dist/sessionvision-recorder.min.js +7 -0
- package/dist/sessionvision-recorder.min.js.map +1 -0
- package/dist/sessionvision.cjs.js +1084 -262
- package/dist/sessionvision.cjs.js.map +1 -1
- package/dist/sessionvision.esm.js +1084 -262
- package/dist/sessionvision.esm.js.map +1 -1
- package/dist/sessionvision.js +1084 -262
- package/dist/sessionvision.js.map +1 -1
- package/dist/sessionvision.min.js +2 -2
- package/dist/sessionvision.min.js.map +1 -1
- package/dist/types/capture/autocapture.d.ts +2 -1
- package/dist/types/capture/deadclick.d.ts +19 -0
- package/dist/types/capture/formfields.d.ts +53 -0
- package/dist/types/capture/rageclick.d.ts +25 -0
- package/dist/types/core/config.d.ts +14 -1
- package/dist/types/core/init.d.ts +25 -0
- package/dist/types/recorder/chunk.d.ts +59 -0
- package/dist/types/recorder/index.d.ts +46 -0
- package/dist/types/recorder/mask.d.ts +13 -0
- package/dist/types/recorder/rrweb.d.ts +19 -0
- package/dist/types/recorder/upload.d.ts +20 -0
- package/dist/types/types.d.ts +119 -4
- package/dist/vue/capture/autocapture.d.ts +2 -1
- package/dist/vue/capture/deadclick.d.ts +19 -0
- package/dist/vue/capture/formfields.d.ts +53 -0
- package/dist/vue/capture/rageclick.d.ts +25 -0
- package/dist/vue/core/config.d.ts +14 -1
- package/dist/vue/core/init.d.ts +25 -0
- package/dist/vue/recorder/chunk.d.ts +59 -0
- package/dist/vue/recorder/index.d.ts +46 -0
- package/dist/vue/recorder/mask.d.ts +13 -0
- package/dist/vue/recorder/rrweb.d.ts +19 -0
- package/dist/vue/recorder/upload.d.ts +20 -0
- package/dist/vue/types.d.ts +119 -4
- package/package.json +10 -7
package/README.md
CHANGED
|
@@ -39,12 +39,15 @@ sessionvision.init('proj_abc123', {
|
|
|
39
39
|
```tsx
|
|
40
40
|
import { SessionVisionProvider, useCapture } from '@sessionvision/core/react';
|
|
41
41
|
|
|
42
|
-
function
|
|
42
|
+
function TrackButton() {
|
|
43
43
|
const capture = useCapture();
|
|
44
|
+
return <button onClick={() => capture('cta_clicked')}>Track</button>;
|
|
45
|
+
}
|
|
44
46
|
|
|
47
|
+
function App() {
|
|
45
48
|
return (
|
|
46
|
-
<SessionVisionProvider apiKey=
|
|
47
|
-
<
|
|
49
|
+
<SessionVisionProvider apiKey="your_project_token">
|
|
50
|
+
<TrackButton />
|
|
48
51
|
</SessionVisionProvider>
|
|
49
52
|
);
|
|
50
53
|
}
|
|
@@ -58,7 +61,7 @@ import { createSessionVision } from '@sessionvision/core/vue';
|
|
|
58
61
|
import App from './App.vue';
|
|
59
62
|
|
|
60
63
|
const app = createApp(App);
|
|
61
|
-
app.use(createSessionVision(
|
|
64
|
+
app.use(createSessionVision('your_project_token'));
|
|
62
65
|
app.mount('#app');
|
|
63
66
|
```
|
|
64
67
|
|
|
@@ -119,12 +122,9 @@ npm run test:e2e:headed
|
|
|
119
122
|
npm run test:e2e:debug
|
|
120
123
|
```
|
|
121
124
|
|
|
122
|
-
E2E tests are located in `tests/e2e/` and run against
|
|
125
|
+
E2E tests are located in `tests/e2e/` and run against:
|
|
123
126
|
- Chromium (Desktop)
|
|
124
|
-
- Firefox (Desktop)
|
|
125
|
-
- WebKit/Safari (Desktop)
|
|
126
127
|
- Chrome Mobile (Pixel 5 emulation)
|
|
127
|
-
- Safari Mobile (iPhone 12 emulation)
|
|
128
128
|
|
|
129
129
|
#### E2E Test Infrastructure
|
|
130
130
|
|
|
@@ -227,9 +227,9 @@ The SDK exposes the following methods on the global `sessionvision` object:
|
|
|
227
227
|
sessionvision.init('your_project_token', {
|
|
228
228
|
apiHost: 'https://api.example.com',
|
|
229
229
|
autocapture: {
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
230
|
+
pageview: true,
|
|
231
|
+
click: true,
|
|
232
|
+
formSubmit: true
|
|
233
233
|
}
|
|
234
234
|
});
|
|
235
235
|
|
|
@@ -250,6 +250,9 @@ sessionvision.register({ app_version: '2.1.0' });
|
|
|
250
250
|
|
|
251
251
|
// Register properties only if not already set
|
|
252
252
|
sessionvision.registerOnce({ initial_referrer: document.referrer });
|
|
253
|
+
|
|
254
|
+
// Manually flush the event buffer (useful before navigation)
|
|
255
|
+
await sessionvision.flushEvents();
|
|
253
256
|
```
|
|
254
257
|
|
|
255
258
|
## Architecture
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dead Click Detection
|
|
3
|
+
*
|
|
4
|
+
* Detects clicks that produce no visible DOM changes.
|
|
5
|
+
* Emits $dead_click events when no response is detected.
|
|
6
|
+
*/
|
|
7
|
+
import { ResolvedConfig } from '../types';
|
|
8
|
+
export declare function shouldExcludeFromDeadClick(element: Element): boolean;
|
|
9
|
+
export declare class DeadClickDetector {
|
|
10
|
+
private static readonly DEFAULT_TIMEOUT_MS;
|
|
11
|
+
private pendingClick;
|
|
12
|
+
private timeoutMs;
|
|
13
|
+
constructor(_config: ResolvedConfig);
|
|
14
|
+
monitorClick(event: MouseEvent, element: Element, properties: Record<string, unknown>): void;
|
|
15
|
+
private cancelPending;
|
|
16
|
+
private isMeaningfulMutation;
|
|
17
|
+
private emitDeadClick;
|
|
18
|
+
destroy(): void;
|
|
19
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Form Field Tracking
|
|
3
|
+
*
|
|
4
|
+
* Tracks form field interactions for abandonment analysis.
|
|
5
|
+
* Emits $form_start when user begins filling a form,
|
|
6
|
+
* $form_field_change when fields are modified.
|
|
7
|
+
*/
|
|
8
|
+
import { ResolvedConfig } from '../types';
|
|
9
|
+
/**
|
|
10
|
+
* State for a form that has been started
|
|
11
|
+
*/
|
|
12
|
+
interface FormState {
|
|
13
|
+
startTime: number;
|
|
14
|
+
fieldCount: number;
|
|
15
|
+
interactedFields: Set<string>;
|
|
16
|
+
filledFields: Set<string>;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Get the current state for a form
|
|
20
|
+
*/
|
|
21
|
+
export declare function getFormState(formSelector: string): FormState | undefined;
|
|
22
|
+
/**
|
|
23
|
+
* Reset tracking for a specific form (called after submit)
|
|
24
|
+
*/
|
|
25
|
+
export declare function resetForm(formSelector: string): void;
|
|
26
|
+
/**
|
|
27
|
+
* Get form tracking data for enhanced submit event
|
|
28
|
+
*/
|
|
29
|
+
export declare function getFormTrackingData(form: HTMLFormElement): {
|
|
30
|
+
formSelector: string;
|
|
31
|
+
formFieldCount: number;
|
|
32
|
+
formFieldsFilled: string[];
|
|
33
|
+
formFieldsInteracted: string[];
|
|
34
|
+
formCompletionRate: number;
|
|
35
|
+
formTimeToSubmitMs: number | null;
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Initialize form field tracking
|
|
39
|
+
*/
|
|
40
|
+
export declare function initFormFieldTracking(_cfg: ResolvedConfig): void;
|
|
41
|
+
/**
|
|
42
|
+
* Stop form field tracking
|
|
43
|
+
*/
|
|
44
|
+
export declare function stopFormFieldTracking(): void;
|
|
45
|
+
/**
|
|
46
|
+
* Check if form field tracking is active
|
|
47
|
+
*/
|
|
48
|
+
export declare function isFormFieldTrackingEnabled(): boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Reset for testing
|
|
51
|
+
*/
|
|
52
|
+
export declare function _reset(): void;
|
|
53
|
+
export {};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rage Click Detection
|
|
3
|
+
*
|
|
4
|
+
* Detects rapid repeated clicks indicating user frustration.
|
|
5
|
+
* Emits a single $rage_click event after the click sequence ends.
|
|
6
|
+
*/
|
|
7
|
+
import { ResolvedConfig } from '../types';
|
|
8
|
+
export declare function shouldExcludeFromRageClick(element: Element): boolean;
|
|
9
|
+
export declare class RageClickDetector {
|
|
10
|
+
private clicks;
|
|
11
|
+
private emitTimeout;
|
|
12
|
+
private threshold;
|
|
13
|
+
private windowMs;
|
|
14
|
+
private radiusPx;
|
|
15
|
+
private static readonly DEFAULT_THRESHOLD;
|
|
16
|
+
private static readonly DEFAULT_WINDOW_MS;
|
|
17
|
+
private static readonly DEFAULT_RADIUS_PX;
|
|
18
|
+
constructor(_config: ResolvedConfig);
|
|
19
|
+
recordClick(event: MouseEvent, element: Element, properties: Record<string, unknown>): void;
|
|
20
|
+
private scheduleEmit;
|
|
21
|
+
private maybeEmitRageClick;
|
|
22
|
+
private isClickCluster;
|
|
23
|
+
private emitRageClick;
|
|
24
|
+
destroy(): void;
|
|
25
|
+
}
|
|
@@ -7,10 +7,22 @@ import { SessionVisionConfig, ResolvedConfig, RemoteConfig } from '../types';
|
|
|
7
7
|
* Resolve user config with defaults
|
|
8
8
|
*/
|
|
9
9
|
export declare function resolveConfig(projectToken: string, userConfig?: SessionVisionConfig): ResolvedConfig;
|
|
10
|
+
/**
|
|
11
|
+
* Get cached remote config if valid (exported for fast path in init.ts)
|
|
12
|
+
*/
|
|
13
|
+
export declare function getCachedRemoteConfig(projectToken: string): RemoteConfig | null;
|
|
14
|
+
/**
|
|
15
|
+
* Resolve the recorder bundle URL relative to the SDK's apiHost
|
|
16
|
+
*/
|
|
17
|
+
export declare function resolveRecorderUrl(config: ResolvedConfig): string;
|
|
18
|
+
interface FetchRemoteConfigOptions {
|
|
19
|
+
/** Inject <link rel="prefetch"> for the recorder bundle (for first-time visitors with no cache) */
|
|
20
|
+
prefetchRecorder?: boolean;
|
|
21
|
+
}
|
|
10
22
|
/**
|
|
11
23
|
* Fetch remote configuration from server
|
|
12
24
|
*/
|
|
13
|
-
export declare function fetchRemoteConfig(resolvedConfig: ResolvedConfig): Promise<RemoteConfig | null>;
|
|
25
|
+
export declare function fetchRemoteConfig(resolvedConfig: ResolvedConfig, options?: FetchRemoteConfigOptions): Promise<RemoteConfig | null>;
|
|
14
26
|
/**
|
|
15
27
|
* Apply remote config settings
|
|
16
28
|
*/
|
|
@@ -19,3 +31,4 @@ export declare function applyRemoteConfig(remoteConfig: RemoteConfig): void;
|
|
|
19
31
|
* Get default remote config for offline mode
|
|
20
32
|
*/
|
|
21
33
|
export declare function getDefaultRemoteConfig(): RemoteConfig;
|
|
34
|
+
export {};
|
|
@@ -47,6 +47,31 @@ export declare function isSDKInitialized(): boolean;
|
|
|
47
47
|
* Get the current configuration
|
|
48
48
|
*/
|
|
49
49
|
export declare function getConfig(): ResolvedConfig | null;
|
|
50
|
+
/**
|
|
51
|
+
* Manually start recording. Respects remote config — no-op if recording.enabled is false.
|
|
52
|
+
* Bypasses sampling when recording is enabled.
|
|
53
|
+
*/
|
|
54
|
+
export declare function startRecording(): Promise<void>;
|
|
55
|
+
/**
|
|
56
|
+
* Stop recording for this session
|
|
57
|
+
*/
|
|
58
|
+
export declare function stopRecording(): void;
|
|
59
|
+
/**
|
|
60
|
+
* Check if recording is active
|
|
61
|
+
*/
|
|
62
|
+
export declare function isRecording(): boolean;
|
|
63
|
+
/**
|
|
64
|
+
* Tag the current recording with custom metadata
|
|
65
|
+
*/
|
|
66
|
+
export declare function tagRecordingFn(tags: Record<string, string>): void;
|
|
67
|
+
/**
|
|
68
|
+
* Subscribe to SDK events
|
|
69
|
+
*/
|
|
70
|
+
export declare function onEvent(event: string, callback: (data?: unknown) => void): void;
|
|
71
|
+
/**
|
|
72
|
+
* Unsubscribe from SDK events
|
|
73
|
+
*/
|
|
74
|
+
export declare function offEvent(event: string, callback: (data?: unknown) => void): void;
|
|
50
75
|
/**
|
|
51
76
|
* Reset for testing
|
|
52
77
|
*/
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Chunk manager for recording events
|
|
3
|
+
* Buffers rrweb events and manages chunked uploads
|
|
4
|
+
*/
|
|
5
|
+
import { RecordingEvent, ResolvedConfig } from '../types';
|
|
6
|
+
type EventEmitFn = (event: string, data?: unknown) => void;
|
|
7
|
+
interface ChunkManagerOptions {
|
|
8
|
+
config: ResolvedConfig;
|
|
9
|
+
emit: EventEmitFn;
|
|
10
|
+
}
|
|
11
|
+
export declare class ChunkManager {
|
|
12
|
+
private buffer;
|
|
13
|
+
private bufferSize;
|
|
14
|
+
private chunkNumber;
|
|
15
|
+
private lastFlush;
|
|
16
|
+
private flushTimer;
|
|
17
|
+
private config;
|
|
18
|
+
private emit;
|
|
19
|
+
private tags;
|
|
20
|
+
private chunkStartTime;
|
|
21
|
+
private hasFullSnapshot;
|
|
22
|
+
private started;
|
|
23
|
+
constructor(options: ChunkManagerOptions);
|
|
24
|
+
/**
|
|
25
|
+
* Start the chunk manager flush timer
|
|
26
|
+
*/
|
|
27
|
+
start(): void;
|
|
28
|
+
/**
|
|
29
|
+
* Stop the chunk manager
|
|
30
|
+
*/
|
|
31
|
+
stop(): void;
|
|
32
|
+
/**
|
|
33
|
+
* Add an rrweb event to the buffer
|
|
34
|
+
*/
|
|
35
|
+
addEvent(event: RecordingEvent): void;
|
|
36
|
+
/**
|
|
37
|
+
* Set tags to be sent with the next chunk
|
|
38
|
+
*/
|
|
39
|
+
setTags(tags: Record<string, string>): void;
|
|
40
|
+
/**
|
|
41
|
+
* Check if the buffer should be flushed
|
|
42
|
+
*/
|
|
43
|
+
private shouldFlush;
|
|
44
|
+
/**
|
|
45
|
+
* Flush the buffer — send accumulated events as a chunk
|
|
46
|
+
*/
|
|
47
|
+
flush(): void;
|
|
48
|
+
/**
|
|
49
|
+
* Get the current chunk number (for testing)
|
|
50
|
+
*/
|
|
51
|
+
getChunkNumber(): number;
|
|
52
|
+
/**
|
|
53
|
+
* Get the current buffer size in bytes (for testing)
|
|
54
|
+
*/
|
|
55
|
+
getBufferSize(): number;
|
|
56
|
+
private handleVisibilityChange;
|
|
57
|
+
private handleBeforeUnload;
|
|
58
|
+
}
|
|
59
|
+
export {};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session Recorder entry point
|
|
3
|
+
* Handles initialization, sampling decision, and lifecycle management
|
|
4
|
+
*/
|
|
5
|
+
import { RemoteConfig, ResolvedConfig } from '../types';
|
|
6
|
+
type EventListener = (data?: unknown) => void;
|
|
7
|
+
export declare function on(event: string, callback: EventListener): void;
|
|
8
|
+
export declare function off(event: string, callback: EventListener): void;
|
|
9
|
+
/**
|
|
10
|
+
* Deterministic sampling based on session ID
|
|
11
|
+
* Same session always gets same result (important for multi-page sessions)
|
|
12
|
+
*/
|
|
13
|
+
export declare function shouldRecordSession(sampleRate: number, sessionId: string): boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Initialize the recorder — called after the recorder bundle is loaded
|
|
16
|
+
*/
|
|
17
|
+
export declare function initRecorder(config: ResolvedConfig, _remoteConfig: RemoteConfig): void;
|
|
18
|
+
/**
|
|
19
|
+
* Stop the recorder
|
|
20
|
+
*/
|
|
21
|
+
export declare function stopRecorder(): void;
|
|
22
|
+
/**
|
|
23
|
+
* Check if the recorder is currently active
|
|
24
|
+
*/
|
|
25
|
+
export declare function isRecorderActive(): boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Tag the current recording with custom metadata
|
|
28
|
+
*/
|
|
29
|
+
export declare function tagRecording(tags: Record<string, string>): void;
|
|
30
|
+
/**
|
|
31
|
+
* Reset recorder state (for testing)
|
|
32
|
+
*/
|
|
33
|
+
export declare function _resetRecorder(): void;
|
|
34
|
+
/**
|
|
35
|
+
* Recorder module interface (exposed via global for script-based loading)
|
|
36
|
+
*/
|
|
37
|
+
export interface RecorderModule {
|
|
38
|
+
initRecorder: typeof initRecorder;
|
|
39
|
+
stopRecorder: typeof stopRecorder;
|
|
40
|
+
isRecorderActive: typeof isRecorderActive;
|
|
41
|
+
tagRecording: typeof tagRecording;
|
|
42
|
+
shouldRecordSession: typeof shouldRecordSession;
|
|
43
|
+
on: typeof on;
|
|
44
|
+
off: typeof off;
|
|
45
|
+
}
|
|
46
|
+
export {};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Privacy & masking bridge for session recordings
|
|
3
|
+
* Bridges rrweb's masking callbacks with the SDK's existing PII detection
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Mask text content for rrweb's maskTextFn callback
|
|
7
|
+
*/
|
|
8
|
+
export declare function maskTextForRecording(text: string): string;
|
|
9
|
+
/**
|
|
10
|
+
* Mask input values for rrweb's maskInputFn callback
|
|
11
|
+
* Respects data-sessionvision-unmask attribute
|
|
12
|
+
*/
|
|
13
|
+
export declare function maskInputForRecording(text: string, element: HTMLElement): string;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* rrweb integration module
|
|
3
|
+
* Wraps rrweb with configured capture options and handles events
|
|
4
|
+
*/
|
|
5
|
+
import { RecordingEvent, ResolvedConfig } from '../types';
|
|
6
|
+
type EventCallback = (event: RecordingEvent) => void;
|
|
7
|
+
/**
|
|
8
|
+
* Start rrweb recording
|
|
9
|
+
*/
|
|
10
|
+
export declare function startRrwebRecording(config: ResolvedConfig, onEvent: EventCallback): void;
|
|
11
|
+
/**
|
|
12
|
+
* Stop rrweb recording
|
|
13
|
+
*/
|
|
14
|
+
export declare function stopRrwebRecording(): void;
|
|
15
|
+
/**
|
|
16
|
+
* Check if rrweb is currently recording
|
|
17
|
+
*/
|
|
18
|
+
export declare function isRrwebRecording(): boolean;
|
|
19
|
+
export {};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Upload manager for recording chunks
|
|
3
|
+
* Sends recording chunks to the ingest API as $recording events
|
|
4
|
+
*/
|
|
5
|
+
import { RecordingEvent, ResolvedConfig } from '../types';
|
|
6
|
+
interface ChunkPayload {
|
|
7
|
+
chunkNumber: number;
|
|
8
|
+
startTime: number;
|
|
9
|
+
endTime: number;
|
|
10
|
+
events: RecordingEvent[];
|
|
11
|
+
fullSnapshotIncluded: boolean;
|
|
12
|
+
tags?: Record<string, string>;
|
|
13
|
+
isFirstChunk: boolean;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Send a recording chunk to the ingest API
|
|
17
|
+
* Uses the same endpoint as regular events with the $recording event name
|
|
18
|
+
*/
|
|
19
|
+
export declare function sendRecordingChunk(config: ResolvedConfig, chunk: ChunkPayload): Promise<boolean>;
|
|
20
|
+
export {};
|
package/dist/react/types.d.ts
CHANGED
|
@@ -8,9 +8,15 @@ export interface AutocaptureConfig {
|
|
|
8
8
|
/** Capture $pageview events (default: true) */
|
|
9
9
|
pageview?: boolean;
|
|
10
10
|
/** Capture $click events (default: true) */
|
|
11
|
-
|
|
11
|
+
click?: boolean;
|
|
12
12
|
/** Capture $form_submit events (default: true) */
|
|
13
13
|
formSubmit?: boolean;
|
|
14
|
+
/** Detect rage clicks - rapid repeated clicks indicating frustration (default: true) */
|
|
15
|
+
rageClick?: boolean;
|
|
16
|
+
/** Detect dead clicks - clicks with no DOM response (default: true) */
|
|
17
|
+
deadClick?: boolean;
|
|
18
|
+
/** Track form field interactions for abandonment analysis (default: true) */
|
|
19
|
+
formAbandonment?: boolean;
|
|
14
20
|
}
|
|
15
21
|
/**
|
|
16
22
|
* SDK configuration options passed to init()
|
|
@@ -30,6 +36,10 @@ export interface SessionVisionConfig {
|
|
|
30
36
|
maskAllInputs?: boolean;
|
|
31
37
|
/** Enable/disable auto-capture (default: true) */
|
|
32
38
|
autocapture?: boolean | AutocaptureConfig;
|
|
39
|
+
/** Override recording behavior. Set false to force-disable regardless of remote config. */
|
|
40
|
+
recording?: false | {
|
|
41
|
+
maskAllInputs?: boolean;
|
|
42
|
+
};
|
|
33
43
|
}
|
|
34
44
|
/**
|
|
35
45
|
* Internal resolved configuration
|
|
@@ -44,12 +54,22 @@ export interface ResolvedConfig {
|
|
|
44
54
|
maskAllInputs: boolean;
|
|
45
55
|
autocapture: {
|
|
46
56
|
pageview: boolean;
|
|
47
|
-
|
|
57
|
+
click: boolean;
|
|
48
58
|
formSubmit: boolean;
|
|
59
|
+
rageClick: boolean;
|
|
60
|
+
deadClick: boolean;
|
|
61
|
+
formAbandonment: boolean;
|
|
62
|
+
};
|
|
63
|
+
recording?: false | {
|
|
64
|
+
maskAllInputs?: boolean;
|
|
49
65
|
};
|
|
50
66
|
}
|
|
51
67
|
/**
|
|
52
68
|
* Remote configuration fetched from server
|
|
69
|
+
*
|
|
70
|
+
* Only recording and session settings are remotely configurable.
|
|
71
|
+
* Autocapture settings (including rage/dead click detection) are
|
|
72
|
+
* configured locally via init() options.
|
|
53
73
|
*/
|
|
54
74
|
export interface RemoteConfig {
|
|
55
75
|
recording?: {
|
|
@@ -59,7 +79,6 @@ export interface RemoteConfig {
|
|
|
59
79
|
session?: {
|
|
60
80
|
timeoutMinutes: number;
|
|
61
81
|
};
|
|
62
|
-
version?: string;
|
|
63
82
|
}
|
|
64
83
|
/**
|
|
65
84
|
* User traits for identify()
|
|
@@ -123,6 +142,65 @@ export interface ClickEventProperties extends EventProperties {
|
|
|
123
142
|
$element_selector: string;
|
|
124
143
|
$element_href: string | null;
|
|
125
144
|
}
|
|
145
|
+
/**
|
|
146
|
+
* Rage click event properties
|
|
147
|
+
*/
|
|
148
|
+
export interface RageClickEventProperties extends EventProperties {
|
|
149
|
+
$element_tag: string;
|
|
150
|
+
$element_text: string;
|
|
151
|
+
$element_classes: string;
|
|
152
|
+
$element_id: string | null;
|
|
153
|
+
$element_selector: string;
|
|
154
|
+
$element_href: string | null;
|
|
155
|
+
$click_count: number;
|
|
156
|
+
$rage_click_duration_ms: number;
|
|
157
|
+
$click_x: number;
|
|
158
|
+
$click_y: number;
|
|
159
|
+
$element_x: number;
|
|
160
|
+
$element_y: number;
|
|
161
|
+
$click_positions: Array<{
|
|
162
|
+
x: number;
|
|
163
|
+
y: number;
|
|
164
|
+
timestamp: number;
|
|
165
|
+
}>;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Dead click event properties
|
|
169
|
+
*/
|
|
170
|
+
export interface DeadClickEventProperties extends EventProperties {
|
|
171
|
+
$element_tag: string;
|
|
172
|
+
$element_text: string;
|
|
173
|
+
$element_classes: string;
|
|
174
|
+
$element_id: string | null;
|
|
175
|
+
$element_selector: string;
|
|
176
|
+
$element_href: string | null;
|
|
177
|
+
$click_x: number;
|
|
178
|
+
$click_y: number;
|
|
179
|
+
$element_x: number;
|
|
180
|
+
$element_y: number;
|
|
181
|
+
$wait_duration_ms: number;
|
|
182
|
+
$element_is_interactive: boolean;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Form start event properties
|
|
186
|
+
*/
|
|
187
|
+
export interface FormStartEventProperties extends EventProperties {
|
|
188
|
+
$form_id: string | null;
|
|
189
|
+
$form_name: string | null;
|
|
190
|
+
$form_selector: string;
|
|
191
|
+
$form_field_count: number;
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Form field change event properties
|
|
195
|
+
*/
|
|
196
|
+
export interface FormFieldChangeEventProperties extends EventProperties {
|
|
197
|
+
$form_selector: string;
|
|
198
|
+
$field_selector: string;
|
|
199
|
+
$field_name: string | null;
|
|
200
|
+
$field_type: string;
|
|
201
|
+
$field_index: number;
|
|
202
|
+
$has_value: boolean;
|
|
203
|
+
}
|
|
126
204
|
/**
|
|
127
205
|
* Form submit event properties
|
|
128
206
|
*/
|
|
@@ -131,6 +209,12 @@ export interface FormSubmitEventProperties extends EventProperties {
|
|
|
131
209
|
$form_action: string;
|
|
132
210
|
$form_method: string;
|
|
133
211
|
$form_name: string | null;
|
|
212
|
+
$form_selector: string;
|
|
213
|
+
$form_field_count: number;
|
|
214
|
+
$form_fields_filled: string[];
|
|
215
|
+
$form_fields_interacted: string[];
|
|
216
|
+
$form_completion_rate: number;
|
|
217
|
+
$form_time_to_submit_ms: number | null;
|
|
134
218
|
}
|
|
135
219
|
/**
|
|
136
220
|
* Pageview event properties
|
|
@@ -185,6 +269,20 @@ export interface SessionVisionAPI {
|
|
|
185
269
|
register(properties: EventProperties): void;
|
|
186
270
|
/** Register properties only if they don't already exist */
|
|
187
271
|
registerOnce(properties: EventProperties): void;
|
|
272
|
+
/** Manually flush the event buffer */
|
|
273
|
+
flushEvents(): Promise<void>;
|
|
274
|
+
/** Subscribe to SDK events (e.g., 'recording:error', 'recording:quota_exceeded') */
|
|
275
|
+
on(event: string, callback: (data?: unknown) => void): void;
|
|
276
|
+
/** Unsubscribe from SDK events */
|
|
277
|
+
off(event: string, callback: (data?: unknown) => void): void;
|
|
278
|
+
/** Manually start recording. Respects remote config — no-op if recording.enabled is false. Bypasses sampling when recording is enabled. */
|
|
279
|
+
startRecording(): void;
|
|
280
|
+
/** Stop recording for this session */
|
|
281
|
+
stopRecording(): void;
|
|
282
|
+
/** Check if recording is active */
|
|
283
|
+
isRecording(): boolean;
|
|
284
|
+
/** Tag the current recording with custom metadata */
|
|
285
|
+
tagRecording(tags: Record<string, string>): void;
|
|
188
286
|
/** SDK version */
|
|
189
287
|
version: string;
|
|
190
288
|
/** Internal: queued method calls before SDK loads */
|
|
@@ -194,6 +292,23 @@ export interface SessionVisionAPI {
|
|
|
194
292
|
/** Internal: SDK version marker */
|
|
195
293
|
__SV?: number;
|
|
196
294
|
}
|
|
295
|
+
/**
|
|
296
|
+
* Recording event type (rrweb event)
|
|
297
|
+
*/
|
|
298
|
+
export interface RecordingEvent {
|
|
299
|
+
type: number;
|
|
300
|
+
data: unknown;
|
|
301
|
+
timestamp: number;
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Recording chunk configuration
|
|
305
|
+
*/
|
|
306
|
+
export declare const RECORDING_CONFIG: {
|
|
307
|
+
readonly FLUSH_INTERVAL_MS: 5000;
|
|
308
|
+
readonly MAX_BUFFER_SIZE_BYTES: number;
|
|
309
|
+
readonly FULL_SNAPSHOT_INTERVAL_MS: number;
|
|
310
|
+
readonly RETRY_DELAY_MS: 2000;
|
|
311
|
+
};
|
|
197
312
|
/**
|
|
198
313
|
* Storage key constants
|
|
199
314
|
*/
|
|
@@ -223,6 +338,6 @@ export declare const BUFFER_CONFIG: {
|
|
|
223
338
|
readonly RETRY_DELAYS_MS: readonly [1000, 2000, 4000];
|
|
224
339
|
};
|
|
225
340
|
/**
|
|
226
|
-
* Config cache TTL in milliseconds (
|
|
341
|
+
* Config cache TTL in milliseconds (4 hours)
|
|
227
342
|
*/
|
|
228
343
|
export declare const CONFIG_CACHE_TTL_MS: number;
|