@ihoomanai/chat-widget 3.0.11 → 3.0.13
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/index.cjs.js +108 -2
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +108 -2
- package/dist/index.esm.js.map +1 -1
- package/dist/index.esm.min.js +1 -1
- package/dist/index.esm.min.js.map +1 -1
- package/dist/index.umd.js +108 -2
- package/dist/index.umd.js.map +1 -1
- package/dist/index.umd.min.js +1 -1
- package/dist/index.umd.min.js.map +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/widget.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/types.ts +1 -0
- package/src/widget.ts +122 -1
package/src/types.ts
CHANGED
package/src/widget.ts
CHANGED
|
@@ -17,7 +17,7 @@ import type {
|
|
|
17
17
|
WidgetView,
|
|
18
18
|
} from './types';
|
|
19
19
|
|
|
20
|
-
const VERSION = '3.0.
|
|
20
|
+
const VERSION = '3.0.13';
|
|
21
21
|
const STORAGE_PREFIX = 'ihooman_chat_';
|
|
22
22
|
const DEFAULT_SERVER_URL = 'https://api.ihooman.ai';
|
|
23
23
|
|
|
@@ -197,6 +197,32 @@ function emit(event: WidgetEvent, data?: unknown): void {
|
|
|
197
197
|
}
|
|
198
198
|
}
|
|
199
199
|
|
|
200
|
+
/**
|
|
201
|
+
* Track an analytics event to the server
|
|
202
|
+
*/
|
|
203
|
+
async function trackAnalyticsEvent(
|
|
204
|
+
eventType: string,
|
|
205
|
+
metadata?: Record<string, unknown>
|
|
206
|
+
): Promise<void> {
|
|
207
|
+
if (!config.widgetId || !config.serverUrl) return;
|
|
208
|
+
|
|
209
|
+
try {
|
|
210
|
+
const url = `${config.serverUrl}/widget-analytics/track?widget_id=${encodeURIComponent(config.widgetId)}`;
|
|
211
|
+
await fetch(url, {
|
|
212
|
+
method: 'POST',
|
|
213
|
+
headers: { 'Content-Type': 'application/json' },
|
|
214
|
+
body: JSON.stringify({
|
|
215
|
+
event_type: eventType,
|
|
216
|
+
session_id: state.sessionId,
|
|
217
|
+
visitor_id: state.visitorId,
|
|
218
|
+
metadata: metadata || {},
|
|
219
|
+
}),
|
|
220
|
+
});
|
|
221
|
+
} catch (e) {
|
|
222
|
+
console.debug('[IhoomanChat] Failed to track event:', eventType, e);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
200
226
|
function getCurrentScrollDepth(): number {
|
|
201
227
|
const scrollTop = window.scrollY || document.documentElement.scrollTop;
|
|
202
228
|
const scrollHeight = document.documentElement.scrollHeight - window.innerHeight;
|
|
@@ -557,6 +583,11 @@ function setupEventListeners(): void {
|
|
|
557
583
|
const proactiveSecondaryBtn = elements.proactiveToast?.querySelector('.ihooman-proactive-toast-btn.secondary');
|
|
558
584
|
if (proactivePrimaryBtn) {
|
|
559
585
|
proactivePrimaryBtn.addEventListener('click', () => {
|
|
586
|
+
// Track click for the most recently shown proactive message
|
|
587
|
+
const lastShownId = shownProactiveIds[shownProactiveIds.length - 1];
|
|
588
|
+
if (lastShownId) {
|
|
589
|
+
trackAnalyticsEvent('proactive_clicked', { message_id: lastShownId });
|
|
590
|
+
}
|
|
560
591
|
hideProactiveToast();
|
|
561
592
|
open();
|
|
562
593
|
emit('proactive:clicked');
|
|
@@ -1052,6 +1083,15 @@ async function handleSurveySubmit(): Promise<void> {
|
|
|
1052
1083
|
}),
|
|
1053
1084
|
});
|
|
1054
1085
|
|
|
1086
|
+
// Track survey submission analytics
|
|
1087
|
+
trackAnalyticsEvent('survey_submitted', {
|
|
1088
|
+
survey_id: config.surveyConfig?.id,
|
|
1089
|
+
rating,
|
|
1090
|
+
comment: comment || null,
|
|
1091
|
+
session_id: state.sessionId,
|
|
1092
|
+
visitor_id: state.visitorId,
|
|
1093
|
+
});
|
|
1094
|
+
|
|
1055
1095
|
// Mark survey as completed for this session
|
|
1056
1096
|
storage('survey_completed_' + state.sessionId, true);
|
|
1057
1097
|
|
|
@@ -1076,6 +1116,13 @@ function checkAndShowSurvey(): void {
|
|
|
1076
1116
|
// Don't show if not enough messages (at least 2 exchanges)
|
|
1077
1117
|
if (state.messages.length < 4) return;
|
|
1078
1118
|
|
|
1119
|
+
// Track survey displayed analytics
|
|
1120
|
+
trackAnalyticsEvent('survey_displayed', {
|
|
1121
|
+
survey_id: config.surveyConfig.id,
|
|
1122
|
+
session_id: state.sessionId,
|
|
1123
|
+
visitor_id: state.visitorId,
|
|
1124
|
+
});
|
|
1125
|
+
|
|
1079
1126
|
// Show the survey
|
|
1080
1127
|
showView('survey');
|
|
1081
1128
|
emit('survey:shown', config.surveyConfig);
|
|
@@ -1089,6 +1136,15 @@ function showSurvey(): void {
|
|
|
1089
1136
|
console.warn('[IhoomanChat] No survey configured');
|
|
1090
1137
|
return;
|
|
1091
1138
|
}
|
|
1139
|
+
|
|
1140
|
+
// Track survey displayed analytics
|
|
1141
|
+
trackAnalyticsEvent('survey_displayed', {
|
|
1142
|
+
survey_id: config.surveyConfig.id,
|
|
1143
|
+
session_id: state.sessionId,
|
|
1144
|
+
visitor_id: state.visitorId,
|
|
1145
|
+
trigger: 'manual',
|
|
1146
|
+
});
|
|
1147
|
+
|
|
1092
1148
|
showView('survey');
|
|
1093
1149
|
emit('survey:shown', config.surveyConfig);
|
|
1094
1150
|
}
|
|
@@ -1122,6 +1178,14 @@ function handleSendClick(): void {
|
|
|
1122
1178
|
if (elements.sendBtn) elements.sendBtn.disabled = true;
|
|
1123
1179
|
|
|
1124
1180
|
addMessage(content, 'user');
|
|
1181
|
+
|
|
1182
|
+
// Track message sent analytics
|
|
1183
|
+
trackAnalyticsEvent('message_sent', {
|
|
1184
|
+
session_id: state.sessionId,
|
|
1185
|
+
visitor_id: state.visitorId,
|
|
1186
|
+
message_length: content.length,
|
|
1187
|
+
});
|
|
1188
|
+
|
|
1125
1189
|
showTyping();
|
|
1126
1190
|
sendMessageToServer(content);
|
|
1127
1191
|
}
|
|
@@ -1163,6 +1227,15 @@ async function sendMessageToServer(content: string): Promise<void> {
|
|
|
1163
1227
|
escalation_offered: data.escalation_offered,
|
|
1164
1228
|
quick_replies: data.quick_replies,
|
|
1165
1229
|
});
|
|
1230
|
+
|
|
1231
|
+
// Track message received analytics
|
|
1232
|
+
trackAnalyticsEvent('message_received', {
|
|
1233
|
+
session_id: state.sessionId,
|
|
1234
|
+
visitor_id: state.visitorId,
|
|
1235
|
+
message_length: data.response.length,
|
|
1236
|
+
has_sources: !!data.sources,
|
|
1237
|
+
confidence: data.confidence,
|
|
1238
|
+
});
|
|
1166
1239
|
}
|
|
1167
1240
|
} catch (error) {
|
|
1168
1241
|
hideTyping();
|
|
@@ -1300,6 +1373,9 @@ function showProactiveMessage(pm: ProactiveMessage): void {
|
|
|
1300
1373
|
storage('shown_proactive', shownProactiveIds);
|
|
1301
1374
|
storage('proactive_cooldowns', proactiveCooldowns);
|
|
1302
1375
|
|
|
1376
|
+
// Track analytics event
|
|
1377
|
+
trackAnalyticsEvent('proactive_displayed', { message_id: pm.id });
|
|
1378
|
+
|
|
1303
1379
|
// Show toast
|
|
1304
1380
|
if (elements.proactiveToast) {
|
|
1305
1381
|
const content = elements.proactiveToast.querySelector('.ihooman-proactive-toast-content');
|
|
@@ -1422,17 +1498,55 @@ function connectWebSocket(chatEndpoint?: string): void {
|
|
|
1422
1498
|
} else if (data.type === 'message') {
|
|
1423
1499
|
hideTyping();
|
|
1424
1500
|
const sender = data.sender === 'user' ? 'user' : 'bot';
|
|
1501
|
+
|
|
1502
|
+
// Check if this is an agent-related system message
|
|
1503
|
+
const metadata = data.metadata || {};
|
|
1504
|
+
if (metadata.agent_accepted) {
|
|
1505
|
+
// Agent has accepted the escalation - update status
|
|
1506
|
+
isLiveAgentMode = true;
|
|
1507
|
+
updateStatusBar('connected', '🟢 Connected to live agent');
|
|
1508
|
+
emit('escalation:accepted', { type: 'live_agent' });
|
|
1509
|
+
}
|
|
1510
|
+
if (metadata.closed_by_agent) {
|
|
1511
|
+
// Agent has closed the conversation - return to AI mode
|
|
1512
|
+
isLiveAgentMode = false;
|
|
1513
|
+
stopLiveAgentPolling();
|
|
1514
|
+
updateStatusBar('hidden');
|
|
1515
|
+
emit('escalation:end', { type: 'live_agent' });
|
|
1516
|
+
}
|
|
1517
|
+
|
|
1518
|
+
// Track message received analytics
|
|
1519
|
+
trackAnalyticsEvent('message_received', {
|
|
1520
|
+
session_id: state.sessionId,
|
|
1521
|
+
visitor_id: state.visitorId,
|
|
1522
|
+
sender: data.sender,
|
|
1523
|
+
is_system_message: metadata.is_system_message || false,
|
|
1524
|
+
});
|
|
1525
|
+
|
|
1425
1526
|
addMessage(data.content, sender, {
|
|
1426
1527
|
confidence: data.confidence,
|
|
1427
1528
|
agent_name: data.agent_name,
|
|
1428
1529
|
escalation_offered: data.escalation_offered,
|
|
1429
1530
|
escalated: data.escalated,
|
|
1430
1531
|
quick_replies: data.quick_replies,
|
|
1532
|
+
...metadata,
|
|
1431
1533
|
});
|
|
1432
1534
|
} else if (data.type === 'typing') {
|
|
1433
1535
|
data.is_typing ? showTyping() : hideTyping();
|
|
1434
1536
|
} else if (data.type === 'pong') {
|
|
1435
1537
|
// Heartbeat response
|
|
1538
|
+
} else if (data.type === 'agent_status') {
|
|
1539
|
+
// Handle agent status updates
|
|
1540
|
+
if (data.status === 'connected') {
|
|
1541
|
+
isLiveAgentMode = true;
|
|
1542
|
+
updateStatusBar('connected', '🟢 Connected to live agent');
|
|
1543
|
+
emit('escalation:accepted', { type: 'live_agent' });
|
|
1544
|
+
} else if (data.status === 'disconnected') {
|
|
1545
|
+
isLiveAgentMode = false;
|
|
1546
|
+
stopLiveAgentPolling();
|
|
1547
|
+
updateStatusBar('hidden');
|
|
1548
|
+
emit('escalation:end', { type: 'live_agent' });
|
|
1549
|
+
}
|
|
1436
1550
|
} else if (data.type === 'error') {
|
|
1437
1551
|
console.error('WebSocket server error:', data.message);
|
|
1438
1552
|
emit('error', { message: data.message });
|
|
@@ -1504,6 +1618,10 @@ function open(): void {
|
|
|
1504
1618
|
|
|
1505
1619
|
hideProactiveToast();
|
|
1506
1620
|
setTimeout(() => elements.input?.focus(), 300);
|
|
1621
|
+
|
|
1622
|
+
// Track widget open event
|
|
1623
|
+
trackAnalyticsEvent('widget_open');
|
|
1624
|
+
|
|
1507
1625
|
emit('open');
|
|
1508
1626
|
}
|
|
1509
1627
|
|
|
@@ -1514,6 +1632,9 @@ function close(): void {
|
|
|
1514
1632
|
if (elements.toggle) elements.toggle.classList.remove('open');
|
|
1515
1633
|
if (elements.window) elements.window.classList.remove('open');
|
|
1516
1634
|
|
|
1635
|
+
// Track widget close event
|
|
1636
|
+
trackAnalyticsEvent('widget_close');
|
|
1637
|
+
|
|
1517
1638
|
// Check if we should show survey after closing (if conversation had enough messages)
|
|
1518
1639
|
if (config.surveyConfig && state.messages.length >= 4) {
|
|
1519
1640
|
const surveyCompleted = state.sessionId && storage<boolean>('survey_completed_' + state.sessionId);
|