@supernal/interface 1.0.13 → 1.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/src/index.js +18 -1
- package/dist/cjs/src/index.js.map +1 -1
- package/dist/cjs/src/tracking/SITrackingProvider.js +126 -0
- package/dist/cjs/src/tracking/SITrackingProvider.js.map +1 -0
- package/dist/cjs/src/tracking/hooks.js +233 -0
- package/dist/cjs/src/tracking/hooks.js.map +1 -0
- package/dist/cjs/src/tracking/index.js +67 -0
- package/dist/cjs/src/tracking/index.js.map +1 -0
- package/dist/cjs/src/tracking/tracker.js +289 -0
- package/dist/cjs/src/tracking/tracker.js.map +1 -0
- package/dist/esm/src/index.d.ts +3 -0
- package/dist/esm/src/index.d.ts.map +1 -1
- package/dist/esm/src/index.js +4 -0
- package/dist/esm/src/index.js.map +1 -1
- package/dist/esm/src/tracking/SITrackingProvider.d.ts +64 -0
- package/dist/esm/src/tracking/SITrackingProvider.d.ts.map +1 -0
- package/dist/esm/src/tracking/SITrackingProvider.js +82 -0
- package/dist/esm/src/tracking/SITrackingProvider.js.map +1 -0
- package/dist/esm/src/tracking/hooks.d.ts +112 -0
- package/dist/esm/src/tracking/hooks.d.ts.map +1 -0
- package/dist/esm/src/tracking/hooks.js +215 -0
- package/dist/esm/src/tracking/hooks.js.map +1 -0
- package/dist/esm/src/tracking/index.d.ts +48 -0
- package/dist/esm/src/tracking/index.d.ts.map +1 -0
- package/dist/esm/src/tracking/index.js +51 -0
- package/dist/esm/src/tracking/index.js.map +1 -0
- package/dist/esm/src/tracking/tracker.d.ts +121 -0
- package/dist/esm/src/tracking/tracker.d.ts.map +1 -0
- package/dist/esm/src/tracking/tracker.js +284 -0
- package/dist/esm/src/tracking/tracker.js.map +1 -0
- package/package.json +9 -4
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SI Tracking React Hooks
|
|
3
|
+
*
|
|
4
|
+
* React hooks for integrating Supernal Interface tracking into components.
|
|
5
|
+
*
|
|
6
|
+
* @packageDocumentation
|
|
7
|
+
*/
|
|
8
|
+
'use client';
|
|
9
|
+
import { useCallback, useEffect, useRef, useContext, createContext } from 'react';
|
|
10
|
+
// Context for providing tracker instance
|
|
11
|
+
const SITrackerContext = createContext(null);
|
|
12
|
+
export const SITrackerProvider = SITrackerContext.Provider;
|
|
13
|
+
/**
|
|
14
|
+
* Get the tracker instance from context
|
|
15
|
+
*/
|
|
16
|
+
export function useTracker() {
|
|
17
|
+
return useContext(SITrackerContext);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Hook to sync auth state with tracker
|
|
21
|
+
* Place this once in your app layout
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```tsx
|
|
25
|
+
* function App() {
|
|
26
|
+
* const { user } = useAuth();
|
|
27
|
+
* useSITrackingInit(tracker, user?.id);
|
|
28
|
+
* return <div>...</div>;
|
|
29
|
+
* }
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export function useSITrackingInit(tracker, userId) {
|
|
33
|
+
useEffect(() => {
|
|
34
|
+
if (tracker) {
|
|
35
|
+
tracker.setUserId(userId ?? null);
|
|
36
|
+
}
|
|
37
|
+
}, [tracker, userId]);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Hook for tracking click events
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```tsx
|
|
44
|
+
* const trackClick = useTrackClick(tracker, 'PostCard');
|
|
45
|
+
* <button onClick={() => trackClick('like', postId)}>Like</button>
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
export function useTrackClick(tracker, componentId) {
|
|
49
|
+
return useCallback((action, targetId, metadata) => {
|
|
50
|
+
if (tracker) {
|
|
51
|
+
tracker.trackClick(componentId, action, targetId, metadata);
|
|
52
|
+
}
|
|
53
|
+
}, [tracker, componentId]);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Hook for tracking component views (impressions)
|
|
57
|
+
* Automatically tracks when component mounts
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* ```tsx
|
|
61
|
+
* useTrackView(tracker, 'PostCard', post.id);
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
64
|
+
export function useTrackView(tracker, componentId, targetId, options) {
|
|
65
|
+
const { trackOnMount = true } = options ?? {};
|
|
66
|
+
useEffect(() => {
|
|
67
|
+
if (tracker && trackOnMount) {
|
|
68
|
+
tracker.trackView(componentId, targetId);
|
|
69
|
+
}
|
|
70
|
+
}, [tracker, componentId, targetId, trackOnMount]);
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Hook for tracking engagement time on a specific target
|
|
74
|
+
* Automatically handles start/end of engagement session
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* ```tsx
|
|
78
|
+
* const { recordInteraction } = useTrackEngagement(tracker, post.id);
|
|
79
|
+
* <button onClick={recordInteraction}>Interact</button>
|
|
80
|
+
* ```
|
|
81
|
+
*/
|
|
82
|
+
export function useTrackEngagement(tracker, targetId, componentId = 'Content') {
|
|
83
|
+
const engagementStarted = useRef(false);
|
|
84
|
+
useEffect(() => {
|
|
85
|
+
if (!tracker || !targetId)
|
|
86
|
+
return;
|
|
87
|
+
// Start engagement tracking
|
|
88
|
+
tracker.startEngagement(targetId);
|
|
89
|
+
engagementStarted.current = true;
|
|
90
|
+
return () => {
|
|
91
|
+
// End engagement tracking on unmount
|
|
92
|
+
if (engagementStarted.current && tracker) {
|
|
93
|
+
tracker.endEngagement(targetId, componentId);
|
|
94
|
+
engagementStarted.current = false;
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
}, [tracker, targetId, componentId]);
|
|
98
|
+
const recordInteraction = useCallback(() => {
|
|
99
|
+
if (tracker) {
|
|
100
|
+
tracker.recordEngagementInteraction(targetId);
|
|
101
|
+
}
|
|
102
|
+
}, [tracker, targetId]);
|
|
103
|
+
return { recordInteraction };
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Hook for tracking scroll depth in feed
|
|
107
|
+
* Attach to a scrollable container
|
|
108
|
+
*
|
|
109
|
+
* @example
|
|
110
|
+
* ```tsx
|
|
111
|
+
* const { handleScroll, resetScroll } = useTrackScrollDepth(tracker);
|
|
112
|
+
* <div onScroll={handleScroll}>...</div>
|
|
113
|
+
* ```
|
|
114
|
+
*/
|
|
115
|
+
export function useTrackScrollDepth(tracker, componentId = 'Feed') {
|
|
116
|
+
const handleScroll = useCallback((event) => {
|
|
117
|
+
if (!tracker)
|
|
118
|
+
return;
|
|
119
|
+
const target = event.currentTarget;
|
|
120
|
+
const scrollHeight = target.scrollHeight - target.clientHeight;
|
|
121
|
+
if (scrollHeight <= 0)
|
|
122
|
+
return;
|
|
123
|
+
const scrollPercent = Math.round((target.scrollTop / scrollHeight) * 100);
|
|
124
|
+
tracker.trackScrollDepth(scrollPercent, componentId);
|
|
125
|
+
}, [tracker, componentId]);
|
|
126
|
+
const resetScroll = useCallback(() => {
|
|
127
|
+
if (tracker) {
|
|
128
|
+
tracker.resetScrollTracking();
|
|
129
|
+
}
|
|
130
|
+
}, [tracker]);
|
|
131
|
+
// Reset on mount
|
|
132
|
+
useEffect(() => {
|
|
133
|
+
if (tracker) {
|
|
134
|
+
tracker.resetScrollTracking();
|
|
135
|
+
}
|
|
136
|
+
}, [tracker]);
|
|
137
|
+
return { handleScroll, resetScroll };
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Hook for tracking intersection observer visibility
|
|
141
|
+
* Useful for tracking when components come into view in feed
|
|
142
|
+
*
|
|
143
|
+
* @example
|
|
144
|
+
* ```tsx
|
|
145
|
+
* const ref = useTrackVisibility(tracker, 'PostCard', post.id);
|
|
146
|
+
* <div ref={ref}>...</div>
|
|
147
|
+
* ```
|
|
148
|
+
*/
|
|
149
|
+
export function useTrackVisibility(tracker, componentId, targetId, options) {
|
|
150
|
+
const { threshold = 0.5 } = options ?? {};
|
|
151
|
+
const hasTracked = useRef(false);
|
|
152
|
+
const observerRef = useRef(null);
|
|
153
|
+
const refCallback = useCallback((element) => {
|
|
154
|
+
// Cleanup previous observer
|
|
155
|
+
if (observerRef.current) {
|
|
156
|
+
observerRef.current.disconnect();
|
|
157
|
+
observerRef.current = null;
|
|
158
|
+
}
|
|
159
|
+
if (!element || !tracker)
|
|
160
|
+
return;
|
|
161
|
+
// Create new observer
|
|
162
|
+
observerRef.current = new IntersectionObserver((entries) => {
|
|
163
|
+
entries.forEach((entry) => {
|
|
164
|
+
if (entry.isIntersecting && !hasTracked.current) {
|
|
165
|
+
tracker.trackView(componentId, targetId);
|
|
166
|
+
hasTracked.current = true;
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
}, { threshold });
|
|
170
|
+
observerRef.current.observe(element);
|
|
171
|
+
}, [tracker, componentId, targetId, threshold]);
|
|
172
|
+
// Reset tracking flag when targetId changes
|
|
173
|
+
useEffect(() => {
|
|
174
|
+
hasTracked.current = false;
|
|
175
|
+
}, [targetId]);
|
|
176
|
+
// Cleanup on unmount
|
|
177
|
+
useEffect(() => {
|
|
178
|
+
return () => {
|
|
179
|
+
if (observerRef.current) {
|
|
180
|
+
observerRef.current.disconnect();
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
}, []);
|
|
184
|
+
return refCallback;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Create a component-specific tracking hook factory
|
|
188
|
+
*
|
|
189
|
+
* @example
|
|
190
|
+
* ```typescript
|
|
191
|
+
* // Define your actions
|
|
192
|
+
* type PostActions = 'like' | 'unlike' | 'share' | 'bookmark';
|
|
193
|
+
*
|
|
194
|
+
* // Create hooks for PostCard
|
|
195
|
+
* export function usePostCardTracking(tracker: SITracker<PostActions>, postId: string) {
|
|
196
|
+
* const trackClick = useTrackClick(tracker, 'PostCard');
|
|
197
|
+
* const visibilityRef = useTrackVisibility(tracker, 'PostCard', postId);
|
|
198
|
+
*
|
|
199
|
+
* return {
|
|
200
|
+
* trackLike: () => trackClick('like', postId),
|
|
201
|
+
* trackShare: () => trackClick('share', postId),
|
|
202
|
+
* visibilityRef,
|
|
203
|
+
* };
|
|
204
|
+
* }
|
|
205
|
+
* ```
|
|
206
|
+
*/
|
|
207
|
+
export function createComponentTrackingHook(componentId, factory) {
|
|
208
|
+
return function useComponentTracking(tracker, targetId) {
|
|
209
|
+
const trackClick = useTrackClick(tracker, componentId);
|
|
210
|
+
if (!tracker)
|
|
211
|
+
return null;
|
|
212
|
+
return factory(trackClick, tracker, targetId);
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
//# sourceMappingURL=hooks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks.js","sourceRoot":"","sources":["../../../../src/tracking/hooks.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Supernal Interface Tracking Module
|
|
3
|
+
*
|
|
4
|
+
* Analytics and interaction tracking for SI-enabled applications.
|
|
5
|
+
* Automatically batches events, handles offline scenarios, and provides
|
|
6
|
+
* React hooks for easy integration.
|
|
7
|
+
*
|
|
8
|
+
* @packageDocumentation
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* // Create a tracker
|
|
13
|
+
* import { createTracker, TrackingProvider, useTrackClick } from '@supernal/interface/tracking';
|
|
14
|
+
*
|
|
15
|
+
* const tracker = createTracker({
|
|
16
|
+
* endpoint: '/api/v1/analytics',
|
|
17
|
+
* batchSize: 10,
|
|
18
|
+
* debug: process.env.NODE_ENV === 'development',
|
|
19
|
+
* });
|
|
20
|
+
*
|
|
21
|
+
* // Provide to React tree
|
|
22
|
+
* function App() {
|
|
23
|
+
* const { user } = useAuth();
|
|
24
|
+
* return (
|
|
25
|
+
* <TrackingProvider tracker={tracker} userId={user?.id}>
|
|
26
|
+
* <YourApp />
|
|
27
|
+
* </TrackingProvider>
|
|
28
|
+
* );
|
|
29
|
+
* }
|
|
30
|
+
*
|
|
31
|
+
* // Use in components
|
|
32
|
+
* function PostCard({ post }) {
|
|
33
|
+
* const tracker = useTracker();
|
|
34
|
+
* const trackClick = useTrackClick(tracker, 'PostCard');
|
|
35
|
+
* const visibilityRef = useTrackVisibility(tracker, 'PostCard', post.id);
|
|
36
|
+
*
|
|
37
|
+
* return (
|
|
38
|
+
* <div ref={visibilityRef}>
|
|
39
|
+
* <button onClick={() => trackClick('like', post.id)}>Like</button>
|
|
40
|
+
* </div>
|
|
41
|
+
* );
|
|
42
|
+
* }
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export { SITracker, createTracker, type SITrackerConfig, type SIInteraction, type SIBaseAction, } from './tracker';
|
|
46
|
+
export { SITrackerProvider, useTracker, useSITrackingInit, useTrackClick, useTrackView, useTrackEngagement, useTrackScrollDepth, useTrackVisibility, createComponentTrackingHook, } from './hooks';
|
|
47
|
+
export { TrackingProvider, withTracking, type SITrackingProviderProps } from './SITrackingProvider';
|
|
48
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/tracking/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAGH,OAAO,EACL,SAAS,EACT,aAAa,EACb,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,YAAY,GAClB,MAAM,WAAW,CAAC;AAGnB,OAAO,EACL,iBAAiB,EACjB,UAAU,EACV,iBAAiB,EACjB,aAAa,EACb,YAAY,EACZ,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,EAClB,2BAA2B,GAC5B,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,KAAK,uBAAuB,EAAE,MAAM,sBAAsB,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Supernal Interface Tracking Module
|
|
3
|
+
*
|
|
4
|
+
* Analytics and interaction tracking for SI-enabled applications.
|
|
5
|
+
* Automatically batches events, handles offline scenarios, and provides
|
|
6
|
+
* React hooks for easy integration.
|
|
7
|
+
*
|
|
8
|
+
* @packageDocumentation
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* // Create a tracker
|
|
13
|
+
* import { createTracker, TrackingProvider, useTrackClick } from '@supernal/interface/tracking';
|
|
14
|
+
*
|
|
15
|
+
* const tracker = createTracker({
|
|
16
|
+
* endpoint: '/api/v1/analytics',
|
|
17
|
+
* batchSize: 10,
|
|
18
|
+
* debug: process.env.NODE_ENV === 'development',
|
|
19
|
+
* });
|
|
20
|
+
*
|
|
21
|
+
* // Provide to React tree
|
|
22
|
+
* function App() {
|
|
23
|
+
* const { user } = useAuth();
|
|
24
|
+
* return (
|
|
25
|
+
* <TrackingProvider tracker={tracker} userId={user?.id}>
|
|
26
|
+
* <YourApp />
|
|
27
|
+
* </TrackingProvider>
|
|
28
|
+
* );
|
|
29
|
+
* }
|
|
30
|
+
*
|
|
31
|
+
* // Use in components
|
|
32
|
+
* function PostCard({ post }) {
|
|
33
|
+
* const tracker = useTracker();
|
|
34
|
+
* const trackClick = useTrackClick(tracker, 'PostCard');
|
|
35
|
+
* const visibilityRef = useTrackVisibility(tracker, 'PostCard', post.id);
|
|
36
|
+
*
|
|
37
|
+
* return (
|
|
38
|
+
* <div ref={visibilityRef}>
|
|
39
|
+
* <button onClick={() => trackClick('like', post.id)}>Like</button>
|
|
40
|
+
* </div>
|
|
41
|
+
* );
|
|
42
|
+
* }
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
// Core tracker
|
|
46
|
+
export { SITracker, createTracker, } from './tracker.js';
|
|
47
|
+
// React hooks
|
|
48
|
+
export { SITrackerProvider, useTracker, useSITrackingInit, useTrackClick, useTrackView, useTrackEngagement, useTrackScrollDepth, useTrackVisibility, createComponentTrackingHook, } from './hooks.js';
|
|
49
|
+
// React provider component
|
|
50
|
+
export { TrackingProvider, withTracking } from './SITrackingProvider.js';
|
|
51
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/tracking/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAEH,eAAe;AACf,OAAO,EACL,SAAS,EACT,aAAa,GAId,MAAM,WAAW,CAAC;AAEnB,cAAc;AACd,OAAO,EACL,iBAAiB,EACjB,UAAU,EACV,iBAAiB,EACjB,aAAa,EACb,YAAY,EACZ,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,EAClB,2BAA2B,GAC5B,MAAM,SAAS,CAAC;AAEjB,2BAA2B;AAC3B,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAgC,MAAM,sBAAsB,CAAC"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Supernal Interface Interaction Tracking
|
|
3
|
+
*
|
|
4
|
+
* Tracks user interactions with SI components for analytics and AI analysis.
|
|
5
|
+
* Batches events to minimize network requests and handles offline gracefully.
|
|
6
|
+
*
|
|
7
|
+
* @packageDocumentation
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Base action types for tracking
|
|
11
|
+
* Apps can extend these with custom actions via generics
|
|
12
|
+
*/
|
|
13
|
+
export type SIBaseAction = 'view' | 'click' | 'expand' | 'collapse' | 'copy' | 'share' | 'like' | 'unlike' | 'bookmark' | 'unbookmark' | 'submit' | 'helpful' | 'challenge' | 'navigate' | 'scroll' | 'refresh' | 'search';
|
|
14
|
+
/**
|
|
15
|
+
* Interaction event structure
|
|
16
|
+
*/
|
|
17
|
+
export interface SIInteraction<TAction extends string = SIBaseAction> {
|
|
18
|
+
/** Component that triggered the event */
|
|
19
|
+
componentId: string;
|
|
20
|
+
/** Action performed */
|
|
21
|
+
action: TAction;
|
|
22
|
+
/** Target entity ID (post, user, etc.) */
|
|
23
|
+
targetId?: string;
|
|
24
|
+
/** Additional event metadata */
|
|
25
|
+
metadata?: Record<string, unknown>;
|
|
26
|
+
/** Client-side timestamp */
|
|
27
|
+
timestamp: number;
|
|
28
|
+
/** Session identifier */
|
|
29
|
+
sessionId: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Tracker configuration options
|
|
33
|
+
*/
|
|
34
|
+
export interface SITrackerConfig {
|
|
35
|
+
/** API endpoint for logging events (default: '/api/v1/analytics') */
|
|
36
|
+
endpoint?: string;
|
|
37
|
+
/** Maximum events before auto-flush (default: 10) */
|
|
38
|
+
batchSize?: number;
|
|
39
|
+
/** Milliseconds between auto-flushes (default: 5000) */
|
|
40
|
+
flushIntervalMs?: number;
|
|
41
|
+
/** Minimum engagement time to track (default: 3000) */
|
|
42
|
+
minEngagementMs?: number;
|
|
43
|
+
/** Scroll depth debounce (default: 500) */
|
|
44
|
+
scrollDebounceMs?: number;
|
|
45
|
+
/** Enable debug logging (default: false) */
|
|
46
|
+
debug?: boolean;
|
|
47
|
+
/** Custom fetch implementation for testing */
|
|
48
|
+
customFetch?: typeof fetch;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* SI Tracker - Core tracking class
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```typescript
|
|
55
|
+
* const tracker = new SITracker({ endpoint: '/api/analytics' });
|
|
56
|
+
* tracker.track('PostCard', 'view', 'post-123');
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
export declare class SITracker<TAction extends string = SIBaseAction> {
|
|
60
|
+
private queue;
|
|
61
|
+
private sessionId;
|
|
62
|
+
private flushInterval;
|
|
63
|
+
private engagementSessions;
|
|
64
|
+
private scrollState;
|
|
65
|
+
private isClient;
|
|
66
|
+
private userId;
|
|
67
|
+
private config;
|
|
68
|
+
constructor(config?: SITrackerConfig);
|
|
69
|
+
/** Generate a unique session ID */
|
|
70
|
+
private generateSessionId;
|
|
71
|
+
/** Log debug message */
|
|
72
|
+
private log;
|
|
73
|
+
/** Set the current user ID for tracking */
|
|
74
|
+
setUserId(userId: string | null): void;
|
|
75
|
+
/** Get current session ID */
|
|
76
|
+
getSessionId(): string;
|
|
77
|
+
/** Get queue length (for testing) */
|
|
78
|
+
getQueueLength(): number;
|
|
79
|
+
/**
|
|
80
|
+
* Track an interaction
|
|
81
|
+
*/
|
|
82
|
+
track(componentId: string, action: TAction, targetId?: string, metadata?: Record<string, unknown>): void;
|
|
83
|
+
/** Alias for track - for click events */
|
|
84
|
+
trackClick(componentId: string, action: TAction, targetId?: string, metadata?: Record<string, unknown>): void;
|
|
85
|
+
/** Track view (impression) of a component */
|
|
86
|
+
trackView(componentId: string, targetId?: string): void;
|
|
87
|
+
/** Start engagement tracking for a target */
|
|
88
|
+
startEngagement(targetId: string): void;
|
|
89
|
+
/** Record an interaction during engagement */
|
|
90
|
+
recordEngagementInteraction(targetId: string): void;
|
|
91
|
+
/** Update scroll depth for engagement session */
|
|
92
|
+
updateEngagementScrollDepth(targetId: string, depth: number): void;
|
|
93
|
+
/** End engagement tracking and log the session */
|
|
94
|
+
endEngagement(targetId: string, componentId?: string): void;
|
|
95
|
+
/** Track scroll depth in feed */
|
|
96
|
+
trackScrollDepth(depth: number, componentId?: string): void;
|
|
97
|
+
/** Reset scroll tracking (e.g., on page navigation) */
|
|
98
|
+
resetScrollTracking(): void;
|
|
99
|
+
/** Start periodic flush interval */
|
|
100
|
+
private startFlushInterval;
|
|
101
|
+
/** Stop flush interval */
|
|
102
|
+
private stopFlushInterval;
|
|
103
|
+
/** Setup beforeunload handler to flush remaining events */
|
|
104
|
+
private setupBeforeUnload;
|
|
105
|
+
/** Flush queued events to the API */
|
|
106
|
+
flush(): Promise<void>;
|
|
107
|
+
/** Flush using sendBeacon (for unload events) */
|
|
108
|
+
private flushWithBeacon;
|
|
109
|
+
/** Cleanup (for testing or unmounting) */
|
|
110
|
+
destroy(): void;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Create a singleton tracker instance
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* ```typescript
|
|
117
|
+
* export const tracker = createTracker({ endpoint: '/api/analytics' });
|
|
118
|
+
* ```
|
|
119
|
+
*/
|
|
120
|
+
export declare function createTracker<TAction extends string = SIBaseAction>(config?: SITrackerConfig): SITracker<TAction>;
|
|
121
|
+
//# sourceMappingURL=tracker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tracker.d.ts","sourceRoot":"","sources":["../../../../src/tracking/tracker.ts"],"names":[],"mappings":"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"}
|