@product7/feedback-sdk 1.1.8 → 1.2.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/README.md +456 -0
- package/dist/README.md +456 -0
- package/dist/feedback-sdk.js +5255 -941
- 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/core/APIService.js +272 -0
- package/src/core/FeedbackSDK.js +70 -1
- package/src/index.js +5 -1
- package/src/styles/messengerStyles.js +1657 -0
- package/src/styles/styles.js +96 -1
- package/src/widgets/BaseWidget.js +1 -1
- package/src/widgets/ButtonWidget.js +84 -49
- package/src/widgets/MessengerWidget.js +441 -0
- package/src/widgets/SurveyWidget.js +24 -8
- package/src/widgets/WidgetFactory.js +2 -0
- package/src/widgets/messenger/MessengerState.js +222 -0
- package/src/widgets/messenger/components/MessengerLauncher.js +119 -0
- package/src/widgets/messenger/components/MessengerPanel.js +130 -0
- package/src/widgets/messenger/components/NavigationTabs.js +134 -0
- package/src/widgets/messenger/views/ChangelogView.js +198 -0
- package/src/widgets/messenger/views/ChatView.js +284 -0
- package/src/widgets/messenger/views/ConversationsView.js +223 -0
- package/src/widgets/messenger/views/HelpView.js +191 -0
- package/src/widgets/messenger/views/HomeView.js +224 -0
- package/types/index.d.ts +129 -67
package/README.md
CHANGED
|
@@ -368,6 +368,462 @@ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file
|
|
|
368
368
|
|
|
369
369
|
---
|
|
370
370
|
|
|
371
|
+
## Survey Widget
|
|
372
|
+
|
|
373
|
+
The SDK includes a powerful survey widget for collecting structured user feedback through NPS, CSAT, CES, and custom surveys. Surveys can be triggered manually, on specific events, or managed through the backend dashboard.
|
|
374
|
+
|
|
375
|
+
### Survey Types
|
|
376
|
+
|
|
377
|
+
| Type | Description | Scale |
|
|
378
|
+
| ---------- | --------------------- | ------------------------ |
|
|
379
|
+
| **NPS** | Net Promoter Score | 0-10 numeric scale |
|
|
380
|
+
| **CSAT** | Customer Satisfaction | 5-point emoji scale |
|
|
381
|
+
| **CES** | Customer Effort Score | 5-level difficulty scale |
|
|
382
|
+
| **Custom** | Multi-question forms | Flexible input types |
|
|
383
|
+
|
|
384
|
+
### Quick Start
|
|
385
|
+
|
|
386
|
+
```javascript
|
|
387
|
+
const feedback = new FeedbackSDK({
|
|
388
|
+
workspace: 'your-workspace',
|
|
389
|
+
boardId: 'your-board-id',
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
await feedback.init();
|
|
393
|
+
|
|
394
|
+
// Show NPS survey
|
|
395
|
+
feedback.showSurvey({
|
|
396
|
+
surveyType: 'nps',
|
|
397
|
+
title: 'How likely are you to recommend us?',
|
|
398
|
+
onSubmit: (response) => {
|
|
399
|
+
console.log('Survey submitted:', response);
|
|
400
|
+
},
|
|
401
|
+
});
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
### Survey Configuration Options
|
|
405
|
+
|
|
406
|
+
```javascript
|
|
407
|
+
feedback.showSurvey({
|
|
408
|
+
surveyId: 'backend-survey-id', // Optional: links response to backend survey
|
|
409
|
+
surveyType: 'nps', // 'nps' | 'csat' | 'ces' | 'custom'
|
|
410
|
+
position: 'bottom-right', // 'bottom-right' | 'bottom-left' | 'center' | 'bottom'
|
|
411
|
+
theme: 'light', // 'light' | 'dark'
|
|
412
|
+
title: 'Your survey title',
|
|
413
|
+
description: 'Optional description',
|
|
414
|
+
lowLabel: 'Not likely', // Low end label (NPS/CES)
|
|
415
|
+
highLabel: 'Very likely', // High end label (NPS/CES)
|
|
416
|
+
customQuestions: [], // For custom surveys
|
|
417
|
+
onSubmit: (response) => {},
|
|
418
|
+
onDismiss: () => {},
|
|
419
|
+
});
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
---
|
|
423
|
+
|
|
424
|
+
### Backend-Driven Surveys
|
|
425
|
+
|
|
426
|
+
For surveys configured in the Product7 dashboard, use `showSurveyById()` to fetch and display them:
|
|
427
|
+
|
|
428
|
+
```javascript
|
|
429
|
+
// Show a specific survey by its backend ID
|
|
430
|
+
await feedback.showSurveyById('survey_abc123', {
|
|
431
|
+
position: 'center', // Override position if needed
|
|
432
|
+
onSubmit: (response) => {
|
|
433
|
+
console.log('Survey completed:', response);
|
|
434
|
+
},
|
|
435
|
+
});
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
### Fetching Active Surveys
|
|
439
|
+
|
|
440
|
+
Retrieve surveys that match the current user's targeting criteria:
|
|
441
|
+
|
|
442
|
+
```javascript
|
|
443
|
+
// Get all active surveys for the current context
|
|
444
|
+
const surveys = await feedback.getActiveSurveys();
|
|
445
|
+
|
|
446
|
+
console.log('Available surveys:', surveys);
|
|
447
|
+
// [{ id: 'survey_123', type: 'nps', title: '...', ... }]
|
|
448
|
+
|
|
449
|
+
// Show the first matching survey
|
|
450
|
+
if (surveys.length > 0) {
|
|
451
|
+
await feedback.showSurveyById(surveys[0].id);
|
|
452
|
+
}
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
With custom targeting context:
|
|
456
|
+
|
|
457
|
+
```javascript
|
|
458
|
+
const surveys = await feedback.getActiveSurveys({
|
|
459
|
+
url: '/dashboard/settings', // Override current URL
|
|
460
|
+
userProperties: {
|
|
461
|
+
plan: 'enterprise',
|
|
462
|
+
feature_usage: 'high',
|
|
463
|
+
},
|
|
464
|
+
});
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
---
|
|
468
|
+
|
|
469
|
+
### Survey Types
|
|
470
|
+
|
|
471
|
+
#### NPS Survey (Net Promoter Score)
|
|
472
|
+
|
|
473
|
+
```javascript
|
|
474
|
+
feedback.showSurvey({
|
|
475
|
+
surveyType: 'nps',
|
|
476
|
+
title: 'How likely are you to recommend us to a friend?',
|
|
477
|
+
lowLabel: 'Not at all likely',
|
|
478
|
+
highLabel: 'Extremely likely',
|
|
479
|
+
position: 'bottom-right',
|
|
480
|
+
onSubmit: (response) => {
|
|
481
|
+
console.log('Score:', response.score); // 0-10
|
|
482
|
+
console.log('Feedback:', response.feedback);
|
|
483
|
+
},
|
|
484
|
+
});
|
|
485
|
+
```
|
|
486
|
+
|
|
487
|
+
#### CSAT Survey (Customer Satisfaction)
|
|
488
|
+
|
|
489
|
+
```javascript
|
|
490
|
+
feedback.showSurvey({
|
|
491
|
+
surveyType: 'csat',
|
|
492
|
+
title: 'How satisfied are you with our service?',
|
|
493
|
+
position: 'center',
|
|
494
|
+
theme: 'dark',
|
|
495
|
+
onSubmit: (response) => {
|
|
496
|
+
console.log('Satisfaction:', response.score); // 1-5
|
|
497
|
+
},
|
|
498
|
+
});
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
#### CES Survey (Customer Effort Score)
|
|
502
|
+
|
|
503
|
+
```javascript
|
|
504
|
+
feedback.showSurvey({
|
|
505
|
+
surveyType: 'ces',
|
|
506
|
+
title: 'How easy was it to complete your task?',
|
|
507
|
+
position: 'bottom',
|
|
508
|
+
onSubmit: (response) => {
|
|
509
|
+
console.log('Effort score:', response.score); // 1-5
|
|
510
|
+
},
|
|
511
|
+
});
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
#### Custom Survey
|
|
515
|
+
|
|
516
|
+
```javascript
|
|
517
|
+
feedback.showSurvey({
|
|
518
|
+
surveyType: 'custom',
|
|
519
|
+
title: 'Quick Feedback',
|
|
520
|
+
customQuestions: [
|
|
521
|
+
{
|
|
522
|
+
id: 'feature',
|
|
523
|
+
type: 'select',
|
|
524
|
+
label: 'Which feature do you use most?',
|
|
525
|
+
options: [
|
|
526
|
+
{ value: 'dashboard', label: 'Dashboard' },
|
|
527
|
+
{ value: 'reports', label: 'Reports' },
|
|
528
|
+
{ value: 'settings', label: 'Settings' },
|
|
529
|
+
],
|
|
530
|
+
},
|
|
531
|
+
{
|
|
532
|
+
id: 'improvement',
|
|
533
|
+
type: 'text',
|
|
534
|
+
label: 'What could we improve?',
|
|
535
|
+
placeholder: 'Your suggestions...',
|
|
536
|
+
},
|
|
537
|
+
],
|
|
538
|
+
onSubmit: (response) => {
|
|
539
|
+
console.log('Answers:', response.customAnswers);
|
|
540
|
+
// { feature: 'dashboard', improvement: 'Better charts' }
|
|
541
|
+
},
|
|
542
|
+
});
|
|
543
|
+
```
|
|
544
|
+
|
|
545
|
+
---
|
|
546
|
+
|
|
547
|
+
### Event-Triggered Surveys
|
|
548
|
+
|
|
549
|
+
Trigger surveys based on user actions:
|
|
550
|
+
|
|
551
|
+
```javascript
|
|
552
|
+
// After completing a purchase
|
|
553
|
+
document.getElementById('checkout-btn').addEventListener('click', async () => {
|
|
554
|
+
await processPayment();
|
|
555
|
+
|
|
556
|
+
feedback.showSurvey({
|
|
557
|
+
surveyType: 'csat',
|
|
558
|
+
title: 'How was your checkout experience?',
|
|
559
|
+
position: 'center',
|
|
560
|
+
});
|
|
561
|
+
});
|
|
562
|
+
|
|
563
|
+
// After closing support chat
|
|
564
|
+
chatWidget.on('close', () => {
|
|
565
|
+
feedback.showSurvey({
|
|
566
|
+
surveyType: 'ces',
|
|
567
|
+
title: 'How easy was it to get help?',
|
|
568
|
+
position: 'bottom-right',
|
|
569
|
+
});
|
|
570
|
+
});
|
|
571
|
+
|
|
572
|
+
// On page exit intent
|
|
573
|
+
document.addEventListener('mouseleave', (e) => {
|
|
574
|
+
if (e.clientY < 0 && !sessionStorage.getItem('exit_survey_shown')) {
|
|
575
|
+
sessionStorage.setItem('exit_survey_shown', 'true');
|
|
576
|
+
feedback.showSurvey({
|
|
577
|
+
surveyType: 'nps',
|
|
578
|
+
title: 'Before you go...',
|
|
579
|
+
description: 'How likely are you to recommend us?',
|
|
580
|
+
position: 'center',
|
|
581
|
+
});
|
|
582
|
+
}
|
|
583
|
+
});
|
|
584
|
+
```
|
|
585
|
+
|
|
586
|
+
### Time-Based Surveys
|
|
587
|
+
|
|
588
|
+
```javascript
|
|
589
|
+
// Show after 60 seconds on page
|
|
590
|
+
setTimeout(() => {
|
|
591
|
+
feedback.showSurvey({
|
|
592
|
+
surveyType: 'nps',
|
|
593
|
+
title: 'Enjoying our product?',
|
|
594
|
+
position: 'bottom-right',
|
|
595
|
+
});
|
|
596
|
+
}, 60000);
|
|
597
|
+
|
|
598
|
+
// Show after N page views
|
|
599
|
+
const pageViews = parseInt(localStorage.getItem('page_views') || '0') + 1;
|
|
600
|
+
localStorage.setItem('page_views', pageViews);
|
|
601
|
+
|
|
602
|
+
if (pageViews === 5) {
|
|
603
|
+
feedback.showSurvey({
|
|
604
|
+
surveyType: 'csat',
|
|
605
|
+
title: 'How are you finding things so far?',
|
|
606
|
+
});
|
|
607
|
+
}
|
|
608
|
+
```
|
|
609
|
+
|
|
610
|
+
---
|
|
611
|
+
|
|
612
|
+
### React Integration
|
|
613
|
+
|
|
614
|
+
```jsx
|
|
615
|
+
import { useEffect, useRef } from 'react';
|
|
616
|
+
import { FeedbackSDK } from '@product7/feedback-sdk';
|
|
617
|
+
|
|
618
|
+
function useSurvey() {
|
|
619
|
+
const sdkRef = useRef(null);
|
|
620
|
+
|
|
621
|
+
useEffect(() => {
|
|
622
|
+
const sdk = new FeedbackSDK({
|
|
623
|
+
workspace: 'your-workspace',
|
|
624
|
+
userContext: {
|
|
625
|
+
user_id: currentUser.id,
|
|
626
|
+
email: currentUser.email,
|
|
627
|
+
},
|
|
628
|
+
});
|
|
629
|
+
|
|
630
|
+
sdk.init().then(() => {
|
|
631
|
+
sdkRef.current = sdk;
|
|
632
|
+
});
|
|
633
|
+
|
|
634
|
+
return () => sdk.destroy();
|
|
635
|
+
}, []);
|
|
636
|
+
|
|
637
|
+
const showNPS = (options = {}) => {
|
|
638
|
+
sdkRef.current?.showSurvey({
|
|
639
|
+
surveyType: 'nps',
|
|
640
|
+
...options,
|
|
641
|
+
});
|
|
642
|
+
};
|
|
643
|
+
|
|
644
|
+
const showCSAT = (options = {}) => {
|
|
645
|
+
sdkRef.current?.showSurvey({
|
|
646
|
+
surveyType: 'csat',
|
|
647
|
+
...options,
|
|
648
|
+
});
|
|
649
|
+
};
|
|
650
|
+
|
|
651
|
+
return { showNPS, showCSAT };
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
// Usage in component
|
|
655
|
+
function CheckoutSuccess() {
|
|
656
|
+
const { showCSAT } = useSurvey();
|
|
657
|
+
|
|
658
|
+
useEffect(() => {
|
|
659
|
+
showCSAT({
|
|
660
|
+
title: 'How was your checkout experience?',
|
|
661
|
+
position: 'center',
|
|
662
|
+
});
|
|
663
|
+
}, []);
|
|
664
|
+
|
|
665
|
+
return <div>Thank you for your purchase!</div>;
|
|
666
|
+
}
|
|
667
|
+
```
|
|
668
|
+
|
|
669
|
+
### Vue.js Integration
|
|
670
|
+
|
|
671
|
+
```vue
|
|
672
|
+
<script setup>
|
|
673
|
+
import { onMounted, onUnmounted, ref } from 'vue';
|
|
674
|
+
import { FeedbackSDK } from '@product7/feedback-sdk';
|
|
675
|
+
|
|
676
|
+
const sdk = ref(null);
|
|
677
|
+
|
|
678
|
+
onMounted(async () => {
|
|
679
|
+
sdk.value = new FeedbackSDK({
|
|
680
|
+
workspace: 'your-workspace',
|
|
681
|
+
userContext: {
|
|
682
|
+
user_id: currentUser.value.id,
|
|
683
|
+
email: currentUser.value.email,
|
|
684
|
+
},
|
|
685
|
+
});
|
|
686
|
+
await sdk.value.init();
|
|
687
|
+
});
|
|
688
|
+
|
|
689
|
+
onUnmounted(() => {
|
|
690
|
+
sdk.value?.destroy();
|
|
691
|
+
});
|
|
692
|
+
|
|
693
|
+
const showSurvey = (type, options = {}) => {
|
|
694
|
+
sdk.value?.showSurvey({
|
|
695
|
+
surveyType: type,
|
|
696
|
+
...options,
|
|
697
|
+
});
|
|
698
|
+
};
|
|
699
|
+
|
|
700
|
+
// Trigger on button click
|
|
701
|
+
const handleFeedbackClick = () => {
|
|
702
|
+
showSurvey('nps', {
|
|
703
|
+
title: 'How likely are you to recommend us?',
|
|
704
|
+
position: 'center',
|
|
705
|
+
});
|
|
706
|
+
};
|
|
707
|
+
</script>
|
|
708
|
+
```
|
|
709
|
+
|
|
710
|
+
---
|
|
711
|
+
|
|
712
|
+
### Survey Events
|
|
713
|
+
|
|
714
|
+
```javascript
|
|
715
|
+
// Survey displayed
|
|
716
|
+
feedback.eventBus.on('survey:shown', (data) => {
|
|
717
|
+
console.log('Survey displayed:', data.type);
|
|
718
|
+
analytics.track('Survey Shown', { type: data.type });
|
|
719
|
+
});
|
|
720
|
+
|
|
721
|
+
// Survey submitted
|
|
722
|
+
feedback.eventBus.on('survey:submitted', (data) => {
|
|
723
|
+
console.log('Survey submitted:', data.response);
|
|
724
|
+
analytics.track('Survey Completed', {
|
|
725
|
+
type: data.response.type,
|
|
726
|
+
score: data.response.score,
|
|
727
|
+
});
|
|
728
|
+
});
|
|
729
|
+
|
|
730
|
+
// Survey dismissed without completing
|
|
731
|
+
feedback.eventBus.on('survey:dismissed', (data) => {
|
|
732
|
+
console.log('Survey dismissed');
|
|
733
|
+
analytics.track('Survey Dismissed');
|
|
734
|
+
});
|
|
735
|
+
```
|
|
736
|
+
|
|
737
|
+
### Response Data Format
|
|
738
|
+
|
|
739
|
+
```javascript
|
|
740
|
+
// NPS/CSAT/CES response
|
|
741
|
+
{
|
|
742
|
+
type: 'nps',
|
|
743
|
+
score: 9,
|
|
744
|
+
feedback: 'Great product!',
|
|
745
|
+
timestamp: '2025-01-26T10:30:00.000Z'
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
// Custom survey response
|
|
749
|
+
{
|
|
750
|
+
type: 'custom',
|
|
751
|
+
score: null,
|
|
752
|
+
feedback: 'Additional comments here',
|
|
753
|
+
customAnswers: {
|
|
754
|
+
feature: 'dashboard',
|
|
755
|
+
improvement: 'Better mobile support'
|
|
756
|
+
},
|
|
757
|
+
timestamp: '2025-01-26T10:30:00.000Z'
|
|
758
|
+
}
|
|
759
|
+
```
|
|
760
|
+
|
|
761
|
+
---
|
|
762
|
+
|
|
763
|
+
### Position Options
|
|
764
|
+
|
|
765
|
+
| Position | Description |
|
|
766
|
+
| -------------- | ----------------------------- |
|
|
767
|
+
| `bottom-right` | Bottom right corner (default) |
|
|
768
|
+
| `bottom-left` | Bottom left corner |
|
|
769
|
+
| `center` | Centered modal with backdrop |
|
|
770
|
+
| `bottom` | Full-width bottom bar |
|
|
771
|
+
|
|
772
|
+
### Theme Options
|
|
773
|
+
|
|
774
|
+
| Theme | Description |
|
|
775
|
+
| ------- | ------------------------------------- |
|
|
776
|
+
| `light` | White background, dark text (default) |
|
|
777
|
+
| `dark` | Dark background, light text |
|
|
778
|
+
|
|
779
|
+
---
|
|
780
|
+
|
|
781
|
+
### Programmatic Control
|
|
782
|
+
|
|
783
|
+
```javascript
|
|
784
|
+
// Create survey widget for later use
|
|
785
|
+
const survey = feedback.createWidget('survey', {
|
|
786
|
+
surveyType: 'nps',
|
|
787
|
+
title: 'Rate us',
|
|
788
|
+
});
|
|
789
|
+
survey.mount();
|
|
790
|
+
|
|
791
|
+
// Show when ready
|
|
792
|
+
survey.show();
|
|
793
|
+
|
|
794
|
+
// Hide programmatically
|
|
795
|
+
survey.hide();
|
|
796
|
+
|
|
797
|
+
// Destroy when done
|
|
798
|
+
survey.destroy();
|
|
799
|
+
```
|
|
800
|
+
|
|
801
|
+
### Survey Rate Limiting
|
|
802
|
+
|
|
803
|
+
Avoid survey fatigue by tracking when surveys were last shown:
|
|
804
|
+
|
|
805
|
+
```javascript
|
|
806
|
+
const SURVEY_COOLDOWN = 7 * 24 * 60 * 60 * 1000; // 7 days
|
|
807
|
+
|
|
808
|
+
function canShowSurvey(surveyType) {
|
|
809
|
+
const lastShown = localStorage.getItem(`survey_${surveyType}_shown`);
|
|
810
|
+
if (!lastShown) return true;
|
|
811
|
+
return Date.now() - parseInt(lastShown) > SURVEY_COOLDOWN;
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
function showSurveyWithCooldown(options) {
|
|
815
|
+
if (!canShowSurvey(options.surveyType)) {
|
|
816
|
+
console.log('Survey on cooldown');
|
|
817
|
+
return null;
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
localStorage.setItem(`survey_${options.surveyType}_shown`, Date.now());
|
|
821
|
+
return feedback.showSurvey(options);
|
|
822
|
+
}
|
|
823
|
+
```
|
|
824
|
+
|
|
825
|
+
---
|
|
826
|
+
|
|
371
827
|
## Related
|
|
372
828
|
|
|
373
829
|
- [Product7 Platform](https://product7.io)
|