humanbehavior-js 0.2.3 → 0.2.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/dist/cjs/index.js +25 -18
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/index.js +25 -18
- package/dist/esm/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 +4 -0
- package/package.json +1 -1
- package/simple-spa.html +184 -4
- package/src/api.ts +13 -6
- package/src/tracker.ts +19 -12
package/dist/types/index.d.ts
CHANGED
|
@@ -194,6 +194,10 @@ declare class HumanBehaviorTracker {
|
|
|
194
194
|
userId?: string;
|
|
195
195
|
userProperties: Record<string, any>;
|
|
196
196
|
}): Promise<string>;
|
|
197
|
+
/**
|
|
198
|
+
* Get current user attributes
|
|
199
|
+
*/
|
|
200
|
+
getUserAttributes(): Record<string, any>;
|
|
197
201
|
start(): Promise<void>;
|
|
198
202
|
stop(): Promise<void>;
|
|
199
203
|
addEvent(event: any): Promise<void>;
|
package/package.json
CHANGED
package/simple-spa.html
CHANGED
|
@@ -228,6 +228,57 @@
|
|
|
228
228
|
<button class="button secondary" onclick="trackCustomEvent('demo_button_2', {button: 'demo2'})">Demo Button 2</button>
|
|
229
229
|
<button class="button success" onclick="trackCustomEvent('demo_button_3', {button: 'demo3'})">Demo Button 3</button>
|
|
230
230
|
|
|
231
|
+
<h3>User Authentication Test</h3>
|
|
232
|
+
<button class="button" onclick="testUserAuthentication()">
|
|
233
|
+
Test User Authentication
|
|
234
|
+
</button>
|
|
235
|
+
<p style="font-size: 12px; color: #666; margin-top: 5px;">
|
|
236
|
+
Tests the new behavior where endUserId stays the same but posthogName gets updated with email
|
|
237
|
+
</p>
|
|
238
|
+
|
|
239
|
+
<h3>Real User Authentication</h3>
|
|
240
|
+
<form onsubmit="handleAuthSubmit(event)" style="background: rgba(255,255,255,0.1); padding: 20px; border-radius: 10px; margin: 15px 0;">
|
|
241
|
+
<div style="margin-bottom: 15px;">
|
|
242
|
+
<label for="authEmail" style="display: block; margin-bottom: 5px; font-weight: 600;">Email:</label>
|
|
243
|
+
<input type="email" id="authEmail" placeholder="your.email@example.com" required
|
|
244
|
+
style="width: 100%; padding: 10px; border-radius: 5px; border: none; background: rgba(255,255,255,0.9);">
|
|
245
|
+
</div>
|
|
246
|
+
|
|
247
|
+
<div style="margin-bottom: 15px;">
|
|
248
|
+
<label for="authName" style="display: block; margin-bottom: 5px; font-weight: 600;">Name:</label>
|
|
249
|
+
<input type="text" id="authName" placeholder="Your Name" required
|
|
250
|
+
style="width: 100%; padding: 10px; border-radius: 5px; border: none; background: rgba(255,255,255,0.9);">
|
|
251
|
+
</div>
|
|
252
|
+
|
|
253
|
+
<div style="margin-bottom: 15px;">
|
|
254
|
+
<label for="authPlan" style="display: block; margin-bottom: 5px; font-weight: 600;">Plan:</label>
|
|
255
|
+
<select id="authPlan" style="width: 100%; padding: 10px; border-radius: 5px; border: none; background: rgba(255,255,255,0.9);">
|
|
256
|
+
<option value="free">Free</option>
|
|
257
|
+
<option value="basic">Basic</option>
|
|
258
|
+
<option value="premium">Premium</option>
|
|
259
|
+
<option value="enterprise">Enterprise</option>
|
|
260
|
+
</select>
|
|
261
|
+
</div>
|
|
262
|
+
|
|
263
|
+
<div style="margin-bottom: 15px;">
|
|
264
|
+
<label for="authCompany" style="display: block; margin-bottom: 5px; font-weight: 600;">Company (Optional):</label>
|
|
265
|
+
<input type="text" id="authCompany" placeholder="Your Company"
|
|
266
|
+
style="width: 100%; padding: 10px; border-radius: 5px; border: none; background: rgba(255,255,255,0.9);">
|
|
267
|
+
</div>
|
|
268
|
+
|
|
269
|
+
<button type="submit" class="button success" style="width: 100%;">
|
|
270
|
+
🔐 Authenticate User
|
|
271
|
+
</button>
|
|
272
|
+
</form>
|
|
273
|
+
|
|
274
|
+
<div style="margin-top: 15px; display: flex; gap: 10px;">
|
|
275
|
+
<button class="button secondary" onclick="showAuthStatus()" style="flex: 1;">
|
|
276
|
+
📊 Show Auth Status
|
|
277
|
+
</button>
|
|
278
|
+
</div>
|
|
279
|
+
|
|
280
|
+
<div id="authResult" style="margin-top: 15px; padding: 10px; border-radius: 5px; display: none;"></div>
|
|
281
|
+
|
|
231
282
|
<div class="logs" id="demoLogs">
|
|
232
283
|
<div>Demo events will appear here...</div>
|
|
233
284
|
</div>
|
|
@@ -498,7 +549,45 @@
|
|
|
498
549
|
addLog('customEvent method not available');
|
|
499
550
|
}
|
|
500
551
|
} catch (error) {
|
|
501
|
-
|
|
552
|
+
console.error('Error tracking custom event:', error);
|
|
553
|
+
addLog('Error tracking custom event: ' + error.message);
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
// Test user authentication (new behavior)
|
|
558
|
+
async function testUserAuthentication() {
|
|
559
|
+
if (!tracker) {
|
|
560
|
+
addLog('Tracker not available');
|
|
561
|
+
return;
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
try {
|
|
565
|
+
const originalEndUserId = tracker.getSessionId();
|
|
566
|
+
addLog(`Original endUserId: ${originalEndUserId}`);
|
|
567
|
+
|
|
568
|
+
// Simulate user sign-in
|
|
569
|
+
const userId = await tracker.addUserInfo({
|
|
570
|
+
userId: 'user123@example.com',
|
|
571
|
+
userProperties: {
|
|
572
|
+
email: 'user123@example.com',
|
|
573
|
+
name: 'John Doe',
|
|
574
|
+
plan: 'premium',
|
|
575
|
+
signupDate: new Date().toISOString()
|
|
576
|
+
}
|
|
577
|
+
});
|
|
578
|
+
|
|
579
|
+
const newEndUserId = tracker.getSessionId();
|
|
580
|
+
addLog(`New endUserId: ${newEndUserId}`);
|
|
581
|
+
addLog(`endUserId changed: ${originalEndUserId !== newEndUserId ? 'YES (BAD)' : 'NO (GOOD)'}`);
|
|
582
|
+
addLog(`User authenticated: ${userId}`);
|
|
583
|
+
|
|
584
|
+
// The endUserId should stay the same, but posthogName will be updated with email
|
|
585
|
+
addLog('✅ endUserId maintained for session continuity');
|
|
586
|
+
addLog('✅ posthogName will be updated with email for UI display');
|
|
587
|
+
|
|
588
|
+
} catch (error) {
|
|
589
|
+
console.error('Error testing user authentication:', error);
|
|
590
|
+
addLog('Error testing user authentication: ' + error.message);
|
|
502
591
|
}
|
|
503
592
|
}
|
|
504
593
|
|
|
@@ -524,6 +613,60 @@
|
|
|
524
613
|
|
|
525
614
|
input.value = '';
|
|
526
615
|
}
|
|
616
|
+
|
|
617
|
+
// Handle authentication form submission
|
|
618
|
+
async function handleAuthSubmit(event) {
|
|
619
|
+
event.preventDefault();
|
|
620
|
+
const email = document.getElementById('authEmail').value;
|
|
621
|
+
const name = document.getElementById('authName').value;
|
|
622
|
+
const plan = document.getElementById('authPlan').value;
|
|
623
|
+
const company = document.getElementById('authCompany').value;
|
|
624
|
+
|
|
625
|
+
if (!email || !name) {
|
|
626
|
+
alert('Email and Name are required for authentication.');
|
|
627
|
+
return;
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
try {
|
|
631
|
+
const userId = await tracker.addUserInfo({
|
|
632
|
+
userId: email, // Use email as userId
|
|
633
|
+
userProperties: {
|
|
634
|
+
email: email,
|
|
635
|
+
name: name,
|
|
636
|
+
plan: plan,
|
|
637
|
+
company: company,
|
|
638
|
+
signupDate: new Date().toISOString()
|
|
639
|
+
}
|
|
640
|
+
});
|
|
641
|
+
|
|
642
|
+
const newEndUserId = tracker.getSessionId();
|
|
643
|
+
addLog(`New endUserId after authentication: ${newEndUserId}`);
|
|
644
|
+
addLog(`endUserId changed: ${tracker.getSessionId() !== newEndUserId ? 'YES (BAD)' : 'NO (GOOD)'}`);
|
|
645
|
+
addLog(`User authenticated: ${userId}`);
|
|
646
|
+
|
|
647
|
+
const authResultDiv = document.getElementById('authResult');
|
|
648
|
+
authResultDiv.style.display = 'block';
|
|
649
|
+
authResultDiv.innerHTML = `
|
|
650
|
+
<strong>Authentication Successful!</strong><br>
|
|
651
|
+
New End User ID: ${newEndUserId}<br>
|
|
652
|
+
Original End User ID: ${tracker.getSessionId()}<br>
|
|
653
|
+
endUserId changed: ${tracker.getSessionId() !== newEndUserId ? 'YES (BAD)' : 'NO (GOOD)'}
|
|
654
|
+
`;
|
|
655
|
+
authResultDiv.style.color = 'green';
|
|
656
|
+
|
|
657
|
+
} catch (error) {
|
|
658
|
+
console.error('Error authenticating user:', error);
|
|
659
|
+
addLog('Error authenticating user: ' + error.message);
|
|
660
|
+
|
|
661
|
+
const authResultDiv = document.getElementById('authResult');
|
|
662
|
+
authResultDiv.style.display = 'block';
|
|
663
|
+
authResultDiv.innerHTML = `
|
|
664
|
+
<strong>Authentication Failed!</strong><br>
|
|
665
|
+
Error: ${error.message}
|
|
666
|
+
`;
|
|
667
|
+
authResultDiv.style.color = 'red';
|
|
668
|
+
}
|
|
669
|
+
}
|
|
527
670
|
|
|
528
671
|
// View logs
|
|
529
672
|
function viewLogs() {
|
|
@@ -571,8 +714,7 @@
|
|
|
571
714
|
try {
|
|
572
715
|
const userInfo = tracker.getUserInfo ? tracker.getUserInfo() : null;
|
|
573
716
|
if (userInfo) {
|
|
574
|
-
const infoText = `
|
|
575
|
-
<strong>Detailed User Information:</strong><br>
|
|
717
|
+
const infoText = ` <strong>Detailed User Information:</strong><br>
|
|
576
718
|
End User ID: ${userInfo.endUserId || 'Not set'}<br>
|
|
577
719
|
Session ID: ${userInfo.sessionId}<br>
|
|
578
720
|
Is Preexisting User: ${userInfo.isPreexistingUser ? 'Yes' : 'No'}<br>
|
|
@@ -593,6 +735,44 @@
|
|
|
593
735
|
addLog(`Error getting user info: ${error.message}`);
|
|
594
736
|
}
|
|
595
737
|
}
|
|
738
|
+
|
|
739
|
+
// Show current authentication status
|
|
740
|
+
function showAuthStatus() {
|
|
741
|
+
if (!tracker) {
|
|
742
|
+
addLog('Tracker not available');
|
|
743
|
+
return;
|
|
744
|
+
}
|
|
745
|
+
try {
|
|
746
|
+
const userInfo = tracker.getUserInfo ? tracker.getUserInfo() : null;
|
|
747
|
+
const userAttributes = tracker.getUserAttributes ? tracker.getUserAttributes() : {};
|
|
748
|
+
|
|
749
|
+
if (userInfo) {
|
|
750
|
+
const statusText = `
|
|
751
|
+
<strong>Current Authentication Status:</strong><br>
|
|
752
|
+
End User ID: ${userInfo.endUserId || 'Not set'}<br>
|
|
753
|
+
Session ID: ${userInfo.sessionId}<br>
|
|
754
|
+
Is Preexisting User: ${userInfo.isPreexistingUser ? 'Yes' : 'No'}<br>
|
|
755
|
+
Initialized: ${userInfo.initialized ? 'Yes' : 'No'}<br>
|
|
756
|
+
<br>
|
|
757
|
+
<strong>User Attributes:</strong><br>
|
|
758
|
+
${Object.keys(userAttributes).length > 0 ?
|
|
759
|
+
Object.entries(userAttributes).map(([key, value]) => `${key}: ${value}`).join('<br>') :
|
|
760
|
+
'No user attributes set'
|
|
761
|
+
}
|
|
762
|
+
<br><br>
|
|
763
|
+
<strong>Cookie Check:</strong><br>
|
|
764
|
+
End User Cookie: ${tracker.getCookie ? tracker.getCookie(`human_behavior_end_user_id_13c3e029-ca45-4a3c-a33b-f5dcb297e31c`) : 'Method not available'}<br>
|
|
765
|
+
Session Cookie: ${tracker.getCookie ? tracker.getCookie('human_behavior_session_id') : 'Method not available'}
|
|
766
|
+
`;
|
|
767
|
+
addLog('Authentication status displayed', { userInfo, userAttributes });
|
|
768
|
+
alert(statusText);
|
|
769
|
+
} else {
|
|
770
|
+
addLog('getUserInfo method not available for status');
|
|
771
|
+
}
|
|
772
|
+
} catch (error) {
|
|
773
|
+
addLog(`Error getting authentication status: ${error.message}`);
|
|
774
|
+
}
|
|
775
|
+
}
|
|
596
776
|
|
|
597
777
|
// Add log message
|
|
598
778
|
function addLog(message, data = null) {
|
|
@@ -655,4 +835,4 @@
|
|
|
655
835
|
}, 5000); // Check every 5 seconds
|
|
656
836
|
</script>
|
|
657
837
|
</body>
|
|
658
|
-
</html>
|
|
838
|
+
</html>
|
package/src/api.ts
CHANGED
|
@@ -222,24 +222,31 @@ export class HumanBehaviorAPI {
|
|
|
222
222
|
|
|
223
223
|
async sendUserData(userId: string, userData: Record<string, any>, sessionId: string) {
|
|
224
224
|
try {
|
|
225
|
+
const payload = {
|
|
226
|
+
userId: userId,
|
|
227
|
+
userAttributes: userData,
|
|
228
|
+
sessionId: sessionId,
|
|
229
|
+
posthogName: userData.email || userData.name || null // Update posthogName with email
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
console.log('Sending user data to server:', payload);
|
|
233
|
+
|
|
225
234
|
const response = await fetch(`${this.baseUrl}/api/ingestion/user`, {
|
|
226
235
|
method: 'POST',
|
|
227
236
|
headers: {
|
|
228
237
|
'Content-Type': 'application/json',
|
|
229
238
|
'Authorization': `Bearer ${this.apiKey}`
|
|
230
239
|
},
|
|
231
|
-
body: JSON.stringify(
|
|
232
|
-
userId: userId,
|
|
233
|
-
userAttributes: userData,
|
|
234
|
-
sessionId: sessionId
|
|
235
|
-
})
|
|
240
|
+
body: JSON.stringify(payload)
|
|
236
241
|
});
|
|
237
242
|
|
|
238
243
|
if (!response.ok) {
|
|
239
244
|
throw new Error(`Failed to send user data: ${response.statusText} with API key: ${this.apiKey}`);
|
|
240
245
|
}
|
|
241
246
|
|
|
242
|
-
|
|
247
|
+
const result = await response.json();
|
|
248
|
+
console.log('Server response:', result);
|
|
249
|
+
return result;
|
|
243
250
|
} catch (error) {
|
|
244
251
|
logError('Error sending user data:', error);
|
|
245
252
|
throw error;
|
package/src/tracker.ts
CHANGED
|
@@ -725,19 +725,26 @@ export class HumanBehaviorTracker {
|
|
|
725
725
|
{ userId, userProperties }: { userId?: string, userProperties: Record<string, any> }
|
|
726
726
|
): Promise<string> {
|
|
727
727
|
await this.ensureInitialized();
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
728
|
+
|
|
729
|
+
// Keep the original endUserId (UUID) - don't change it
|
|
730
|
+
const originalEndUserId = this.endUserId;
|
|
731
|
+
|
|
732
|
+
// Store user properties
|
|
733
733
|
this.userProperties = userProperties;
|
|
734
|
-
|
|
735
|
-
//
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
734
|
+
|
|
735
|
+
// Send user data with the original endUserId
|
|
736
|
+
await this.api.sendUserData(originalEndUserId!, userProperties, this.sessionId);
|
|
737
|
+
|
|
738
|
+
// Don't update endUserId - keep it as the original UUID
|
|
739
|
+
// The posthogName will be updated on the server side with the email
|
|
740
|
+
|
|
741
|
+
return originalEndUserId || '';
|
|
742
|
+
}
|
|
743
|
+
/**
|
|
744
|
+
* Get current user attributes
|
|
745
|
+
*/
|
|
746
|
+
public getUserAttributes(): Record<string, any> {
|
|
747
|
+
return { ...this.userProperties };
|
|
741
748
|
}
|
|
742
749
|
|
|
743
750
|
public async start() {
|