guideai-app 0.3.1 → 0.3.4
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 +138 -246
- package/dist/GuideAI.js +1 -1
- package/dist/GuideAI.js.map +1 -1
- package/dist/components/TranscriptBox.d.ts +1 -1
- package/dist/metric/event-listner.d.ts +19 -0
- package/dist/metric/metadata-tracker.d.ts +12 -1
- package/dist/utils/logger.d.ts +41 -0
- package/dist/utils/workflow.d.ts +62 -0
- package/metadata-tracking-example.md +324 -0
- package/obfuscate.js +40 -0
- package/obfuscator.prod.json +24 -0
- package/package.json +1 -1
- package/structure.md +128 -0
- package/text-input-usage.md +321 -0
- package/transcript-toggle-usage.md +267 -0
- package/visit-tracking-usage.md +134 -0
- package/components/Styles.d.ts +0 -3
- package/types/index.d.ts +0 -24
|
@@ -13,5 +13,5 @@ interface TranscriptBoxProps {
|
|
|
13
13
|
onTextKeyPress?: (event: React.KeyboardEvent) => void;
|
|
14
14
|
textPlaceholder?: string;
|
|
15
15
|
}
|
|
16
|
-
declare const TranscriptBox: React.
|
|
16
|
+
declare const TranscriptBox: React.NamedExoticComponent<TranscriptBoxProps>;
|
|
17
17
|
export default TranscriptBox;
|
|
@@ -33,18 +33,31 @@ declare class EventTracker {
|
|
|
33
33
|
private pendingEvents;
|
|
34
34
|
private currentUrl;
|
|
35
35
|
private organizationKey?;
|
|
36
|
+
private lastEventTime;
|
|
37
|
+
private eventThrottleInterval;
|
|
38
|
+
private lastEventsByType;
|
|
39
|
+
private duplicateEventBuffer;
|
|
40
|
+
private maxDuplicateBuffer;
|
|
41
|
+
private isInitialized;
|
|
36
42
|
private customerMetadata;
|
|
37
43
|
constructor(options?: {
|
|
38
44
|
customerId?: string;
|
|
39
45
|
customerType?: string;
|
|
40
46
|
organizationId?: string;
|
|
41
47
|
organizationKey?: string;
|
|
48
|
+
batchSize?: number;
|
|
49
|
+
batchTimeout?: number;
|
|
50
|
+
eventThrottleInterval?: number;
|
|
42
51
|
});
|
|
52
|
+
private init;
|
|
53
|
+
private loadEventsFromStorage;
|
|
54
|
+
private saveEventsToStorage;
|
|
43
55
|
setCustomerMetadata(metadata: Partial<typeof this.customerMetadata>): void;
|
|
44
56
|
getCustomerMetadata(): typeof this.customerMetadata;
|
|
45
57
|
clearCustomerMetadata(): void;
|
|
46
58
|
initialize(): void;
|
|
47
59
|
private enrichEventData;
|
|
60
|
+
private sanitizeEventData;
|
|
48
61
|
private getSessionId;
|
|
49
62
|
private getDeviceType;
|
|
50
63
|
startTracking(): void;
|
|
@@ -65,6 +78,12 @@ declare class EventTracker {
|
|
|
65
78
|
private getSafeValue;
|
|
66
79
|
private isFocusable;
|
|
67
80
|
private isFormElement;
|
|
81
|
+
private generateEventKey;
|
|
82
|
+
private shouldThrottleEvent;
|
|
83
|
+
private isDuplicateEvent;
|
|
84
|
+
private isSignificantClickTarget;
|
|
85
|
+
private isSignificantFocusTarget;
|
|
86
|
+
private isSignificantRouteChange;
|
|
68
87
|
private logEvent;
|
|
69
88
|
private startBatchTimer;
|
|
70
89
|
private emitBatch;
|
|
@@ -6,11 +6,18 @@ declare class UserMetadataTracker {
|
|
|
6
6
|
private pendingUpdates;
|
|
7
7
|
private isInitialized;
|
|
8
8
|
private onError?;
|
|
9
|
+
private lastSyncTime;
|
|
10
|
+
private minSyncInterval;
|
|
11
|
+
private lastMetadataHash;
|
|
12
|
+
private pendingUpdateTypes;
|
|
9
13
|
constructor(organizationKey: string, config?: MetadataConfig, onError?: (error: Error, context: string) => void);
|
|
10
|
-
|
|
14
|
+
init(): void;
|
|
11
15
|
updateUserInfo(userInfo: Partial<UserMetadata>): void;
|
|
12
16
|
trackLogin(additionalInfo?: Partial<UserMetadata>): void;
|
|
17
|
+
private trackVisitOncePerSession;
|
|
13
18
|
trackVisit(): void;
|
|
19
|
+
resetSessionVisitTracking(): void;
|
|
20
|
+
trackVisitManually(): void;
|
|
14
21
|
trackCustomEvent(eventType: string, customData: Record<string, any>): void;
|
|
15
22
|
getMetadata(): UserMetadata;
|
|
16
23
|
getPendingUpdates(): MetadataUpdate[];
|
|
@@ -21,6 +28,10 @@ declare class UserMetadataTracker {
|
|
|
21
28
|
private collectBrowserInfo;
|
|
22
29
|
private parseBrowserInfo;
|
|
23
30
|
private startSyncTimer;
|
|
31
|
+
private shouldSync;
|
|
32
|
+
private addPendingUpdate;
|
|
33
|
+
private isDataDuplicate;
|
|
34
|
+
private generateDataHash;
|
|
24
35
|
private setupEventTrackerIntegration;
|
|
25
36
|
private stopSyncTimer;
|
|
26
37
|
private emitPendingUpdates;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Standardized logging utility for GuideAI package
|
|
3
|
+
* Provides consistent formatting and development gating across all components
|
|
4
|
+
*/
|
|
5
|
+
type Component = 'GuideAI' | 'EventTracker' | 'UserMetadata' | 'API' | 'TranscriptBox' | 'Onboarding';
|
|
6
|
+
declare class Logger {
|
|
7
|
+
private static formatMessage;
|
|
8
|
+
/**
|
|
9
|
+
* Standard info logging - only in development
|
|
10
|
+
*/
|
|
11
|
+
static log(component: Component, action: string, data?: any): void;
|
|
12
|
+
/**
|
|
13
|
+
* Warning logging - always shown
|
|
14
|
+
*/
|
|
15
|
+
static warn(component: Component, action: string, data?: any): void;
|
|
16
|
+
/**
|
|
17
|
+
* Error logging - always shown
|
|
18
|
+
*/
|
|
19
|
+
static error(component: Component, action: string, error?: any): void;
|
|
20
|
+
/**
|
|
21
|
+
* API call logging with method and endpoint
|
|
22
|
+
*/
|
|
23
|
+
static apiCall(method: string, endpoint: string, data?: any): void;
|
|
24
|
+
/**
|
|
25
|
+
* API response logging
|
|
26
|
+
*/
|
|
27
|
+
static apiResponse(method: string, endpoint: string, success: boolean, data?: any): void;
|
|
28
|
+
/**
|
|
29
|
+
* Conversation flow tracking
|
|
30
|
+
*/
|
|
31
|
+
static conversation(action: string, data?: any): void;
|
|
32
|
+
/**
|
|
33
|
+
* Event tracking logging
|
|
34
|
+
*/
|
|
35
|
+
static event(action: string, data?: any): void;
|
|
36
|
+
/**
|
|
37
|
+
* Metadata tracking logging
|
|
38
|
+
*/
|
|
39
|
+
static metadata(action: string, data?: any): void;
|
|
40
|
+
}
|
|
41
|
+
export default Logger;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { Workflow } from './api';
|
|
2
|
+
export interface WorkflowTrigger {
|
|
3
|
+
triggerWords: string[];
|
|
4
|
+
workflowKey: string;
|
|
5
|
+
description?: string;
|
|
6
|
+
}
|
|
7
|
+
export interface WorkflowLogEvent {
|
|
8
|
+
type: 'workflow_init' | 'trigger_detected' | 'workflow_activated';
|
|
9
|
+
timestamp: string;
|
|
10
|
+
data: any;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Format a workflow log message for console output
|
|
14
|
+
*/
|
|
15
|
+
export declare const formatWorkflowLog: (event: WorkflowLogEvent) => string;
|
|
16
|
+
/**
|
|
17
|
+
* Log workflow event to console with formatting
|
|
18
|
+
*/
|
|
19
|
+
export declare const logWorkflowEvent: (event: WorkflowLogEvent) => void;
|
|
20
|
+
/**
|
|
21
|
+
* Detect which workflows should be triggered based on a user message
|
|
22
|
+
* @param message The user's message
|
|
23
|
+
* @param workflows Array of available workflows
|
|
24
|
+
* @returns Array of workflows that should be triggered
|
|
25
|
+
*/
|
|
26
|
+
export declare const detectWorkflowTriggers: (message: string, workflows: Workflow[]) => Workflow[];
|
|
27
|
+
/**
|
|
28
|
+
* Get trigger words from a message that match a specific workflow
|
|
29
|
+
* @param message The user's message
|
|
30
|
+
* @param workflow The workflow to check against
|
|
31
|
+
* @returns Array of detected trigger words for this workflow
|
|
32
|
+
*/
|
|
33
|
+
export declare const getWorkflowTriggerWords: (message: string, workflow: Workflow) => string[];
|
|
34
|
+
/**
|
|
35
|
+
* Check if a message contains any trigger words for any workflow
|
|
36
|
+
* @param message The user's message
|
|
37
|
+
* @param workflows Array of available workflows
|
|
38
|
+
* @returns True if any workflow triggers are found
|
|
39
|
+
*/
|
|
40
|
+
export declare const hasWorkflowTriggers: (message: string, workflows: Workflow[]) => boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Get the most relevant workflow for a message
|
|
43
|
+
* @param message The user's message
|
|
44
|
+
* @param workflows Array of available workflows
|
|
45
|
+
* @returns The most relevant workflow or null if none found
|
|
46
|
+
*/
|
|
47
|
+
export declare const getMostRelevantWorkflow: (message: string, workflows: Workflow[]) => Workflow | null;
|
|
48
|
+
/**
|
|
49
|
+
* Legacy function for backward compatibility
|
|
50
|
+
* @deprecated Use detectWorkflowTriggers instead
|
|
51
|
+
*/
|
|
52
|
+
export declare const detectTriggerWords: (message: string, triggerWords: string[]) => string[];
|
|
53
|
+
/**
|
|
54
|
+
* Legacy function for backward compatibility
|
|
55
|
+
* @deprecated Use hasWorkflowTriggers instead
|
|
56
|
+
*/
|
|
57
|
+
export declare const hasTriggerWords: (message: string, triggerWords: string[]) => boolean;
|
|
58
|
+
/**
|
|
59
|
+
* Legacy function for backward compatibility
|
|
60
|
+
* @deprecated Use getMostRelevantWorkflow instead
|
|
61
|
+
*/
|
|
62
|
+
export declare const getMostRelevantTrigger: (message: string, triggerWords: string[]) => string | null;
|
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
# User Metadata Tracking - Implementation Guide
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
The GuideAI package now includes comprehensive user metadata tracking capabilities designed for integration with Overproof. This system tracks the following metadata:
|
|
6
|
+
|
|
7
|
+
- **User's First Visit** - Timestamp of the first time the user interacted with GuideAI
|
|
8
|
+
- **User's Last Visit** - Timestamp of the most recent user interaction
|
|
9
|
+
- **User Logins** - Count and timestamp of login events
|
|
10
|
+
- **User Type** - Classification of the user (agent, admin, manager, customer, guest, etc.)
|
|
11
|
+
- **Customer Type** - Type of customer (individual, business, enterprise, etc.)
|
|
12
|
+
- **Customer License** - License identifier for the customer
|
|
13
|
+
|
|
14
|
+
## Basic Usage
|
|
15
|
+
|
|
16
|
+
### 1. Basic Integration
|
|
17
|
+
|
|
18
|
+
```typescript
|
|
19
|
+
import { GuideAI } from 'guide-ai-package';
|
|
20
|
+
|
|
21
|
+
function App() {
|
|
22
|
+
return (
|
|
23
|
+
<GuideAI
|
|
24
|
+
organizationKey="your-org-key"
|
|
25
|
+
metadata={{
|
|
26
|
+
config: {
|
|
27
|
+
trackVisits: true,
|
|
28
|
+
trackLogins: true,
|
|
29
|
+
syncInterval: 30000, // Sync every 30 seconds
|
|
30
|
+
storage: 'localStorage'
|
|
31
|
+
},
|
|
32
|
+
initialUserData: {
|
|
33
|
+
userType: 'agent',
|
|
34
|
+
customerType: 'business',
|
|
35
|
+
customerLicense: 'OVERPRF-12345'
|
|
36
|
+
},
|
|
37
|
+
onMetadataUpdate: (metadata) => {
|
|
38
|
+
console.log('Metadata updated:', metadata);
|
|
39
|
+
// Send to your analytics system
|
|
40
|
+
}
|
|
41
|
+
}}
|
|
42
|
+
/>
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### 2. Tracking User Login Events
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
import { useRef } from 'react';
|
|
51
|
+
|
|
52
|
+
function LoginComponent() {
|
|
53
|
+
const guideAIRef = useRef();
|
|
54
|
+
|
|
55
|
+
const handleLogin = async (userInfo) => {
|
|
56
|
+
// Your login logic here
|
|
57
|
+
const loginResult = await performLogin(userInfo);
|
|
58
|
+
|
|
59
|
+
if (loginResult.success) {
|
|
60
|
+
// Track the login with GuideAI
|
|
61
|
+
guideAIRef.current?.trackLogin({
|
|
62
|
+
userId: loginResult.userId,
|
|
63
|
+
userType: loginResult.userType,
|
|
64
|
+
customerType: loginResult.customerType,
|
|
65
|
+
customerLicense: loginResult.license
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
return (
|
|
71
|
+
<div>
|
|
72
|
+
<GuideAI
|
|
73
|
+
ref={guideAIRef}
|
|
74
|
+
organizationKey="your-org-key"
|
|
75
|
+
metadata={{
|
|
76
|
+
config: { trackLogins: true }
|
|
77
|
+
}}
|
|
78
|
+
/>
|
|
79
|
+
<button onClick={handleLogin}>Login</button>
|
|
80
|
+
</div>
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### 3. Updating User Information
|
|
86
|
+
|
|
87
|
+
```typescript
|
|
88
|
+
function UserProfileComponent() {
|
|
89
|
+
const guideAIRef = useRef();
|
|
90
|
+
|
|
91
|
+
const updateUserProfile = (newUserData) => {
|
|
92
|
+
// Update user profile in your system
|
|
93
|
+
saveUserProfile(newUserData);
|
|
94
|
+
|
|
95
|
+
// Update GuideAI metadata
|
|
96
|
+
guideAIRef.current?.updateUserInfo({
|
|
97
|
+
userType: newUserData.role,
|
|
98
|
+
customerType: newUserData.accountType,
|
|
99
|
+
customerLicense: newUserData.license,
|
|
100
|
+
customFields: {
|
|
101
|
+
department: newUserData.department,
|
|
102
|
+
region: newUserData.region
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
return (
|
|
108
|
+
<GuideAI
|
|
109
|
+
ref={guideAIRef}
|
|
110
|
+
organizationKey="your-org-key"
|
|
111
|
+
metadata={{
|
|
112
|
+
config: {
|
|
113
|
+
customFields: ['department', 'region'],
|
|
114
|
+
collectBrowserInfo: true
|
|
115
|
+
}
|
|
116
|
+
}}
|
|
117
|
+
/>
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## Configuration Options
|
|
123
|
+
|
|
124
|
+
### MetadataConfig
|
|
125
|
+
|
|
126
|
+
```typescript
|
|
127
|
+
interface MetadataConfig {
|
|
128
|
+
// Whether to automatically track visits (default: true)
|
|
129
|
+
trackVisits?: boolean;
|
|
130
|
+
|
|
131
|
+
// Whether to automatically track logins (default: true)
|
|
132
|
+
trackLogins?: boolean;
|
|
133
|
+
|
|
134
|
+
// How often to sync metadata to backend in milliseconds (default: 30000)
|
|
135
|
+
syncInterval?: number;
|
|
136
|
+
|
|
137
|
+
// Storage strategy (default: 'localStorage')
|
|
138
|
+
storage?: 'localStorage' | 'sessionStorage' | 'memory';
|
|
139
|
+
|
|
140
|
+
// Custom metadata fields to collect
|
|
141
|
+
customFields?: string[];
|
|
142
|
+
|
|
143
|
+
// Whether to collect browser information (default: true)
|
|
144
|
+
collectBrowserInfo?: boolean;
|
|
145
|
+
|
|
146
|
+
// Whether to collect user agent (default: true)
|
|
147
|
+
collectUserAgent?: boolean;
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### UserMetadata Structure
|
|
152
|
+
|
|
153
|
+
```typescript
|
|
154
|
+
interface UserMetadata {
|
|
155
|
+
// Core identification
|
|
156
|
+
userId?: string;
|
|
157
|
+
userType?: 'agent' | 'admin' | 'manager' | 'customer' | 'guest' | string;
|
|
158
|
+
|
|
159
|
+
// Customer-specific metadata
|
|
160
|
+
customerType?: 'individual' | 'business' | 'enterprise' | string;
|
|
161
|
+
customerLicense?: string;
|
|
162
|
+
|
|
163
|
+
// Visit tracking (automatically managed)
|
|
164
|
+
firstVisit?: number; // timestamp
|
|
165
|
+
lastVisit?: number; // timestamp
|
|
166
|
+
visitCount?: number;
|
|
167
|
+
|
|
168
|
+
// Login tracking (requires manual tracking)
|
|
169
|
+
loginCount?: number;
|
|
170
|
+
lastLogin?: number; // timestamp
|
|
171
|
+
|
|
172
|
+
// Session metadata (automatically managed)
|
|
173
|
+
organizationKey: string;
|
|
174
|
+
sessionId?: string;
|
|
175
|
+
|
|
176
|
+
// Browser information (automatically collected if enabled)
|
|
177
|
+
userAgent?: string;
|
|
178
|
+
browserInfo?: {
|
|
179
|
+
name?: string;
|
|
180
|
+
version?: string;
|
|
181
|
+
platform?: string;
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
// Custom fields for Overproof-specific needs
|
|
185
|
+
customFields?: Record<string, string | number | boolean>;
|
|
186
|
+
}
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## API Integration
|
|
190
|
+
|
|
191
|
+
The system automatically sends metadata updates to these endpoints:
|
|
192
|
+
|
|
193
|
+
### POST `/user-metadata`
|
|
194
|
+
Sends complete user metadata object when initially collected.
|
|
195
|
+
|
|
196
|
+
### POST `/metadata-updates`
|
|
197
|
+
Sends batched metadata updates periodically.
|
|
198
|
+
|
|
199
|
+
### PATCH `/users/{userId}/metadata`
|
|
200
|
+
Updates specific user metadata when userId is available.
|
|
201
|
+
|
|
202
|
+
## Backend Implementation
|
|
203
|
+
|
|
204
|
+
You'll need to implement these endpoints in your backend:
|
|
205
|
+
|
|
206
|
+
```typescript
|
|
207
|
+
// Example Express.js implementation
|
|
208
|
+
app.post('/api/user-metadata', (req, res) => {
|
|
209
|
+
const { organizationKey, metadata, timestamp } = req.body;
|
|
210
|
+
|
|
211
|
+
// Store metadata in your database
|
|
212
|
+
await UserMetadata.upsert({
|
|
213
|
+
organizationKey,
|
|
214
|
+
userId: metadata.userId || 'anonymous',
|
|
215
|
+
...metadata,
|
|
216
|
+
lastUpdated: new Date(timestamp)
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
res.json({ success: true });
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
app.post('/api/metadata-updates', (req, res) => {
|
|
223
|
+
const { organizationKey, updates, batchTimestamp } = req.body;
|
|
224
|
+
|
|
225
|
+
// Process batch updates
|
|
226
|
+
for (const update of updates) {
|
|
227
|
+
await processMetadataUpdate(organizationKey, update);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
res.json({ success: true });
|
|
231
|
+
});
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
## Privacy Considerations
|
|
235
|
+
|
|
236
|
+
- **User Agent Collection**: Can be disabled via `collectUserAgent: false`
|
|
237
|
+
- **Browser Info Collection**: Can be disabled via `collectBrowserInfo: false`
|
|
238
|
+
- **Custom Fields**: Only fields specified in `customFields` array are collected
|
|
239
|
+
- **Storage**: Can be set to `'memory'` for session-only storage without persistence
|
|
240
|
+
|
|
241
|
+
## Testing
|
|
242
|
+
|
|
243
|
+
```typescript
|
|
244
|
+
// Get current metadata
|
|
245
|
+
const metadata = guideAIRef.current?.getMetadata();
|
|
246
|
+
console.log('Current metadata:', metadata);
|
|
247
|
+
|
|
248
|
+
// Force sync metadata now
|
|
249
|
+
await guideAIRef.current?.syncMetadata();
|
|
250
|
+
|
|
251
|
+
// Track custom events
|
|
252
|
+
guideAIRef.current?.trackCustomEvent('document_viewed', {
|
|
253
|
+
documentType: 'policy',
|
|
254
|
+
documentId: 'POL-12345'
|
|
255
|
+
});
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
## Overproof Integration Example
|
|
259
|
+
|
|
260
|
+
```typescript
|
|
261
|
+
function OverproofApp() {
|
|
262
|
+
const guideAIRef = useRef();
|
|
263
|
+
|
|
264
|
+
// Track when user logs into Overproof
|
|
265
|
+
const handleOverproofLogin = (user) => {
|
|
266
|
+
guideAIRef.current?.trackLogin({
|
|
267
|
+
userId: user.id,
|
|
268
|
+
userType: user.role, // 'agent', 'admin', etc.
|
|
269
|
+
customerType: user.accountType,
|
|
270
|
+
customerLicense: user.licenseNumber,
|
|
271
|
+
customFields: {
|
|
272
|
+
agencyId: user.agencyId,
|
|
273
|
+
territory: user.territory,
|
|
274
|
+
permissions: user.permissions.join(',')
|
|
275
|
+
}
|
|
276
|
+
});
|
|
277
|
+
};
|
|
278
|
+
|
|
279
|
+
// Track when user profile is updated
|
|
280
|
+
const handleProfileUpdate = (updatedProfile) => {
|
|
281
|
+
guideAIRef.current?.updateUserInfo({
|
|
282
|
+
userType: updatedProfile.role,
|
|
283
|
+
customerLicense: updatedProfile.licenseNumber,
|
|
284
|
+
customFields: {
|
|
285
|
+
agencyId: updatedProfile.agencyId,
|
|
286
|
+
territory: updatedProfile.territory
|
|
287
|
+
}
|
|
288
|
+
});
|
|
289
|
+
};
|
|
290
|
+
|
|
291
|
+
return (
|
|
292
|
+
<GuideAI
|
|
293
|
+
ref={guideAIRef}
|
|
294
|
+
organizationKey="overproof-org-key"
|
|
295
|
+
metadata={{
|
|
296
|
+
config: {
|
|
297
|
+
trackVisits: true,
|
|
298
|
+
trackLogins: true,
|
|
299
|
+
syncInterval: 15000, // More frequent syncing for Overproof
|
|
300
|
+
customFields: ['agencyId', 'territory', 'permissions'],
|
|
301
|
+
collectBrowserInfo: true
|
|
302
|
+
},
|
|
303
|
+
onMetadataUpdate: (metadata) => {
|
|
304
|
+
// Send to Overproof analytics
|
|
305
|
+
window.OverproofAnalytics?.track('guideai_metadata_update', metadata);
|
|
306
|
+
}
|
|
307
|
+
}}
|
|
308
|
+
/>
|
|
309
|
+
);
|
|
310
|
+
}
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
## Storage and Data Persistence
|
|
314
|
+
|
|
315
|
+
- **localStorage**: Persists across browser sessions (default)
|
|
316
|
+
- **sessionStorage**: Persists only for current session
|
|
317
|
+
- **memory**: No persistence, data lost on page refresh
|
|
318
|
+
|
|
319
|
+
Metadata is automatically:
|
|
320
|
+
- Saved locally based on storage configuration
|
|
321
|
+
- Synced to backend at configured intervals
|
|
322
|
+
- Restored when user returns (if using persistent storage)
|
|
323
|
+
|
|
324
|
+
This implementation provides a robust foundation for tracking user metadata in the Overproof environment while maintaining flexibility for other use cases.
|
package/obfuscate.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const JavaScriptObfuscator = require('javascript-obfuscator');
|
|
4
|
+
|
|
5
|
+
// Files to obfuscate
|
|
6
|
+
const files = [
|
|
7
|
+
'dist/index.js',
|
|
8
|
+
'dist/index.esm.js'
|
|
9
|
+
];
|
|
10
|
+
|
|
11
|
+
// Load obfuscator config
|
|
12
|
+
const config = JSON.parse(fs.readFileSync(path.resolve(__dirname, 'obfuscator.json'), 'utf8'));
|
|
13
|
+
|
|
14
|
+
// Process each file
|
|
15
|
+
|
|
16
|
+
files.forEach(file => {
|
|
17
|
+
const filePath = path.resolve(__dirname, file);
|
|
18
|
+
|
|
19
|
+
try {
|
|
20
|
+
// Check if file exists
|
|
21
|
+
if (!fs.existsSync(filePath)) {
|
|
22
|
+
console.warn(`Warning: ${file} does not exist, skipping obfuscation.`);
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
// Read the file
|
|
28
|
+
const code = fs.readFileSync(filePath, 'utf8');
|
|
29
|
+
|
|
30
|
+
// Obfuscate the code
|
|
31
|
+
const obfuscationResult = JavaScriptObfuscator.obfuscate(code, config);
|
|
32
|
+
|
|
33
|
+
// Write the obfuscated code back to the file
|
|
34
|
+
fs.writeFileSync(filePath, obfuscationResult.getObfuscatedCode());
|
|
35
|
+
|
|
36
|
+
} catch (error) {
|
|
37
|
+
console.error(`Error obfuscating ${file}:`, error);
|
|
38
|
+
process.exit(1);
|
|
39
|
+
}
|
|
40
|
+
});
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compact": true,
|
|
3
|
+
"controlFlowFlattening": false,
|
|
4
|
+
"controlFlowFlatteningThreshold": 0.75,
|
|
5
|
+
"deadCodeInjection": false,
|
|
6
|
+
"deadCodeInjectionThreshold": 0.4,
|
|
7
|
+
"debugProtection": false,
|
|
8
|
+
"debugProtectionInterval": 0,
|
|
9
|
+
"disableConsoleOutput": true,
|
|
10
|
+
"identifierNamesGenerator": "hexadecimal",
|
|
11
|
+
"log": false,
|
|
12
|
+
"numbersToExpressions": false,
|
|
13
|
+
"renameGlobals": false,
|
|
14
|
+
"rotateStringArray": false,
|
|
15
|
+
"selfDefending": false,
|
|
16
|
+
"shuffleStringArray": false,
|
|
17
|
+
"splitStrings": false,
|
|
18
|
+
"splitStringsChunkLength": 10,
|
|
19
|
+
"stringArray": false,
|
|
20
|
+
"stringArrayEncoding": [],
|
|
21
|
+
"stringArrayThreshold": 0,
|
|
22
|
+
"transformObjectKeys": false,
|
|
23
|
+
"unicodeEscapeSequence": false
|
|
24
|
+
}
|