@product7/product7-js 0.3.2 → 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 +53 -29
- package/dist/README.md +53 -29
- package/dist/product7-js.js +455 -139
- package/dist/product7-js.js.map +1 -1
- package/dist/product7-js.min.js +1 -1
- package/dist/product7-js.min.js.map +1 -1
- package/package.json +1 -1
- package/src/api/services/MessengerService.js +1 -30
- package/src/core/APIService.js +35 -1
- package/src/core/BaseAPIService.js +124 -11
- package/src/core/Product7.js +182 -18
- package/src/docs/api.md +253 -89
- package/src/docs/example.md +203 -153
- package/src/docs/framework-integrations.md +236 -358
- package/src/docs/installation.md +171 -143
- package/src/index.js +48 -41
- package/src/widgets/MessengerWidget.js +27 -29
- package/src/widgets/SurveyWidget.js +20 -0
- package/src/widgets/messenger/views/ChatView.js +14 -8
- package/src/widgets/messenger/views/HomeView.js +5 -2
- package/types/index.d.ts +34 -0
package/dist/product7-js.js
CHANGED
|
@@ -737,36 +737,7 @@
|
|
|
737
737
|
}
|
|
738
738
|
|
|
739
739
|
async identifyContact(data) {
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
if (this.api.mock) {
|
|
743
|
-
await delay$1(300);
|
|
744
|
-
return {
|
|
745
|
-
status: true,
|
|
746
|
-
data: {
|
|
747
|
-
contact_id: 'mock_contact_' + Date.now(),
|
|
748
|
-
email: data.email,
|
|
749
|
-
name: data.name || '',
|
|
750
|
-
is_new: true,
|
|
751
|
-
},
|
|
752
|
-
};
|
|
753
|
-
}
|
|
754
|
-
|
|
755
|
-
return this.api._makeRequest('/widget/messenger/identify', {
|
|
756
|
-
method: 'POST',
|
|
757
|
-
headers: {
|
|
758
|
-
'Content-Type': 'application/json',
|
|
759
|
-
Authorization: `Bearer ${this.api.sessionToken}`,
|
|
760
|
-
},
|
|
761
|
-
body: JSON.stringify({
|
|
762
|
-
email: data.email,
|
|
763
|
-
name: data.name || '',
|
|
764
|
-
phone: data.phone || '',
|
|
765
|
-
company: data.company || '',
|
|
766
|
-
avatar_url: data.avatar_url || '',
|
|
767
|
-
metadata: data.metadata || {},
|
|
768
|
-
}),
|
|
769
|
-
});
|
|
740
|
+
return this.api.identify(data);
|
|
770
741
|
}
|
|
771
742
|
|
|
772
743
|
async sendTypingIndicator(conversationId, isTyping) {
|
|
@@ -995,11 +966,16 @@
|
|
|
995
966
|
this.sessionToken = null;
|
|
996
967
|
this.sessionExpiry = null;
|
|
997
968
|
this.metadata = config.metadata || null;
|
|
969
|
+
this.identitySyncedToken = null;
|
|
998
970
|
this.mock = config.mock || false;
|
|
999
971
|
this.env = config.env || 'production';
|
|
1000
972
|
this.baseURL = this._getBaseURL(config);
|
|
1001
973
|
|
|
1002
974
|
this._loadStoredSession();
|
|
975
|
+
this._loadStoredMetadata();
|
|
976
|
+
if (this.isSessionValid() && this.metadata) {
|
|
977
|
+
this.identitySyncedToken = this.sessionToken;
|
|
978
|
+
}
|
|
1003
979
|
}
|
|
1004
980
|
|
|
1005
981
|
_getBaseURL(config) {
|
|
@@ -1039,20 +1015,17 @@
|
|
|
1039
1015
|
: envConfig.base;
|
|
1040
1016
|
}
|
|
1041
1017
|
|
|
1042
|
-
async init(metadata =
|
|
1043
|
-
if (metadata) {
|
|
1044
|
-
this.metadata
|
|
1018
|
+
async init(metadata = undefined) {
|
|
1019
|
+
if (metadata !== undefined) {
|
|
1020
|
+
this.setMetadata(metadata);
|
|
1045
1021
|
}
|
|
1046
1022
|
|
|
1047
1023
|
if (this.isSessionValid()) {
|
|
1048
1024
|
return { sessionToken: this.sessionToken };
|
|
1049
1025
|
}
|
|
1050
1026
|
|
|
1051
|
-
if (!this.workspace
|
|
1052
|
-
throw new APIError$1(
|
|
1053
|
-
400,
|
|
1054
|
-
`Missing ${!this.workspace ? 'workspace' : 'user context'} for initialization`
|
|
1055
|
-
);
|
|
1027
|
+
if (!this.workspace) {
|
|
1028
|
+
throw new APIError$1(400, 'Missing workspace for initialization');
|
|
1056
1029
|
}
|
|
1057
1030
|
|
|
1058
1031
|
if (this.mock) {
|
|
@@ -1065,6 +1038,7 @@
|
|
|
1065
1038
|
async _initMockSession() {
|
|
1066
1039
|
this.sessionToken = 'mock_session_' + Date.now();
|
|
1067
1040
|
this.sessionExpiry = new Date(Date.now() + 3600 * 1000);
|
|
1041
|
+
this.identitySyncedToken = null;
|
|
1068
1042
|
this._storeSession();
|
|
1069
1043
|
return {
|
|
1070
1044
|
sessionToken: this.sessionToken,
|
|
@@ -1083,7 +1057,6 @@
|
|
|
1083
1057
|
async _initRealSession() {
|
|
1084
1058
|
const payload = {
|
|
1085
1059
|
workspace: this.workspace,
|
|
1086
|
-
user: this.metadata,
|
|
1087
1060
|
};
|
|
1088
1061
|
|
|
1089
1062
|
try {
|
|
@@ -1096,6 +1069,7 @@
|
|
|
1096
1069
|
|
|
1097
1070
|
this.sessionToken = initData.sessionToken;
|
|
1098
1071
|
this.sessionExpiry = new Date(Date.now() + initData.expiresIn * 1000);
|
|
1072
|
+
this.identitySyncedToken = null;
|
|
1099
1073
|
this._storeSession();
|
|
1100
1074
|
|
|
1101
1075
|
return {
|
|
@@ -1162,12 +1136,52 @@
|
|
|
1162
1136
|
this.sessionToken = null;
|
|
1163
1137
|
this.sessionExpiry = null;
|
|
1164
1138
|
await this.init();
|
|
1139
|
+
await this._restoreIdentity();
|
|
1165
1140
|
return await method.apply(this, args);
|
|
1166
1141
|
}
|
|
1167
1142
|
throw error;
|
|
1168
1143
|
}
|
|
1169
1144
|
}
|
|
1170
1145
|
|
|
1146
|
+
async identify(metadata = this.metadata) {
|
|
1147
|
+
if (metadata !== undefined) {
|
|
1148
|
+
this.setMetadata(metadata);
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1151
|
+
if (!this.metadata) {
|
|
1152
|
+
throw new APIError$1(400, 'Missing user context for identify');
|
|
1153
|
+
}
|
|
1154
|
+
|
|
1155
|
+
await this._ensureSession();
|
|
1156
|
+
|
|
1157
|
+
const payload = this._buildIdentifyPayload(this.metadata);
|
|
1158
|
+
|
|
1159
|
+
if (this.mock) {
|
|
1160
|
+
this.identitySyncedToken = this.sessionToken;
|
|
1161
|
+
return {
|
|
1162
|
+
status: true,
|
|
1163
|
+
identified: true,
|
|
1164
|
+
data: {
|
|
1165
|
+
user_id: payload.user_id || null,
|
|
1166
|
+
email: payload.email || null,
|
|
1167
|
+
name: payload.name || null,
|
|
1168
|
+
},
|
|
1169
|
+
};
|
|
1170
|
+
}
|
|
1171
|
+
|
|
1172
|
+
const response = await this._makeRequest('/widget/identify', {
|
|
1173
|
+
method: 'POST',
|
|
1174
|
+
body: JSON.stringify(payload),
|
|
1175
|
+
headers: {
|
|
1176
|
+
'Content-Type': 'application/json',
|
|
1177
|
+
Authorization: `Bearer ${this.sessionToken}`,
|
|
1178
|
+
},
|
|
1179
|
+
});
|
|
1180
|
+
|
|
1181
|
+
this.identitySyncedToken = this.sessionToken;
|
|
1182
|
+
return response;
|
|
1183
|
+
}
|
|
1184
|
+
|
|
1171
1185
|
isSessionValid() {
|
|
1172
1186
|
return (
|
|
1173
1187
|
this.sessionToken && this.sessionExpiry && new Date() < this.sessionExpiry
|
|
@@ -1175,8 +1189,13 @@
|
|
|
1175
1189
|
}
|
|
1176
1190
|
|
|
1177
1191
|
setMetadata(metadata) {
|
|
1178
|
-
this.metadata = metadata;
|
|
1179
|
-
this.
|
|
1192
|
+
this.metadata = metadata || null;
|
|
1193
|
+
this.identitySyncedToken = null;
|
|
1194
|
+
if (this.metadata) {
|
|
1195
|
+
this._storeData('product7_metadata', this.metadata);
|
|
1196
|
+
} else {
|
|
1197
|
+
this._removeData('product7_metadata');
|
|
1198
|
+
}
|
|
1180
1199
|
}
|
|
1181
1200
|
|
|
1182
1201
|
getMetadata() {
|
|
@@ -1186,6 +1205,7 @@
|
|
|
1186
1205
|
clearSession() {
|
|
1187
1206
|
this.sessionToken = null;
|
|
1188
1207
|
this.sessionExpiry = null;
|
|
1208
|
+
this.identitySyncedToken = null;
|
|
1189
1209
|
this._removeData('product7_session');
|
|
1190
1210
|
this._removeData('product7_metadata');
|
|
1191
1211
|
}
|
|
@@ -1211,6 +1231,14 @@
|
|
|
1211
1231
|
if (!stored) return false;
|
|
1212
1232
|
|
|
1213
1233
|
const sessionData = JSON.parse(stored);
|
|
1234
|
+
if (
|
|
1235
|
+
this.workspace &&
|
|
1236
|
+
sessionData.workspace &&
|
|
1237
|
+
sessionData.workspace !== this.workspace
|
|
1238
|
+
) {
|
|
1239
|
+
localStorage.removeItem('product7_session');
|
|
1240
|
+
return false;
|
|
1241
|
+
}
|
|
1214
1242
|
this.sessionToken = sessionData.token;
|
|
1215
1243
|
this.sessionExpiry = new Date(sessionData.expiry);
|
|
1216
1244
|
|
|
@@ -1220,6 +1248,32 @@
|
|
|
1220
1248
|
}
|
|
1221
1249
|
}
|
|
1222
1250
|
|
|
1251
|
+
_loadStoredMetadata() {
|
|
1252
|
+
if (this.metadata || typeof localStorage === 'undefined') return false;
|
|
1253
|
+
|
|
1254
|
+
try {
|
|
1255
|
+
const session = localStorage.getItem('product7_session');
|
|
1256
|
+
if (session) {
|
|
1257
|
+
const sessionData = JSON.parse(session);
|
|
1258
|
+
if (
|
|
1259
|
+
this.workspace &&
|
|
1260
|
+
sessionData.workspace &&
|
|
1261
|
+
sessionData.workspace !== this.workspace
|
|
1262
|
+
) {
|
|
1263
|
+
return false;
|
|
1264
|
+
}
|
|
1265
|
+
}
|
|
1266
|
+
|
|
1267
|
+
const stored = localStorage.getItem('product7_metadata');
|
|
1268
|
+
if (!stored) return false;
|
|
1269
|
+
|
|
1270
|
+
this.metadata = JSON.parse(stored);
|
|
1271
|
+
return true;
|
|
1272
|
+
} catch (error) {
|
|
1273
|
+
return false;
|
|
1274
|
+
}
|
|
1275
|
+
}
|
|
1276
|
+
|
|
1223
1277
|
_storeData(key, value) {
|
|
1224
1278
|
if (typeof localStorage !== 'undefined') {
|
|
1225
1279
|
localStorage.setItem(key, JSON.stringify(value));
|
|
@@ -1282,6 +1336,36 @@
|
|
|
1282
1336
|
const queryString = this._buildQueryParams(params);
|
|
1283
1337
|
return `${endpoint}${queryString ? '?' + queryString : ''}`;
|
|
1284
1338
|
}
|
|
1339
|
+
|
|
1340
|
+
_buildIdentifyPayload(metadata = {}) {
|
|
1341
|
+
const payload = {
|
|
1342
|
+
user_id: metadata.user_id,
|
|
1343
|
+
email: metadata.email,
|
|
1344
|
+
name: metadata.name,
|
|
1345
|
+
avatar:
|
|
1346
|
+
metadata.profile_picture || metadata.avatar_url || metadata.avatar,
|
|
1347
|
+
attributes: metadata.custom_fields || {},
|
|
1348
|
+
};
|
|
1349
|
+
|
|
1350
|
+
if (metadata.company) {
|
|
1351
|
+
payload.company = metadata.company;
|
|
1352
|
+
}
|
|
1353
|
+
|
|
1354
|
+
return payload;
|
|
1355
|
+
}
|
|
1356
|
+
|
|
1357
|
+
async _restoreIdentity() {
|
|
1358
|
+
if (
|
|
1359
|
+
!this.metadata ||
|
|
1360
|
+
!this.sessionToken ||
|
|
1361
|
+
!this.identitySyncedToken ||
|
|
1362
|
+
this.identitySyncedToken === this.sessionToken
|
|
1363
|
+
) {
|
|
1364
|
+
return;
|
|
1365
|
+
}
|
|
1366
|
+
|
|
1367
|
+
await this.identify(this.metadata);
|
|
1368
|
+
}
|
|
1285
1369
|
}
|
|
1286
1370
|
|
|
1287
1371
|
class APIService extends BaseAPIService {
|
|
@@ -1503,8 +1587,42 @@
|
|
|
1503
1587
|
return this.messenger.submitRating(conversationId, data);
|
|
1504
1588
|
}
|
|
1505
1589
|
|
|
1590
|
+
async identify(metadata) {
|
|
1591
|
+
await this._ensureSession();
|
|
1592
|
+
|
|
1593
|
+
if (this.mock) {
|
|
1594
|
+
await new Promise((r) => setTimeout(r, 300));
|
|
1595
|
+
return {
|
|
1596
|
+
status: true,
|
|
1597
|
+
data: {
|
|
1598
|
+
contact_id: 'mock_contact_' + Date.now(),
|
|
1599
|
+
email: metadata.email,
|
|
1600
|
+
name: metadata.name || '',
|
|
1601
|
+
is_new: true,
|
|
1602
|
+
},
|
|
1603
|
+
};
|
|
1604
|
+
}
|
|
1605
|
+
|
|
1606
|
+
return this._makeRequest('/widget/messenger/identify', {
|
|
1607
|
+
method: 'POST',
|
|
1608
|
+
headers: {
|
|
1609
|
+
'Content-Type': 'application/json',
|
|
1610
|
+
Authorization: `Bearer ${this.sessionToken}`,
|
|
1611
|
+
},
|
|
1612
|
+
body: JSON.stringify({
|
|
1613
|
+
user_id: metadata.user_id || null,
|
|
1614
|
+
email: metadata.email || '',
|
|
1615
|
+
name: metadata.name || '',
|
|
1616
|
+
phone: metadata.phone || '',
|
|
1617
|
+
company: metadata.company || '',
|
|
1618
|
+
avatar_url: metadata.avatar_url || '',
|
|
1619
|
+
metadata: metadata.custom_fields || {},
|
|
1620
|
+
}),
|
|
1621
|
+
});
|
|
1622
|
+
}
|
|
1623
|
+
|
|
1506
1624
|
async identifyContact(data) {
|
|
1507
|
-
return this.
|
|
1625
|
+
return this.identify(data);
|
|
1508
1626
|
}
|
|
1509
1627
|
|
|
1510
1628
|
async getHelpCollections(options) {
|
|
@@ -9492,7 +9610,9 @@
|
|
|
9492
9610
|
|
|
9493
9611
|
this._unsubscribe = this.state.subscribe((type, data) => {
|
|
9494
9612
|
if (type === 'connectionChange') {
|
|
9495
|
-
const banner = this.element?.querySelector(
|
|
9613
|
+
const banner = this.element?.querySelector(
|
|
9614
|
+
'.messenger-connection-banner'
|
|
9615
|
+
);
|
|
9496
9616
|
if (banner) {
|
|
9497
9617
|
banner.style.display = data.connected ? 'none' : 'flex';
|
|
9498
9618
|
}
|
|
@@ -9542,9 +9662,10 @@
|
|
|
9542
9662
|
? this._renderEmptyState(isNewConversation)
|
|
9543
9663
|
: this._renderGroupedMessages(messages);
|
|
9544
9664
|
|
|
9545
|
-
const defaultPlaceholder =
|
|
9665
|
+
const defaultPlaceholder =
|
|
9666
|
+
this.options.composePlaceholder || 'Write a message...';
|
|
9546
9667
|
const placeholder = isNewConversation
|
|
9547
|
-
?
|
|
9668
|
+
? this.options.composePlaceholder || 'Start typing your message...'
|
|
9548
9669
|
: isClosed
|
|
9549
9670
|
? 'Conversation closed'
|
|
9550
9671
|
: defaultPlaceholder;
|
|
@@ -9565,7 +9686,7 @@
|
|
|
9565
9686
|
</div>
|
|
9566
9687
|
<div class="messenger-chat-header-info">
|
|
9567
9688
|
<span class="messenger-chat-title">${this._escapeHtml(teamName)}</span>
|
|
9568
|
-
<span class="messenger-chat-subtitle">${isClosed ? 'Conversation resolved' :
|
|
9689
|
+
<span class="messenger-chat-subtitle">${isClosed ? 'Conversation resolved' : this.state.responseTime || 'Typically replies within minutes'}</span>
|
|
9569
9690
|
</div>
|
|
9570
9691
|
<div class="messenger-chat-header-actions">
|
|
9571
9692
|
<button class="sdk-btn-icon sdk-close-btn messenger-mobile-close-btn" aria-label="Close">
|
|
@@ -9682,7 +9803,9 @@
|
|
|
9682
9803
|
const messageClass = isOwn
|
|
9683
9804
|
? 'messenger-message-own'
|
|
9684
9805
|
: 'messenger-message-received';
|
|
9685
|
-
const timeStr = isLastInGroup
|
|
9806
|
+
const timeStr = isLastInGroup
|
|
9807
|
+
? this._formatMessageTime(message.timestamp)
|
|
9808
|
+
: '';
|
|
9686
9809
|
const attachmentsHtml = this._renderMessageAttachments(message.attachments);
|
|
9687
9810
|
const isOptimistic = message.isOptimistic;
|
|
9688
9811
|
|
|
@@ -9696,9 +9819,10 @@
|
|
|
9696
9819
|
if (isOwn) {
|
|
9697
9820
|
const sentIndicator = isLastInGroup
|
|
9698
9821
|
? `<div class="messenger-message-meta messenger-message-meta-own">
|
|
9699
|
-
${
|
|
9700
|
-
|
|
9701
|
-
|
|
9822
|
+
${
|
|
9823
|
+
isOptimistic
|
|
9824
|
+
? `<span class="messenger-message-sent-status">Sending…</span>`
|
|
9825
|
+
: `<span class="messenger-message-sent-status">Sent</span>`
|
|
9702
9826
|
}
|
|
9703
9827
|
${timeStr ? `<span>·</span><span>${timeStr}</span>` : ''}
|
|
9704
9828
|
</div>`
|
|
@@ -10929,7 +11053,8 @@
|
|
|
10929
11053
|
const title = conversation.title || teamName;
|
|
10930
11054
|
const timeAgo = this._formatTimeAgo(conversation.lastMessageTime);
|
|
10931
11055
|
const preview = conversation.lastMessage
|
|
10932
|
-
? conversation.lastMessage.substring(0, 48) +
|
|
11056
|
+
? conversation.lastMessage.substring(0, 48) +
|
|
11057
|
+
(conversation.lastMessage.length > 48 ? '...' : '')
|
|
10933
11058
|
: '';
|
|
10934
11059
|
const hasUnread = conversation.unread > 0;
|
|
10935
11060
|
|
|
@@ -11045,7 +11170,9 @@
|
|
|
11045
11170
|
}
|
|
11046
11171
|
|
|
11047
11172
|
_attachEvents() {
|
|
11048
|
-
const recentCard = this.element.querySelector(
|
|
11173
|
+
const recentCard = this.element.querySelector(
|
|
11174
|
+
'.messenger-home-recent-card'
|
|
11175
|
+
);
|
|
11049
11176
|
if (recentCard) {
|
|
11050
11177
|
recentCard.addEventListener('click', () => {
|
|
11051
11178
|
const convId = recentCard.dataset.conversationId;
|
|
@@ -11326,6 +11453,10 @@
|
|
|
11326
11453
|
this._handleConversationClosed = this._handleConversationClosed.bind(this);
|
|
11327
11454
|
}
|
|
11328
11455
|
|
|
11456
|
+
_hasTrigger() {
|
|
11457
|
+
return this.options.trigger === true || this.options.trigger === undefined;
|
|
11458
|
+
}
|
|
11459
|
+
|
|
11329
11460
|
_createInternalFeedbackWidget() {
|
|
11330
11461
|
try {
|
|
11331
11462
|
const widget = this.sdk.createWidget('button', {
|
|
@@ -11361,11 +11492,13 @@
|
|
|
11361
11492
|
this._feedbackWidget = this._createInternalFeedbackWidget();
|
|
11362
11493
|
}
|
|
11363
11494
|
|
|
11364
|
-
|
|
11365
|
-
|
|
11366
|
-
|
|
11367
|
-
|
|
11368
|
-
|
|
11495
|
+
if (this._hasTrigger()) {
|
|
11496
|
+
this.launcher = new MessengerLauncher(this.messengerState, {
|
|
11497
|
+
position: this.messengerOptions.position,
|
|
11498
|
+
primaryColor: this.messengerOptions.primaryColor,
|
|
11499
|
+
});
|
|
11500
|
+
container.appendChild(this.launcher.render());
|
|
11501
|
+
}
|
|
11369
11502
|
|
|
11370
11503
|
this.panel = new MessengerPanel(this.messengerState, {
|
|
11371
11504
|
position: this.messengerOptions.position,
|
|
@@ -11500,28 +11633,13 @@
|
|
|
11500
11633
|
|
|
11501
11634
|
async _handleIdentifyContact(contactData) {
|
|
11502
11635
|
try {
|
|
11503
|
-
|
|
11504
|
-
|
|
11636
|
+
// Route through sdk.identify() so the SDK-level identity state is updated
|
|
11637
|
+
// and applyIdentity() handles the messenger state + WebSocket as a side effect.
|
|
11638
|
+
const result = await this.sdk.identify({
|
|
11505
11639
|
email: contactData.email,
|
|
11640
|
+
name: contactData.name,
|
|
11506
11641
|
});
|
|
11507
|
-
|
|
11508
|
-
if (response.status) {
|
|
11509
|
-
console.log(
|
|
11510
|
-
'[MessengerWidget] Contact identified:',
|
|
11511
|
-
response.data.contact_id
|
|
11512
|
-
);
|
|
11513
|
-
this.messengerState.setIdentified(true, {
|
|
11514
|
-
name: contactData.name,
|
|
11515
|
-
email: contactData.email,
|
|
11516
|
-
});
|
|
11517
|
-
|
|
11518
|
-
// Start WebSocket now that session token is available
|
|
11519
|
-
if (this.apiService?.sessionToken && !this.wsService?.isConnected) {
|
|
11520
|
-
this._initWebSocket();
|
|
11521
|
-
}
|
|
11522
|
-
}
|
|
11523
|
-
|
|
11524
|
-
return response;
|
|
11642
|
+
return result;
|
|
11525
11643
|
} catch (error) {
|
|
11526
11644
|
console.error('[MessengerWidget] Failed to identify contact:', error);
|
|
11527
11645
|
throw error;
|
|
@@ -11529,10 +11647,14 @@
|
|
|
11529
11647
|
}
|
|
11530
11648
|
|
|
11531
11649
|
markAsIdentified(name, email) {
|
|
11532
|
-
|
|
11533
|
-
|
|
11650
|
+
// Called externally by the app when the user is already known.
|
|
11651
|
+
// No API call needed — identity was already established via sdk.identify().
|
|
11652
|
+
this.applyIdentity({ name, email });
|
|
11653
|
+
}
|
|
11654
|
+
|
|
11655
|
+
applyIdentity(metadata = {}) {
|
|
11656
|
+
this.messengerState.setIdentified(true, metadata);
|
|
11534
11657
|
|
|
11535
|
-
// Start WebSocket now that we have a session token
|
|
11536
11658
|
if (this.apiService?.sessionToken && !this.wsService?.isConnected) {
|
|
11537
11659
|
this._initWebSocket();
|
|
11538
11660
|
}
|
|
@@ -12076,7 +12198,10 @@
|
|
|
12076
12198
|
}
|
|
12077
12199
|
|
|
12078
12200
|
_hasExplicitOption(key) {
|
|
12079
|
-
return Object.prototype.hasOwnProperty.call(
|
|
12201
|
+
return Object.prototype.hasOwnProperty.call(
|
|
12202
|
+
this._explicitOptions || {},
|
|
12203
|
+
key
|
|
12204
|
+
);
|
|
12080
12205
|
}
|
|
12081
12206
|
|
|
12082
12207
|
async checkAgentAvailability() {
|
|
@@ -12371,6 +12496,7 @@
|
|
|
12371
12496
|
|
|
12372
12497
|
SurveyWidget.removeDanglingElements();
|
|
12373
12498
|
this._renderSurvey();
|
|
12499
|
+
this.state.isOpen = true;
|
|
12374
12500
|
this.surveyState.isVisible = true;
|
|
12375
12501
|
this.sdk.eventBus.emit('survey:shown', {
|
|
12376
12502
|
widget: this,
|
|
@@ -12380,6 +12506,7 @@
|
|
|
12380
12506
|
}
|
|
12381
12507
|
|
|
12382
12508
|
hide() {
|
|
12509
|
+
this.state.isOpen = false;
|
|
12383
12510
|
this._closeSurvey();
|
|
12384
12511
|
return this;
|
|
12385
12512
|
}
|
|
@@ -12454,6 +12581,7 @@
|
|
|
12454
12581
|
this._attachSurveyEvents();
|
|
12455
12582
|
|
|
12456
12583
|
requestAnimationFrame(() => {
|
|
12584
|
+
if (!this.surveyElement) return;
|
|
12457
12585
|
this.surveyElement.style.opacity = '1';
|
|
12458
12586
|
this.surveyElement.style.transform =
|
|
12459
12587
|
this.surveyOptions.position === 'center'
|
|
@@ -13591,6 +13719,7 @@
|
|
|
13591
13719
|
}
|
|
13592
13720
|
|
|
13593
13721
|
_closeSurvey(resetState = true, immediate = false) {
|
|
13722
|
+
this.state.isOpen = false;
|
|
13594
13723
|
if (this._escapeHandler) {
|
|
13595
13724
|
document.removeEventListener('keydown', this._escapeHandler);
|
|
13596
13725
|
this._escapeHandler = null;
|
|
@@ -13653,6 +13782,22 @@
|
|
|
13653
13782
|
this.sdk.eventBus.emit('survey:closed', { widget: this });
|
|
13654
13783
|
}
|
|
13655
13784
|
|
|
13785
|
+
open() {
|
|
13786
|
+
return this.show();
|
|
13787
|
+
}
|
|
13788
|
+
|
|
13789
|
+
close() {
|
|
13790
|
+
return this.hide();
|
|
13791
|
+
}
|
|
13792
|
+
|
|
13793
|
+
toggle() {
|
|
13794
|
+
if (this.surveyState.isVisible) {
|
|
13795
|
+
return this.hide();
|
|
13796
|
+
}
|
|
13797
|
+
|
|
13798
|
+
return this.show();
|
|
13799
|
+
}
|
|
13800
|
+
|
|
13656
13801
|
destroy() {
|
|
13657
13802
|
this._closeSurvey(true, true);
|
|
13658
13803
|
super.destroy();
|
|
@@ -13770,6 +13915,7 @@
|
|
|
13770
13915
|
constructor(config = {}) {
|
|
13771
13916
|
this.config = this._validateAndMergeConfig(config);
|
|
13772
13917
|
this.initialized = false;
|
|
13918
|
+
this.identified = false;
|
|
13773
13919
|
this.widgets = new Map();
|
|
13774
13920
|
this.eventBus = new EventBus();
|
|
13775
13921
|
|
|
@@ -13814,13 +13960,14 @@
|
|
|
13814
13960
|
this._injectStyles();
|
|
13815
13961
|
|
|
13816
13962
|
try {
|
|
13817
|
-
const initData = await this.apiService.init(
|
|
13963
|
+
const initData = await this.apiService.init();
|
|
13818
13964
|
|
|
13819
13965
|
if (initData.config) {
|
|
13820
13966
|
this.config = deepMerge(initData.config, this.config);
|
|
13821
13967
|
}
|
|
13822
13968
|
|
|
13823
13969
|
this.initialized = true;
|
|
13970
|
+
const identifyResult = await this._syncConfiguredMetadataAfterInit();
|
|
13824
13971
|
this.eventBus.emit('sdk:initialized', {
|
|
13825
13972
|
config: this.config,
|
|
13826
13973
|
sessionToken: initData.sessionToken,
|
|
@@ -13831,6 +13978,7 @@
|
|
|
13831
13978
|
config: initData.config || {},
|
|
13832
13979
|
sessionToken: initData.sessionToken,
|
|
13833
13980
|
expiresIn: initData.expiresIn,
|
|
13981
|
+
identified: Boolean(identifyResult?.identified),
|
|
13834
13982
|
};
|
|
13835
13983
|
} catch (error) {
|
|
13836
13984
|
this.eventBus.emit('sdk:error', { error });
|
|
@@ -13845,10 +13993,14 @@
|
|
|
13845
13993
|
);
|
|
13846
13994
|
}
|
|
13847
13995
|
|
|
13996
|
+
const requestedType = type || 'button';
|
|
13997
|
+
const normalizedType = this._normalizeWidgetType(requestedType);
|
|
13848
13998
|
const widgetId = generateId('widget');
|
|
13849
|
-
const widgetConfig = this._getWidgetTypeConfig(
|
|
13850
|
-
const explicitOptions = this._omitUndefined(
|
|
13851
|
-
|
|
13999
|
+
const widgetConfig = this._getWidgetTypeConfig(normalizedType);
|
|
14000
|
+
const explicitOptions = this._omitUndefined(
|
|
14001
|
+
this._normalizeWidgetOptions(normalizedType, options)
|
|
14002
|
+
);
|
|
14003
|
+
const widgetEnabled = this._isWidgetEnabled(normalizedType, {
|
|
13852
14004
|
...widgetConfig,
|
|
13853
14005
|
...explicitOptions,
|
|
13854
14006
|
});
|
|
@@ -13863,15 +14015,35 @@
|
|
|
13863
14015
|
};
|
|
13864
14016
|
|
|
13865
14017
|
try {
|
|
13866
|
-
const widget = WidgetFactory.create(
|
|
14018
|
+
const widget = WidgetFactory.create(normalizedType, widgetOptions);
|
|
13867
14019
|
this.widgets.set(widgetId, widget);
|
|
13868
|
-
this.eventBus.emit('widget:created', {
|
|
14020
|
+
this.eventBus.emit('widget:created', {
|
|
14021
|
+
widget,
|
|
14022
|
+
type: requestedType,
|
|
14023
|
+
internalType: normalizedType,
|
|
14024
|
+
});
|
|
13869
14025
|
return widget;
|
|
13870
14026
|
} catch (error) {
|
|
13871
14027
|
throw new SDKError(`Failed to create widget: ${error.message}`, error);
|
|
13872
14028
|
}
|
|
13873
14029
|
}
|
|
13874
14030
|
|
|
14031
|
+
createFeedbackWidget(options = {}) {
|
|
14032
|
+
return this.createWidget('feedback', options);
|
|
14033
|
+
}
|
|
14034
|
+
|
|
14035
|
+
createMessengerWidget(options = {}) {
|
|
14036
|
+
return this.createWidget('messenger', options);
|
|
14037
|
+
}
|
|
14038
|
+
|
|
14039
|
+
createChangelogWidget(options = {}) {
|
|
14040
|
+
return this.createWidget('changelog', options);
|
|
14041
|
+
}
|
|
14042
|
+
|
|
14043
|
+
createSurveyWidget(options = {}) {
|
|
14044
|
+
return this.createWidget('survey', options);
|
|
14045
|
+
}
|
|
14046
|
+
|
|
13875
14047
|
getWidget(id) {
|
|
13876
14048
|
return this.widgets.get(id);
|
|
13877
14049
|
}
|
|
@@ -13990,7 +14162,7 @@
|
|
|
13990
14162
|
return null;
|
|
13991
14163
|
}
|
|
13992
14164
|
|
|
13993
|
-
const surveyWidget = this.
|
|
14165
|
+
const surveyWidget = this.createSurveyWidget({
|
|
13994
14166
|
surveyId: normalizedOptions.surveyId,
|
|
13995
14167
|
surveyType:
|
|
13996
14168
|
normalizedOptions.surveyType || normalizedOptions.type || 'nps',
|
|
@@ -14224,18 +14396,34 @@
|
|
|
14224
14396
|
? this.config.widgets
|
|
14225
14397
|
: {};
|
|
14226
14398
|
|
|
14227
|
-
const
|
|
14228
|
-
|
|
14229
|
-
|
|
14399
|
+
const mergedTypeConfig = this._getWidgetTypeAliases(type).reduce(
|
|
14400
|
+
(config, alias) => {
|
|
14401
|
+
const legacyTypeConfig = this._isPlainObject(this.config?.[alias])
|
|
14402
|
+
? this.config[alias]
|
|
14403
|
+
: {};
|
|
14230
14404
|
|
|
14231
|
-
|
|
14232
|
-
|
|
14233
|
-
|
|
14405
|
+
const namespacedTypeConfig = this._isPlainObject(widgetsConfig?.[alias])
|
|
14406
|
+
? widgetsConfig[alias]
|
|
14407
|
+
: {};
|
|
14234
14408
|
|
|
14235
|
-
|
|
14409
|
+
return deepMerge(
|
|
14410
|
+
config,
|
|
14411
|
+
deepMerge(legacyTypeConfig, namespacedTypeConfig)
|
|
14412
|
+
);
|
|
14413
|
+
},
|
|
14414
|
+
{}
|
|
14415
|
+
);
|
|
14236
14416
|
return this._toCamelCaseObject(mergedTypeConfig);
|
|
14237
14417
|
}
|
|
14238
14418
|
|
|
14419
|
+
_getWidgetTypeAliases(type) {
|
|
14420
|
+
if (type === 'button') {
|
|
14421
|
+
return ['button', 'feedback'];
|
|
14422
|
+
}
|
|
14423
|
+
|
|
14424
|
+
return [type];
|
|
14425
|
+
}
|
|
14426
|
+
|
|
14239
14427
|
_isWidgetEnabled(type, options = {}) {
|
|
14240
14428
|
const typeConfig = this._getWidgetTypeConfig(type);
|
|
14241
14429
|
if (typeConfig.enabled === false) {
|
|
@@ -14278,6 +14466,31 @@
|
|
|
14278
14466
|
return normalized;
|
|
14279
14467
|
}
|
|
14280
14468
|
|
|
14469
|
+
_normalizeWidgetType(type) {
|
|
14470
|
+
if (type === 'feedback') {
|
|
14471
|
+
return 'button';
|
|
14472
|
+
}
|
|
14473
|
+
|
|
14474
|
+
return type;
|
|
14475
|
+
}
|
|
14476
|
+
|
|
14477
|
+
_normalizeWidgetOptions(type, options = {}) {
|
|
14478
|
+
if (!this._isPlainObject(options)) {
|
|
14479
|
+
return options;
|
|
14480
|
+
}
|
|
14481
|
+
|
|
14482
|
+
const normalizedOptions = { ...options };
|
|
14483
|
+
if (
|
|
14484
|
+
normalizedOptions.headless === true &&
|
|
14485
|
+
normalizedOptions.trigger === undefined &&
|
|
14486
|
+
type !== 'survey'
|
|
14487
|
+
) {
|
|
14488
|
+
normalizedOptions.trigger = false;
|
|
14489
|
+
}
|
|
14490
|
+
|
|
14491
|
+
return normalizedOptions;
|
|
14492
|
+
}
|
|
14493
|
+
|
|
14281
14494
|
_omitUndefined(value) {
|
|
14282
14495
|
if (!this._isPlainObject(value)) {
|
|
14283
14496
|
return value;
|
|
@@ -14322,7 +14535,7 @@
|
|
|
14322
14535
|
return null;
|
|
14323
14536
|
}
|
|
14324
14537
|
|
|
14325
|
-
const changelogWidget = this.
|
|
14538
|
+
const changelogWidget = this.createChangelogWidget({
|
|
14326
14539
|
...defaults,
|
|
14327
14540
|
...configDefaults,
|
|
14328
14541
|
...explicitOptions,
|
|
@@ -14389,10 +14602,15 @@
|
|
|
14389
14602
|
}
|
|
14390
14603
|
|
|
14391
14604
|
setMetadata(metadata) {
|
|
14605
|
+
if (metadata) {
|
|
14606
|
+
this._validateMetadata(metadata);
|
|
14607
|
+
}
|
|
14608
|
+
|
|
14392
14609
|
this.config.metadata = metadata;
|
|
14393
14610
|
if (this.apiService) {
|
|
14394
14611
|
this.apiService.setMetadata(metadata);
|
|
14395
14612
|
}
|
|
14613
|
+
this.identified = false;
|
|
14396
14614
|
this.eventBus.emit('metadata:updated', { metadata });
|
|
14397
14615
|
}
|
|
14398
14616
|
|
|
@@ -14403,11 +14621,53 @@
|
|
|
14403
14621
|
);
|
|
14404
14622
|
}
|
|
14405
14623
|
|
|
14624
|
+
async identify(metadata = this.config.metadata) {
|
|
14625
|
+
if (!this.initialized) {
|
|
14626
|
+
throw new SDKError(
|
|
14627
|
+
'SDK must be initialized before identifying users. Call init() first.'
|
|
14628
|
+
);
|
|
14629
|
+
}
|
|
14630
|
+
|
|
14631
|
+
if (!metadata) {
|
|
14632
|
+
throw new SDKError(
|
|
14633
|
+
'Identify requires metadata. Provide at least user_id or email.'
|
|
14634
|
+
);
|
|
14635
|
+
}
|
|
14636
|
+
|
|
14637
|
+
this._validateMetadata(metadata);
|
|
14638
|
+
this.setMetadata(metadata);
|
|
14639
|
+
|
|
14640
|
+
try {
|
|
14641
|
+
const response = await this.apiService.identify(metadata);
|
|
14642
|
+
const configPatch = this._extractIdentifyConfig(response);
|
|
14643
|
+
if (Object.keys(configPatch).length > 0) {
|
|
14644
|
+
this.updateConfig(configPatch);
|
|
14645
|
+
}
|
|
14646
|
+
|
|
14647
|
+
this.identified = true;
|
|
14648
|
+
this._applyIdentityToWidgets(metadata);
|
|
14649
|
+
|
|
14650
|
+
const result = {
|
|
14651
|
+
identified: true,
|
|
14652
|
+
metadata: this.getMetadata(),
|
|
14653
|
+
response,
|
|
14654
|
+
};
|
|
14655
|
+
|
|
14656
|
+
this.eventBus.emit('sdk:identified', result);
|
|
14657
|
+
return result;
|
|
14658
|
+
} catch (error) {
|
|
14659
|
+
this.identified = false;
|
|
14660
|
+
this.eventBus.emit('sdk:error', { error, phase: 'identify' });
|
|
14661
|
+
throw new SDKError(`Failed to identify user: ${error.message}`, error);
|
|
14662
|
+
}
|
|
14663
|
+
}
|
|
14664
|
+
|
|
14406
14665
|
async reinitialize(newMetadata = null) {
|
|
14407
14666
|
this.apiService.clearSession();
|
|
14408
14667
|
this.initialized = false;
|
|
14668
|
+
this.identified = false;
|
|
14409
14669
|
|
|
14410
|
-
if (newMetadata) {
|
|
14670
|
+
if (newMetadata !== null) {
|
|
14411
14671
|
this.setMetadata(newMetadata);
|
|
14412
14672
|
}
|
|
14413
14673
|
|
|
@@ -14436,10 +14696,11 @@
|
|
|
14436
14696
|
|
|
14437
14697
|
destroy() {
|
|
14438
14698
|
this.destroyAllWidgets();
|
|
14439
|
-
this.eventBus.
|
|
14699
|
+
this.eventBus.emit('sdk:destroyed');
|
|
14700
|
+
this.eventBus.clear();
|
|
14440
14701
|
this.apiService.clearSession();
|
|
14441
14702
|
this.initialized = false;
|
|
14442
|
-
this.
|
|
14703
|
+
this.identified = false;
|
|
14443
14704
|
}
|
|
14444
14705
|
|
|
14445
14706
|
hasFeedbackBeenSubmitted(cooldownDays = 30) {
|
|
@@ -14558,7 +14819,12 @@
|
|
|
14558
14819
|
|
|
14559
14820
|
_bindMethods() {
|
|
14560
14821
|
this.createWidget = this.createWidget.bind(this);
|
|
14822
|
+
this.createFeedbackWidget = this.createFeedbackWidget.bind(this);
|
|
14823
|
+
this.createMessengerWidget = this.createMessengerWidget.bind(this);
|
|
14824
|
+
this.createChangelogWidget = this.createChangelogWidget.bind(this);
|
|
14825
|
+
this.createSurveyWidget = this.createSurveyWidget.bind(this);
|
|
14561
14826
|
this.destroyWidget = this.destroyWidget.bind(this);
|
|
14827
|
+
this.identify = this.identify.bind(this);
|
|
14562
14828
|
this.updateConfig = this.updateConfig.bind(this);
|
|
14563
14829
|
}
|
|
14564
14830
|
|
|
@@ -14594,6 +14860,49 @@
|
|
|
14594
14860
|
: undefined,
|
|
14595
14861
|
};
|
|
14596
14862
|
}
|
|
14863
|
+
|
|
14864
|
+
async _syncConfiguredMetadataAfterInit() {
|
|
14865
|
+
if (
|
|
14866
|
+
!this.config.metadata ||
|
|
14867
|
+
this.apiService.identitySyncedToken === this.apiService.sessionToken
|
|
14868
|
+
) {
|
|
14869
|
+
return null;
|
|
14870
|
+
}
|
|
14871
|
+
|
|
14872
|
+
try {
|
|
14873
|
+
return await this.identify(this.config.metadata);
|
|
14874
|
+
} catch (error) {
|
|
14875
|
+
if (this.config.debug) {
|
|
14876
|
+
console.warn('[Product7] Initial identify failed:', error);
|
|
14877
|
+
}
|
|
14878
|
+
return null;
|
|
14879
|
+
}
|
|
14880
|
+
}
|
|
14881
|
+
|
|
14882
|
+
_extractIdentifyConfig(response) {
|
|
14883
|
+
const payload = this._isPlainObject(response?.data)
|
|
14884
|
+
? response.data
|
|
14885
|
+
: response || {};
|
|
14886
|
+
const configPatch = this._isPlainObject(payload.config)
|
|
14887
|
+
? payload.config
|
|
14888
|
+
: {};
|
|
14889
|
+
|
|
14890
|
+
if (payload.last_feedback_at !== undefined) {
|
|
14891
|
+
configPatch.last_feedback_at = payload.last_feedback_at;
|
|
14892
|
+
} else if (payload.lastFeedbackAt !== undefined) {
|
|
14893
|
+
configPatch.last_feedback_at = payload.lastFeedbackAt;
|
|
14894
|
+
}
|
|
14895
|
+
|
|
14896
|
+
return this._omitUndefined(configPatch);
|
|
14897
|
+
}
|
|
14898
|
+
|
|
14899
|
+
_applyIdentityToWidgets(metadata) {
|
|
14900
|
+
for (const widget of this.widgets.values()) {
|
|
14901
|
+
if (typeof widget.applyIdentity === 'function') {
|
|
14902
|
+
widget.applyIdentity(metadata);
|
|
14903
|
+
}
|
|
14904
|
+
}
|
|
14905
|
+
}
|
|
14597
14906
|
};
|
|
14598
14907
|
|
|
14599
14908
|
// --- Identify: transform flat user data into internal format ---
|
|
@@ -14676,9 +14985,21 @@
|
|
|
14676
14985
|
return obj;
|
|
14677
14986
|
}
|
|
14678
14987
|
|
|
14988
|
+
function hasIdentifyMetadata(metadata = {}) {
|
|
14989
|
+
return Object.values(metadata).some((value) => value !== undefined);
|
|
14990
|
+
}
|
|
14991
|
+
|
|
14679
14992
|
// --- Ensure SDK is initialized (shared by widget inits) ---
|
|
14680
14993
|
|
|
14681
14994
|
async function ensureSDK(options) {
|
|
14995
|
+
if (
|
|
14996
|
+
Product7._sdk &&
|
|
14997
|
+
options.organization &&
|
|
14998
|
+
Product7._sdk.config.workspace !== options.organization
|
|
14999
|
+
) {
|
|
15000
|
+
Product7.destroy();
|
|
15001
|
+
}
|
|
15002
|
+
|
|
14682
15003
|
if (Product7._sdk) return Product7._sdk;
|
|
14683
15004
|
|
|
14684
15005
|
if (options.organization) {
|
|
@@ -14721,63 +15042,58 @@
|
|
|
14721
15042
|
async identify(data = {}, callback) {
|
|
14722
15043
|
try {
|
|
14723
15044
|
const transformed = transformIdentifyData(data);
|
|
14724
|
-
Product7._organization =
|
|
15045
|
+
Product7._organization =
|
|
15046
|
+
transformed.workspace || Product7._organization || null;
|
|
14725
15047
|
|
|
14726
15048
|
const config = cleanUndefined({
|
|
14727
|
-
workspace:
|
|
14728
|
-
metadata: transformed.metadata,
|
|
15049
|
+
workspace: Product7._organization,
|
|
14729
15050
|
debug: transformed.debug,
|
|
14730
15051
|
mock: transformed.mock,
|
|
14731
15052
|
env: transformed.env,
|
|
14732
15053
|
apiUrl: transformed.apiUrl,
|
|
14733
15054
|
});
|
|
14734
15055
|
|
|
14735
|
-
|
|
14736
|
-
const
|
|
15056
|
+
let sdk = Product7._sdk;
|
|
15057
|
+
const requiresNewSDK =
|
|
15058
|
+
!sdk || (config.workspace && sdk.config.workspace !== config.workspace);
|
|
14737
15059
|
|
|
14738
|
-
|
|
14739
|
-
|
|
14740
|
-
|
|
14741
|
-
|
|
14742
|
-
if (transformed.metadata && sdk.apiService?.sessionToken) {
|
|
14743
|
-
try {
|
|
14744
|
-
const identifyPayload = {
|
|
14745
|
-
user_id: transformed.metadata.user_id,
|
|
14746
|
-
email: transformed.metadata.email,
|
|
14747
|
-
name: transformed.metadata.name,
|
|
14748
|
-
avatar: transformed.metadata.profile_picture,
|
|
14749
|
-
attributes: transformed.metadata.custom_fields || {},
|
|
14750
|
-
};
|
|
14751
|
-
if (transformed.metadata.company) {
|
|
14752
|
-
identifyPayload.company = transformed.metadata.company;
|
|
14753
|
-
}
|
|
14754
|
-
await sdk.apiService._makeRequest('/widget/identify', {
|
|
14755
|
-
method: 'POST',
|
|
14756
|
-
body: JSON.stringify(identifyPayload),
|
|
14757
|
-
headers: {
|
|
14758
|
-
'Content-Type': 'application/json',
|
|
14759
|
-
Authorization: `Bearer ${sdk.apiService.sessionToken}`,
|
|
14760
|
-
},
|
|
14761
|
-
});
|
|
14762
|
-
} catch (identifyErr) {
|
|
14763
|
-
if (config.debug) {
|
|
14764
|
-
console.warn('[Product7] Attribute sync failed:', identifyErr);
|
|
14765
|
-
}
|
|
15060
|
+
if (requiresNewSDK) {
|
|
15061
|
+
if (Product7._sdk) {
|
|
15062
|
+
Product7.destroy();
|
|
15063
|
+
Product7._organization = config.workspace || null;
|
|
14766
15064
|
}
|
|
15065
|
+
sdk = new Product7$1(config);
|
|
15066
|
+
Product7._sdk = sdk;
|
|
14767
15067
|
}
|
|
14768
15068
|
|
|
15069
|
+
const initData = sdk.initialized
|
|
15070
|
+
? {
|
|
15071
|
+
alreadyInitialized: true,
|
|
15072
|
+
sessionToken: sdk.apiService?.sessionToken,
|
|
15073
|
+
}
|
|
15074
|
+
: await sdk.init();
|
|
15075
|
+
|
|
15076
|
+
const identifyData = hasIdentifyMetadata(transformed.metadata)
|
|
15077
|
+
? await sdk.identify(transformed.metadata)
|
|
15078
|
+
: null;
|
|
15079
|
+
Product7._identified = Boolean(identifyData?.identified);
|
|
15080
|
+
|
|
14769
15081
|
Product7._flushQueue();
|
|
14770
15082
|
|
|
14771
15083
|
if (typeof window !== 'undefined' && typeof CustomEvent !== 'undefined') {
|
|
14772
15084
|
window.dispatchEvent(
|
|
14773
15085
|
new CustomEvent('Product7Ready', {
|
|
14774
|
-
detail: { sdk, config, initData },
|
|
15086
|
+
detail: { sdk, config: sdk.config, initData, identifyData },
|
|
14775
15087
|
})
|
|
14776
15088
|
);
|
|
14777
15089
|
}
|
|
14778
15090
|
|
|
14779
15091
|
if (typeof callback === 'function') callback(null);
|
|
14780
|
-
return
|
|
15092
|
+
return {
|
|
15093
|
+
...initData,
|
|
15094
|
+
identified: Product7._identified,
|
|
15095
|
+
identify: identifyData,
|
|
15096
|
+
};
|
|
14781
15097
|
} catch (error) {
|
|
14782
15098
|
console.error('[Product7] Identify failed:', error);
|
|
14783
15099
|
|
|
@@ -14836,7 +15152,7 @@
|
|
|
14836
15152
|
if (!options.placement) {
|
|
14837
15153
|
widgetOptions.autoShow = false;
|
|
14838
15154
|
widgetOptions.displayMode = 'modal';
|
|
14839
|
-
widgetOptions.
|
|
15155
|
+
widgetOptions.headless = true;
|
|
14840
15156
|
} else {
|
|
14841
15157
|
// Trigger button is always visible when placement is set
|
|
14842
15158
|
widgetOptions.suppressAfterSubmission = false;
|
|
@@ -14844,7 +15160,7 @@
|
|
|
14844
15160
|
}
|
|
14845
15161
|
|
|
14846
15162
|
try {
|
|
14847
|
-
const widget = sdk.
|
|
15163
|
+
const widget = sdk.createFeedbackWidget(widgetOptions);
|
|
14848
15164
|
widget.mount();
|
|
14849
15165
|
|
|
14850
15166
|
if (options.placement) {
|
|
@@ -14883,13 +15199,13 @@
|
|
|
14883
15199
|
if (options.setBoard) {
|
|
14884
15200
|
Product7._feedbackWidget.options.boardName = options.setBoard;
|
|
14885
15201
|
}
|
|
14886
|
-
Product7._feedbackWidget.
|
|
15202
|
+
Product7._feedbackWidget.open();
|
|
14887
15203
|
}
|
|
14888
15204
|
},
|
|
14889
15205
|
|
|
14890
15206
|
closeFeedback() {
|
|
14891
15207
|
if (Product7._feedbackWidget) {
|
|
14892
|
-
Product7._feedbackWidget.
|
|
15208
|
+
Product7._feedbackWidget.close();
|
|
14893
15209
|
}
|
|
14894
15210
|
},
|
|
14895
15211
|
|
|
@@ -14948,7 +15264,7 @@
|
|
|
14948
15264
|
widgetOptions.enabled = true;
|
|
14949
15265
|
|
|
14950
15266
|
try {
|
|
14951
|
-
const widget = sdk.
|
|
15267
|
+
const widget = sdk.createMessengerWidget(widgetOptions);
|
|
14952
15268
|
widget.mount();
|
|
14953
15269
|
widget.show();
|
|
14954
15270
|
|