@product7/feedback-sdk 1.6.8 → 1.7.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/docs/survey-test-cases.md +398 -0
- package/dist/feedback-sdk.js +245 -28
- package/dist/feedback-sdk.js.map +1 -1
- package/dist/feedback-sdk.min.js +1 -1
- package/dist/feedback-sdk.min.js.map +1 -1
- package/package.json +1 -1
- package/src/api/mock-data/index.js +157 -16
- package/src/core/FeedbackSDK.js +1 -0
- package/src/docs/framework-integrations.md +1 -0
- package/src/widgets/ChangelogWidget.js +15 -10
- package/src/widgets/SurveyWidget.js +72 -2
- package/types/index.d.ts +1 -0
package/package.json
CHANGED
|
@@ -173,30 +173,171 @@ export const MOCK_HELP_COLLECTIONS = [
|
|
|
173
173
|
export const MOCK_SURVEYS = [
|
|
174
174
|
{
|
|
175
175
|
id: 'mock_nps_survey',
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
description: 'Your feedback helps us improve',
|
|
179
|
-
low_label: 'Not likely',
|
|
180
|
-
high_label: 'Very likely',
|
|
181
|
-
trigger: 'manual',
|
|
176
|
+
name: 'NPS Score',
|
|
177
|
+
slug: 'nps',
|
|
182
178
|
status: 'active',
|
|
179
|
+
trigger_type: 'manual',
|
|
180
|
+
pages: [
|
|
181
|
+
{
|
|
182
|
+
id: 'nps-page-1',
|
|
183
|
+
type: 'rating',
|
|
184
|
+
title: 'How likely are you to recommend us to a friend?',
|
|
185
|
+
description: '',
|
|
186
|
+
placeholder: '',
|
|
187
|
+
rating_config: { scale: 11, low_label: 'Very unlikely', high_label: 'Very likely', survey_type: 'nps' },
|
|
188
|
+
multiple_choice_config: null,
|
|
189
|
+
link_config: null,
|
|
190
|
+
after_this_page: { default: 'end_survey', conditions: [] },
|
|
191
|
+
required: true,
|
|
192
|
+
},
|
|
193
|
+
],
|
|
183
194
|
},
|
|
184
195
|
{
|
|
185
196
|
id: 'mock_csat_survey',
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
description: 'Rate your experience with our product',
|
|
189
|
-
trigger: 'manual',
|
|
197
|
+
name: 'CSAT Survey',
|
|
198
|
+
slug: 'csat',
|
|
190
199
|
status: 'active',
|
|
200
|
+
trigger_type: 'manual',
|
|
201
|
+
pages: [
|
|
202
|
+
{
|
|
203
|
+
id: 'csat-page-1',
|
|
204
|
+
type: 'rating',
|
|
205
|
+
title: 'How satisfied are you with our service?',
|
|
206
|
+
description: '',
|
|
207
|
+
placeholder: '',
|
|
208
|
+
rating_config: { scale: 5, low_label: 'Very dissatisfied', high_label: 'Very satisfied', survey_type: 'emoji' },
|
|
209
|
+
multiple_choice_config: null,
|
|
210
|
+
link_config: null,
|
|
211
|
+
after_this_page: { default: 'end_survey', conditions: [] },
|
|
212
|
+
required: true,
|
|
213
|
+
},
|
|
214
|
+
],
|
|
191
215
|
},
|
|
192
216
|
{
|
|
193
217
|
id: 'mock_ces_survey',
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
218
|
+
name: 'Customer Effort Score',
|
|
219
|
+
slug: 'ces',
|
|
220
|
+
status: 'active',
|
|
221
|
+
trigger_type: 'manual',
|
|
222
|
+
pages: [
|
|
223
|
+
{
|
|
224
|
+
id: 'ces-page-1',
|
|
225
|
+
type: 'rating',
|
|
226
|
+
title: 'How easy was it to use our product?',
|
|
227
|
+
description: '',
|
|
228
|
+
placeholder: '',
|
|
229
|
+
rating_config: { scale: 5, low_label: 'Very difficult', high_label: 'Very easy', survey_type: 'ces' },
|
|
230
|
+
multiple_choice_config: null,
|
|
231
|
+
link_config: null,
|
|
232
|
+
after_this_page: { default: 'end_survey', conditions: [] },
|
|
233
|
+
required: true,
|
|
234
|
+
},
|
|
235
|
+
],
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
id: 'mock_open_question_survey',
|
|
239
|
+
name: 'Open Question',
|
|
240
|
+
slug: 'open-question',
|
|
241
|
+
status: 'active',
|
|
242
|
+
trigger_type: 'manual',
|
|
243
|
+
pages: [
|
|
244
|
+
{
|
|
245
|
+
id: 'open-page-1',
|
|
246
|
+
type: 'text',
|
|
247
|
+
title: 'What could we do better?',
|
|
248
|
+
description: 'Is there anything we could do to make our product better for you?',
|
|
249
|
+
placeholder: 'Type your answer here',
|
|
250
|
+
rating_config: null,
|
|
251
|
+
multiple_choice_config: null,
|
|
252
|
+
link_config: null,
|
|
253
|
+
after_this_page: { default: 'end_survey', conditions: [] },
|
|
254
|
+
required: true,
|
|
255
|
+
},
|
|
256
|
+
],
|
|
257
|
+
},
|
|
258
|
+
{
|
|
259
|
+
id: 'mock_product_idea_poll_survey',
|
|
260
|
+
name: 'Product Idea Poll',
|
|
261
|
+
slug: 'product-idea-poll',
|
|
200
262
|
status: 'active',
|
|
263
|
+
trigger_type: 'manual',
|
|
264
|
+
pages: [
|
|
265
|
+
{
|
|
266
|
+
id: 'poll-page-1',
|
|
267
|
+
type: 'multiple_choice',
|
|
268
|
+
title: 'Which feature should we add next?',
|
|
269
|
+
description: 'Vote on the feature you would like to see next.',
|
|
270
|
+
placeholder: '',
|
|
271
|
+
rating_config: null,
|
|
272
|
+
multiple_choice_config: {
|
|
273
|
+
allow_multiple_selection: false,
|
|
274
|
+
survey_type: 'regular',
|
|
275
|
+
options: [
|
|
276
|
+
{ id: 'opt1', label: 'Better reporting' },
|
|
277
|
+
{ id: 'opt2', label: 'Mobile app' },
|
|
278
|
+
{ id: 'opt3', label: 'Integrations' },
|
|
279
|
+
{ id: 'opt4', label: 'AI features' },
|
|
280
|
+
],
|
|
281
|
+
},
|
|
282
|
+
link_config: null,
|
|
283
|
+
after_this_page: { default: 'end_survey', conditions: [] },
|
|
284
|
+
required: true,
|
|
285
|
+
},
|
|
286
|
+
],
|
|
287
|
+
},
|
|
288
|
+
{
|
|
289
|
+
id: 'mock_pmf_survey',
|
|
290
|
+
name: 'Product Market Fit (PMF)',
|
|
291
|
+
slug: 'pmf',
|
|
292
|
+
status: 'active',
|
|
293
|
+
trigger_type: 'manual',
|
|
294
|
+
pages: [
|
|
295
|
+
{
|
|
296
|
+
id: 'pmf-page-1',
|
|
297
|
+
type: 'multiple_choice',
|
|
298
|
+
title: 'How would you feel if you could no longer use our product?',
|
|
299
|
+
description: '',
|
|
300
|
+
placeholder: '',
|
|
301
|
+
rating_config: null,
|
|
302
|
+
multiple_choice_config: {
|
|
303
|
+
allow_multiple_selection: false,
|
|
304
|
+
survey_type: 'regular',
|
|
305
|
+
options: [
|
|
306
|
+
{ id: 'very_disappointed', label: 'Very disappointed' },
|
|
307
|
+
{ id: 'somewhat_disappointed', label: 'Somewhat disappointed' },
|
|
308
|
+
{ id: 'not_disappointed', label: 'Not disappointed' },
|
|
309
|
+
],
|
|
310
|
+
},
|
|
311
|
+
link_config: null,
|
|
312
|
+
after_this_page: { default: 'end_survey', conditions: [] },
|
|
313
|
+
required: true,
|
|
314
|
+
},
|
|
315
|
+
],
|
|
316
|
+
},
|
|
317
|
+
{
|
|
318
|
+
id: 'mock_user_interview_survey',
|
|
319
|
+
name: 'User Interview Request',
|
|
320
|
+
slug: 'user-interview',
|
|
321
|
+
status: 'active',
|
|
322
|
+
trigger_type: 'manual',
|
|
323
|
+
pages: [
|
|
324
|
+
{
|
|
325
|
+
id: 'interview-page-1',
|
|
326
|
+
type: 'link',
|
|
327
|
+
title: 'Would you like to hop on a quick demo?',
|
|
328
|
+
description: 'We would love to hear your thoughts and answer any questions you have.',
|
|
329
|
+
placeholder: '',
|
|
330
|
+
rating_config: null,
|
|
331
|
+
multiple_choice_config: null,
|
|
332
|
+
link_config: {
|
|
333
|
+
button_text: 'Book a demo',
|
|
334
|
+
link_text: '',
|
|
335
|
+
redirect_url: 'https://example.com',
|
|
336
|
+
open_in: 'new_tab',
|
|
337
|
+
},
|
|
338
|
+
after_this_page: { default: 'end_survey', conditions: [] },
|
|
339
|
+
required: true,
|
|
340
|
+
},
|
|
341
|
+
],
|
|
201
342
|
},
|
|
202
343
|
];
|
package/src/core/FeedbackSDK.js
CHANGED
|
@@ -7,6 +7,7 @@ export class ChangelogWidget extends BaseWidget {
|
|
|
7
7
|
this.isLoading = false;
|
|
8
8
|
this.modalElement = null;
|
|
9
9
|
this.sidebarElement = null;
|
|
10
|
+
this.listModalBackdropElement = null;
|
|
10
11
|
this.currentIndex = 0;
|
|
11
12
|
}
|
|
12
13
|
|
|
@@ -87,10 +88,12 @@ export class ChangelogWidget extends BaseWidget {
|
|
|
87
88
|
}
|
|
88
89
|
|
|
89
90
|
_createModal() {
|
|
90
|
-
this.
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
91
|
+
if (this.options.showBackdrop !== false) {
|
|
92
|
+
this.backdropElement = document.createElement('div');
|
|
93
|
+
this.backdropElement.className = `changelog-modal-backdrop changelog-theme-${this.options.theme || 'light'}`;
|
|
94
|
+
document.body.appendChild(this.backdropElement);
|
|
95
|
+
this.backdropElement.addEventListener('click', () => this.closeModal());
|
|
96
|
+
}
|
|
94
97
|
|
|
95
98
|
this.modalElement = document.createElement('div');
|
|
96
99
|
this.modalElement.className = `changelog-modal changelog-theme-${this.options.theme || 'light'}`;
|
|
@@ -230,12 +233,14 @@ export class ChangelogWidget extends BaseWidget {
|
|
|
230
233
|
}
|
|
231
234
|
|
|
232
235
|
_createListModal() {
|
|
233
|
-
this.
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
this.
|
|
238
|
-
|
|
236
|
+
if (this.options.showBackdrop !== false) {
|
|
237
|
+
this.listModalBackdropElement = document.createElement('div');
|
|
238
|
+
this.listModalBackdropElement.className = `changelog-list-modal-backdrop changelog-theme-${this.options.theme || 'light'}`;
|
|
239
|
+
document.body.appendChild(this.listModalBackdropElement);
|
|
240
|
+
this.listModalBackdropElement.addEventListener('click', () =>
|
|
241
|
+
this.closeSidebar()
|
|
242
|
+
);
|
|
243
|
+
}
|
|
239
244
|
|
|
240
245
|
this.listModalElement = document.createElement('div');
|
|
241
246
|
this.listModalElement.className = `changelog-list-modal changelog-theme-${this.options.theme || 'light'}`;
|
|
@@ -406,6 +406,8 @@ export class SurveyWidget extends BaseWidget {
|
|
|
406
406
|
return this._renderMultipleChoicePage(page);
|
|
407
407
|
case 'text':
|
|
408
408
|
return this._renderTextPage(page);
|
|
409
|
+
case 'link':
|
|
410
|
+
return this._renderLinkPage(page);
|
|
409
411
|
default:
|
|
410
412
|
return this._renderTextPage(page);
|
|
411
413
|
}
|
|
@@ -464,6 +466,21 @@ export class SurveyWidget extends BaseWidget {
|
|
|
464
466
|
`;
|
|
465
467
|
}
|
|
466
468
|
|
|
469
|
+
if (ratingType === 'ces') {
|
|
470
|
+
const cesLabels = ['Very Difficult', 'Difficult', 'Neutral', 'Easy', 'Very Easy'];
|
|
471
|
+
return `
|
|
472
|
+
<div class="feedback-survey-ces" data-page-id="${pageId}">
|
|
473
|
+
${cesLabels
|
|
474
|
+
.map((label, i) => {
|
|
475
|
+
const score = i + 1;
|
|
476
|
+
const selected = currentRating === score ? ' selected' : '';
|
|
477
|
+
return `<button class="feedback-survey-page-rating-btn feedback-survey-ces-btn${selected}" data-page-id="${pageId}" data-score="${score}">${label}</button>`;
|
|
478
|
+
})
|
|
479
|
+
.join('')}
|
|
480
|
+
</div>
|
|
481
|
+
`;
|
|
482
|
+
}
|
|
483
|
+
|
|
467
484
|
if (ratingType === 'emoji' && scale === 5) {
|
|
468
485
|
const emojis = [
|
|
469
486
|
'\uD83D\uDE1E',
|
|
@@ -506,7 +523,9 @@ export class SurveyWidget extends BaseWidget {
|
|
|
506
523
|
page.multipleChoiceConfig || page.multiple_choice_config || {};
|
|
507
524
|
const options = Array.isArray(config.options) ? config.options : [];
|
|
508
525
|
const allowMultiple =
|
|
509
|
-
config.allow_multiple === true ||
|
|
526
|
+
config.allow_multiple === true ||
|
|
527
|
+
config.multiple === true ||
|
|
528
|
+
config.allow_multiple_selection === true;
|
|
510
529
|
const pageAnswer = this.surveyState.pageAnswers[pageId] || {};
|
|
511
530
|
const selectedValues = Array.isArray(pageAnswer.values)
|
|
512
531
|
? pageAnswer.values
|
|
@@ -533,10 +552,36 @@ export class SurveyWidget extends BaseWidget {
|
|
|
533
552
|
const pageId = page.id || `page_${this.surveyState.currentPageIndex}`;
|
|
534
553
|
const pageAnswer = this.surveyState.pageAnswers[pageId] || {};
|
|
535
554
|
const value = pageAnswer.text || '';
|
|
555
|
+
const placeholder = page.placeholder || 'Type your answer...';
|
|
536
556
|
|
|
537
557
|
return `
|
|
538
558
|
<div class="feedback-survey-text-page" data-page-id="${pageId}">
|
|
539
|
-
<textarea class="feedback-survey-page-textarea" data-page-id="${pageId}" placeholder="
|
|
559
|
+
<textarea class="feedback-survey-page-textarea" data-page-id="${pageId}" placeholder="${placeholder}">${value}</textarea>
|
|
560
|
+
</div>
|
|
561
|
+
`;
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
_renderLinkPage(page) {
|
|
565
|
+
const pageId = page.id || `page_${this.surveyState.currentPageIndex}`;
|
|
566
|
+
const config = page.link_config || page.linkConfig || {};
|
|
567
|
+
const buttonText = config.button_text || config.buttonText || 'Click here';
|
|
568
|
+
const linkText = config.link_text || config.linkText || '';
|
|
569
|
+
const redirectUrl = config.redirect_url || config.redirectUrl || '#';
|
|
570
|
+
const openIn = config.open_in || config.openIn || 'new_tab';
|
|
571
|
+
const target = openIn === 'new_tab' ? '_blank' : '_self';
|
|
572
|
+
const pageAnswer = this.surveyState.pageAnswers[pageId] || {};
|
|
573
|
+
const clicked = pageAnswer.clicked === true;
|
|
574
|
+
|
|
575
|
+
return `
|
|
576
|
+
<div class="feedback-survey-link-page" data-page-id="${pageId}">
|
|
577
|
+
${linkText ? `<p class="feedback-survey-link-text">${linkText}</p>` : ''}
|
|
578
|
+
<a class="feedback-survey-link-btn${clicked ? ' selected' : ''}"
|
|
579
|
+
href="${redirectUrl}"
|
|
580
|
+
target="${target}"
|
|
581
|
+
rel="noopener noreferrer"
|
|
582
|
+
data-page-id="${pageId}">
|
|
583
|
+
${buttonText}
|
|
584
|
+
</a>
|
|
540
585
|
</div>
|
|
541
586
|
`;
|
|
542
587
|
}
|
|
@@ -785,6 +830,24 @@ export class SurveyWidget extends BaseWidget {
|
|
|
785
830
|
});
|
|
786
831
|
}
|
|
787
832
|
}
|
|
833
|
+
|
|
834
|
+
if (page.type === 'link') {
|
|
835
|
+
this.surveyElement
|
|
836
|
+
.querySelectorAll('.feedback-survey-link-btn')
|
|
837
|
+
.forEach((btn) => {
|
|
838
|
+
btn.addEventListener('click', () => {
|
|
839
|
+
const pId = btn.dataset.pageId;
|
|
840
|
+
this._setPageAnswer(pId, { clicked: true });
|
|
841
|
+
btn.classList.add('selected');
|
|
842
|
+
|
|
843
|
+
const navigation = page.afterThisPage || page.after_this_page;
|
|
844
|
+
const goesTo = navigation ? navigation.default : null;
|
|
845
|
+
if (!goesTo || goesTo === 'end_survey') {
|
|
846
|
+
setTimeout(() => this._handleSubmit(), 400);
|
|
847
|
+
}
|
|
848
|
+
});
|
|
849
|
+
});
|
|
850
|
+
}
|
|
788
851
|
}
|
|
789
852
|
|
|
790
853
|
_selectNPS(score) {
|
|
@@ -976,6 +1039,13 @@ export class SurveyWidget extends BaseWidget {
|
|
|
976
1039
|
}
|
|
977
1040
|
}
|
|
978
1041
|
|
|
1042
|
+
if (page.type === 'link') {
|
|
1043
|
+
if (page.required && !answer.clicked) {
|
|
1044
|
+
this._showError('Please click the link to continue');
|
|
1045
|
+
return false;
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
|
|
979
1049
|
return true;
|
|
980
1050
|
}
|
|
981
1051
|
|
package/types/index.d.ts
CHANGED
|
@@ -233,6 +233,7 @@ declare module '@product7/feedback-sdk' {
|
|
|
233
233
|
enabled?: boolean;
|
|
234
234
|
position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
|
|
235
235
|
theme?: 'light' | 'dark';
|
|
236
|
+
showBackdrop?: boolean;
|
|
236
237
|
triggerText?: string;
|
|
237
238
|
showBadge?: boolean;
|
|
238
239
|
title?: string;
|