@product7/product7-js 0.2.5 → 0.2.6

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.
Files changed (3) hide show
  1. package/README.md +114 -133
  2. package/dist/README.md +114 -133
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -1,9 +1,9 @@
1
- # Feedback Widget SDK
1
+ # Product7 JS
2
2
 
3
3
  [![npm version](https://badge.fury.io/js/%40product7%2Fproduct7-js.svg)](https://badge.fury.io/js/%40product7%2Fproduct7-js)
4
4
  [![Bundle Size](https://img.shields.io/bundlephobia/minzip/@product7/product7-js)](https://bundlephobia.com/package/@product7/product7-js)
5
5
 
6
- A lightweight, customizable JavaScript SDK for collecting user feedback on any website. Built for the Product7 feedback platform.
6
+ The official JavaScript SDK for Product7. Collect feedback, chat with users, run surveys, and share changelogs — all through lightweight, embeddable widgets.
7
7
 
8
8
  ---
9
9
 
@@ -30,23 +30,29 @@ A lightweight, customizable JavaScript SDK for collecting user feedback on any w
30
30
 
31
31
  ## Quick Start
32
32
 
33
- ### CDN Installation (Recommended)
33
+ ### CDN Installation
34
34
 
35
35
  ```html
36
- <script src="https://cdn.jsdelivr.net/npm/@product7/product7-js/dist/product7-js.min.js"></script>
36
+ <script src="https://cdn.jsdelivr.net/npm/@product7/product7-js@latest/dist/product7-js.min.js"></script>
37
37
  <script>
38
- const feedback = new Product7({
38
+ const sdk = new window.Product7.Product7SDK({
39
39
  workspace: 'your-workspace-name',
40
- boardName: 'your-board-id',
40
+ metadata: {
41
+ user_id: 'user_123',
42
+ email: 'user@example.com',
43
+ name: 'Jane Doe',
44
+ },
41
45
  });
42
46
 
43
- feedback.init().then(() => {
44
- const widget = feedback.createWidget('button');
45
- widget.mount();
46
- });
47
+ await sdk.init();
48
+
49
+ const widget = sdk.createWidget('button', { position: 'bottom-right' });
50
+ widget.mount();
47
51
  </script>
48
52
  ```
49
53
 
54
+ > `window.Product7.Product7SDK` is the constructable class exposed by the CDN bundle. Do not use `new window.Product7(...)` directly — `window.Product7` is a plain object, not a class.
55
+
50
56
  ### NPM Installation
51
57
 
52
58
  ```bash
@@ -56,32 +62,20 @@ npm install @product7/product7-js
56
62
  ```javascript
57
63
  import { Product7 } from '@product7/product7-js';
58
64
 
59
- const feedback = new Product7({
65
+ const sdk = new Product7({
60
66
  workspace: 'your-workspace-name',
61
- boardName: 'your-board-id',
67
+ metadata: {
68
+ user_id: 'user_123',
69
+ email: 'user@example.com',
70
+ name: 'Jane Doe',
71
+ },
62
72
  });
63
73
 
64
- await feedback.init();
65
- const widget = feedback.createWidget('button');
74
+ await sdk.init();
75
+ const widget = sdk.createWidget('button', { position: 'bottom-right' });
66
76
  widget.mount();
67
77
  ```
68
78
 
69
- ### Auto-Initialization
70
-
71
- ```html
72
- <script>
73
- window.Product7Config = {
74
- workspace: 'your-workspace',
75
- boardName: 'your-board-id',
76
- autoCreate: {
77
- type: 'button',
78
- position: 'bottom-right',
79
- },
80
- };
81
- </script>
82
- <script src="https://cdn.jsdelivr.net/npm/@product7/product7-js/dist/product7-js.min.js"></script>
83
- ```
84
-
85
79
  ---
86
80
 
87
81
  ## Documentation
@@ -98,7 +92,7 @@ widget.mount();
98
92
  **Button Widget with Side Panel**
99
93
 
100
94
  ```javascript
101
- const widget = feedback.createWidget('button', {
95
+ const widget = sdk.createWidget('button', {
102
96
  position: 'bottom-right',
103
97
  displayMode: 'panel', // Slides in from the side
104
98
  size: 'medium',
@@ -109,7 +103,7 @@ widget.mount();
109
103
  **Button Widget with Modal**
110
104
 
111
105
  ```javascript
112
- const widget = feedback.createWidget('button', {
106
+ const widget = sdk.createWidget('button', {
113
107
  position: 'bottom-right',
114
108
  displayMode: 'modal',
115
109
  size: 'large',
@@ -123,14 +117,14 @@ widget.mount();
123
117
  **Inline Widget**
124
118
 
125
119
  ```javascript
126
- const inline = feedback.createWidget('inline');
120
+ const inline = sdk.createWidget('inline');
127
121
  inline.mount('#feedback-container');
128
122
  ```
129
123
 
130
124
  **Messenger Widget**
131
125
 
132
126
  ```javascript
133
- const messenger = feedback.createWidget('messenger', {
127
+ const messenger = sdk.createWidget('messenger', {
134
128
  position: 'bottom-right',
135
129
  theme: 'light',
136
130
  teamName: 'Support',
@@ -165,7 +159,7 @@ messenger.mount();
165
159
  | `position` | string | 'bottom-right' | Button position (see below) |
166
160
  | `backgroundColor` | string | '#ffffff' | Panel/modal background color |
167
161
  | `textColor` | string | '#1F2937' | Text color |
168
- | `primaryColor` | string | ''#21244A | Button and accent color |
162
+ | `primaryColor` | string | '#21244A' | Button and accent color |
169
163
 
170
164
  ### Position Options
171
165
 
@@ -192,11 +186,11 @@ messenger.mount();
192
186
  Instead of predefined themes, use direct color values for full flexibility:
193
187
 
194
188
  ```javascript
195
- const widget = feedback.createWidget('button', {
189
+ const widget = sdk.createWidget('button', {
196
190
  displayMode: 'modal',
197
191
  backgroundColor: '#1a1a2e', // Dark background
198
- textColor: '#ffffff', // White text
199
- primaryColor: '#e94560', // Red accent
192
+ textColor: '#ffffff', // White text
193
+ primaryColor: '#e94560', // Red accent
200
194
  });
201
195
  ```
202
196
 
@@ -213,18 +207,23 @@ This approach works better than predefined themes because:
213
207
  Hide the default floating button and trigger from your own UI:
214
208
 
215
209
  ```javascript
216
- window.Product7.onReady((sdk) => {
217
- const widget = sdk.createWidget('button', {
218
- displayMode: 'modal',
219
- size: 'medium',
220
- });
221
- widget.mount();
222
- widget.hide(); // Hide the floating button
210
+ const sdk = new Product7({
211
+ workspace: 'your-workspace',
212
+ metadata: { user_id: 'user_123', email: 'user@example.com', name: 'Jane Doe' },
213
+ });
223
214
 
224
- // Trigger from your own button
225
- document.getElementById('my-feedback-btn').addEventListener('click', () => {
226
- widget.openPanel();
227
- });
215
+ await sdk.init();
216
+
217
+ const widget = sdk.createWidget('button', {
218
+ displayMode: 'modal',
219
+ size: 'medium',
220
+ });
221
+ widget.mount();
222
+ widget.hide(); // Hide the floating button
223
+
224
+ // Trigger from your own button
225
+ document.getElementById('my-feedback-btn').addEventListener('click', () => {
226
+ widget.openPanel();
228
227
  });
229
228
  ```
230
229
 
@@ -235,14 +234,17 @@ window.Product7.onReady((sdk) => {
235
234
  For development without a backend connection:
236
235
 
237
236
  ```javascript
238
- window.Product7Config = {
237
+ const sdk = new Product7({
239
238
  workspace: 'demo',
240
239
  mock: true, // No backend required
241
240
  metadata: {
242
241
  user_id: 'test_user',
243
242
  email: 'test@example.com',
243
+ name: 'Test User',
244
244
  },
245
- };
245
+ });
246
+
247
+ await sdk.init();
246
248
  ```
247
249
 
248
250
  Mock mode simulates:
@@ -264,9 +266,9 @@ The SDK supports multiple environments for development and production use.
264
266
  ### Production (Default)
265
267
 
266
268
  ```javascript
267
- const feedback = new Product7({
269
+ const sdk = new Product7({
268
270
  workspace: 'your-workspace',
269
- environment: 'production', // Default, can be omitted
271
+ env: 'production', // Default, can be omitted
270
272
  });
271
273
  ```
272
274
 
@@ -278,9 +280,9 @@ const feedback = new Product7({
278
280
  ### Staging
279
281
 
280
282
  ```javascript
281
- const feedback = new Product7({
283
+ const sdk = new Product7({
282
284
  workspace: 'your-workspace',
283
- environment: 'staging',
285
+ env: 'staging',
284
286
  });
285
287
  ```
286
288
 
@@ -294,7 +296,7 @@ const feedback = new Product7({
294
296
  For self-hosted or custom deployments:
295
297
 
296
298
  ```javascript
297
- const feedback = new Product7({
299
+ const sdk = new Product7({
298
300
  workspace: 'your-workspace',
299
301
  apiUrl: 'https://your-custom-api.com/api/v1',
300
302
  });
@@ -308,8 +310,7 @@ Configuration values merge in this order (later overrides earlier):
308
310
 
309
311
  1. **Default values** — Built-in SDK defaults
310
312
  2. **Backend config** — Returned from `/widget/init` API
311
- 3. **SDK config** — `window.Product7Config`
312
- 4. **Widget options** — Passed to `createWidget()`
313
+ 3. **Widget options** — Passed to `createWidget()`
313
314
 
314
315
  This allows backend-managed defaults while permitting per-widget customization.
315
316
 
@@ -318,11 +319,11 @@ This allows backend-managed defaults while permitting per-widget customization.
318
319
  ## Events
319
320
 
320
321
  ```javascript
321
- feedback.eventBus.on('feedback:submitted', (data) => {
322
+ sdk.eventBus.on('feedback:submitted', (data) => {
322
323
  console.log('Feedback submitted:', data);
323
324
  });
324
325
 
325
- feedback.eventBus.on('feedback:error', (error) => {
326
+ sdk.eventBus.on('feedback:error', (error) => {
326
327
  console.error('Submission failed:', error);
327
328
  });
328
329
  ```
@@ -404,7 +405,7 @@ The SDK includes a full-featured messenger widget for real-time customer convers
404
405
  ### Quick Start
405
406
 
406
407
  ```javascript
407
- const feedback = new Product7({
408
+ const sdk = new Product7({
408
409
  workspace: 'your-workspace',
409
410
  metadata: {
410
411
  user_id: 'user_123',
@@ -413,9 +414,9 @@ const feedback = new Product7({
413
414
  },
414
415
  });
415
416
 
416
- await feedback.init();
417
+ await sdk.init();
417
418
 
418
- const messenger = feedback.createWidget('messenger', {
419
+ const messenger = sdk.createWidget('messenger', {
419
420
  position: 'bottom-right',
420
421
  theme: 'light',
421
422
  teamName: 'Support Team',
@@ -486,16 +487,16 @@ messenger.setUnreadCount(3);
486
487
 
487
488
  ```javascript
488
489
  // Message sent
489
- feedback.eventBus.on('messenger:messageSent', (data) => {
490
+ sdk.eventBus.on('messenger:messageSent', (data) => {
490
491
  console.log('Message sent:', data.message);
491
492
  });
492
493
 
493
494
  // Messenger opened/closed
494
- feedback.eventBus.on('messenger:opened', () => {
495
+ sdk.eventBus.on('messenger:opened', () => {
495
496
  console.log('Messenger opened');
496
497
  });
497
498
 
498
- feedback.eventBus.on('messenger:closed', () => {
499
+ sdk.eventBus.on('messenger:closed', () => {
499
500
  console.log('Messenger closed');
500
501
  });
501
502
  ```
@@ -524,13 +525,13 @@ The SDK automatically detects the environment based on the hostname:
524
525
 
525
526
  ```javascript
526
527
  // Auto-detection (recommended)
527
- const feedback = new Product7({
528
+ const sdk = new Product7({
528
529
  workspace: 'your-workspace',
529
530
  // env is auto-detected from window.location.hostname
530
531
  });
531
532
 
532
533
  // Manual override
533
- const feedback = new Product7({
534
+ const sdk = new Product7({
534
535
  workspace: 'your-workspace',
535
536
  env: 'staging', // Force staging environment
536
537
  });
@@ -554,18 +555,21 @@ The SDK includes a powerful survey widget for collecting structured user feedbac
554
555
  ### Quick Start
555
556
 
556
557
  ```javascript
557
- const feedback = new Product7({
558
+ const sdk = new Product7({
558
559
  workspace: 'your-workspace',
559
- boardName: 'your-board-id',
560
+ metadata: {
561
+ user_id: 'user_123',
562
+ email: 'user@example.com',
563
+ name: 'Jane Doe',
564
+ },
560
565
  });
561
566
 
562
- await feedback.init();
567
+ await sdk.init();
563
568
 
564
569
  // Show NPS survey
565
- feedback.showSurvey({
570
+ sdk.showSurvey({
566
571
  surveyType: 'nps',
567
- description:
568
- 'To what extent do you agree or disagree that our tools support the work you do?',
572
+ description: 'To what extent do you agree or disagree that our tools support the work you do?',
569
573
  ratingScale: 5,
570
574
  showTitle: false,
571
575
  showDescription: true,
@@ -581,22 +585,22 @@ feedback.showSurvey({
581
585
  ### Survey Configuration Options
582
586
 
583
587
  ```javascript
584
- feedback.showSurvey({
588
+ sdk.showSurvey({
585
589
  surveyId: 'backend-survey-id', // Optional: links response to backend survey
586
- surveyType: 'nps', // 'nps' | 'csat' | 'ces' | 'custom'
587
- position: 'bottom-right', // 'bottom-right' | 'bottom-left' | 'center' | 'bottom'
588
- theme: 'light', // 'light' | 'dark'
590
+ surveyType: 'nps', // 'nps' | 'csat' | 'ces' | 'custom'
591
+ position: 'bottom-right', // 'bottom-right' | 'bottom-left' | 'center' | 'bottom'
592
+ theme: 'light', // 'light' | 'dark'
589
593
  title: 'Your survey title',
590
594
  description: 'Optional description',
591
- ratingScale: 5, // NPS scale (default 5, set 11 for 0-10)
592
- showTitle: false, // default false for single-step rating surveys
593
- showDescription: true, // default true for single-step rating surveys
594
- showFeedbackInput: false, // default false for single-step rating surveys
595
- showSubmitButton: false, // default false for single-step rating surveys
596
- autoSubmitOnSelect: true, // default true for single-step rating surveys
597
- lowLabel: 'Not likely', // Low end label (NPS/CES)
598
- highLabel: 'Very likely', // High end label (NPS/CES)
599
- customQuestions: [], // For custom surveys
595
+ ratingScale: 5, // NPS scale (default 5, set 11 for 0-10)
596
+ showTitle: false, // default false for single-step rating surveys
597
+ showDescription: true, // default true for single-step rating surveys
598
+ showFeedbackInput: false, // default false for single-step rating surveys
599
+ showSubmitButton: false, // default false for single-step rating surveys
600
+ autoSubmitOnSelect: true, // default true for single-step rating surveys
601
+ lowLabel: 'Not likely', // Low end label (NPS/CES)
602
+ highLabel: 'Very likely', // High end label (NPS/CES)
603
+ customQuestions: [], // For custom surveys
600
604
  onSubmit: (response) => {},
601
605
  onDismiss: () => {},
602
606
  });
@@ -610,8 +614,8 @@ For surveys configured in the Product7 dashboard, use `showSurveyById()` to fetc
610
614
 
611
615
  ```javascript
612
616
  // Show a specific survey by its backend ID
613
- await feedback.showSurveyById('survey_abc123', {
614
- position: 'center', // Override position if needed
617
+ await sdk.showSurveyById('survey_abc123', {
618
+ position: 'center',
615
619
  onSubmit: (response) => {
616
620
  console.log('Survey completed:', response);
617
621
  },
@@ -624,29 +628,17 @@ Retrieve surveys that match the current user's targeting criteria:
624
628
 
625
629
  ```javascript
626
630
  // Get all active surveys for the current context
627
- const surveys = await feedback.getActiveSurveys();
631
+ const surveys = await sdk.getActiveSurveys({ includeEligibility: true });
628
632
 
629
633
  console.log('Available surveys:', surveys);
630
- // [{ id: 'survey_123', type: 'nps', title: '...', ... }]
634
+ // [{ surveyId: 'survey_123', surveyType: 'nps', title: '...', ... }]
631
635
 
632
636
  // Show the first matching survey
633
637
  if (surveys.length > 0) {
634
- await feedback.showSurveyById(surveys[0].id);
638
+ await sdk.showSurveyById(surveys[0].surveyId, { position: 'center' });
635
639
  }
636
640
  ```
637
641
 
638
- With custom targeting context:
639
-
640
- ```javascript
641
- const surveys = await feedback.getActiveSurveys({
642
- url: '/dashboard/settings', // Override current URL
643
- userProperties: {
644
- plan: 'enterprise',
645
- feature_usage: 'high',
646
- },
647
- });
648
- ```
649
-
650
642
  ---
651
643
 
652
644
  ### Survey Types
@@ -654,10 +646,9 @@ const surveys = await feedback.getActiveSurveys({
654
646
  #### NPS Survey (Net Promoter Score)
655
647
 
656
648
  ```javascript
657
- feedback.showSurvey({
649
+ sdk.showSurvey({
658
650
  surveyType: 'nps',
659
- description:
660
- 'To what extent do you agree or disagree that our tools support the work you do?',
651
+ description: 'To what extent do you agree or disagree that our tools support the work you do?',
661
652
  ratingScale: 5,
662
653
  showTitle: false,
663
654
  showDescription: true,
@@ -677,7 +668,7 @@ feedback.showSurvey({
677
668
  #### CSAT Survey (Customer Satisfaction)
678
669
 
679
670
  ```javascript
680
- feedback.showSurvey({
671
+ sdk.showSurvey({
681
672
  surveyType: 'csat',
682
673
  title: 'How satisfied are you with our service?',
683
674
  position: 'center',
@@ -691,7 +682,7 @@ feedback.showSurvey({
691
682
  #### CES Survey (Customer Effort Score)
692
683
 
693
684
  ```javascript
694
- feedback.showSurvey({
685
+ sdk.showSurvey({
695
686
  surveyType: 'ces',
696
687
  title: 'How easy was it to complete your task?',
697
688
  position: 'bottom',
@@ -704,7 +695,7 @@ feedback.showSurvey({
704
695
  #### Custom Survey
705
696
 
706
697
  ```javascript
707
- feedback.showSurvey({
698
+ sdk.showSurvey({
708
699
  surveyType: 'custom',
709
700
  title: 'Quick Feedback',
710
701
  customQuestions: [
@@ -743,7 +734,7 @@ Trigger surveys based on user actions:
743
734
  document.getElementById('checkout-btn').addEventListener('click', async () => {
744
735
  await processPayment();
745
736
 
746
- feedback.showSurvey({
737
+ sdk.showSurvey({
747
738
  surveyType: 'csat',
748
739
  title: 'How was your checkout experience?',
749
740
  position: 'center',
@@ -752,7 +743,7 @@ document.getElementById('checkout-btn').addEventListener('click', async () => {
752
743
 
753
744
  // After closing support chat
754
745
  chatWidget.on('close', () => {
755
- feedback.showSurvey({
746
+ sdk.showSurvey({
756
747
  surveyType: 'ces',
757
748
  title: 'How easy was it to get help?',
758
749
  position: 'bottom-right',
@@ -763,7 +754,7 @@ chatWidget.on('close', () => {
763
754
  document.addEventListener('mouseleave', (e) => {
764
755
  if (e.clientY < 0 && !sessionStorage.getItem('exit_survey_shown')) {
765
756
  sessionStorage.setItem('exit_survey_shown', 'true');
766
- feedback.showSurvey({
757
+ sdk.showSurvey({
767
758
  surveyType: 'nps',
768
759
  title: 'Before you go...',
769
760
  description: 'How likely are you to recommend us?',
@@ -778,7 +769,7 @@ document.addEventListener('mouseleave', (e) => {
778
769
  ```javascript
779
770
  // Show after 60 seconds on page
780
771
  setTimeout(() => {
781
- feedback.showSurvey({
772
+ sdk.showSurvey({
782
773
  surveyType: 'nps',
783
774
  title: 'Enjoying our product?',
784
775
  position: 'bottom-right',
@@ -790,7 +781,7 @@ const pageViews = parseInt(localStorage.getItem('page_views') || '0') + 1;
790
781
  localStorage.setItem('page_views', pageViews);
791
782
 
792
783
  if (pageViews === 5) {
793
- feedback.showSurvey({
784
+ sdk.showSurvey({
794
785
  surveyType: 'csat',
795
786
  title: 'How are you finding things so far?',
796
787
  });
@@ -825,17 +816,11 @@ function useSurvey() {
825
816
  }, []);
826
817
 
827
818
  const showNPS = (options = {}) => {
828
- sdkRef.current?.showSurvey({
829
- surveyType: 'nps',
830
- ...options,
831
- });
819
+ sdkRef.current?.showSurvey({ surveyType: 'nps', ...options });
832
820
  };
833
821
 
834
822
  const showCSAT = (options = {}) => {
835
- sdkRef.current?.showSurvey({
836
- surveyType: 'csat',
837
- ...options,
838
- });
823
+ sdkRef.current?.showSurvey({ surveyType: 'csat', ...options });
839
824
  };
840
825
 
841
826
  return { showNPS, showCSAT };
@@ -881,13 +866,9 @@ function CheckoutSuccess() {
881
866
  });
882
867
 
883
868
  const showSurvey = (type, options = {}) => {
884
- sdk.value?.showSurvey({
885
- surveyType: type,
886
- ...options,
887
- });
869
+ sdk.value?.showSurvey({ surveyType: type, ...options });
888
870
  };
889
871
 
890
- // Trigger on button click
891
872
  const handleFeedbackClick = () => {
892
873
  showSurvey('nps', {
893
874
  title: 'How likely are you to recommend us?',
@@ -903,13 +884,13 @@ function CheckoutSuccess() {
903
884
 
904
885
  ```javascript
905
886
  // Survey displayed
906
- feedback.eventBus.on('survey:shown', (data) => {
887
+ sdk.eventBus.on('survey:shown', (data) => {
907
888
  console.log('Survey displayed:', data.type);
908
889
  analytics.track('Survey Shown', { type: data.type });
909
890
  });
910
891
 
911
892
  // Survey submitted
912
- feedback.eventBus.on('survey:submitted', (data) => {
893
+ sdk.eventBus.on('survey:submitted', (data) => {
913
894
  console.log('Survey submitted:', data.response);
914
895
  analytics.track('Survey Completed', {
915
896
  type: data.response.type,
@@ -918,7 +899,7 @@ feedback.eventBus.on('survey:submitted', (data) => {
918
899
  });
919
900
 
920
901
  // Survey dismissed without completing
921
- feedback.eventBus.on('survey:dismissed', (data) => {
902
+ sdk.eventBus.on('survey:dismissed', (data) => {
922
903
  console.log('Survey dismissed');
923
904
  analytics.track('Survey Dismissed');
924
905
  });
@@ -972,7 +953,7 @@ feedback.eventBus.on('survey:dismissed', (data) => {
972
953
 
973
954
  ```javascript
974
955
  // Create survey widget for later use
975
- const survey = feedback.createWidget('survey', {
956
+ const survey = sdk.createWidget('survey', {
976
957
  surveyType: 'nps',
977
958
  title: 'Rate us',
978
959
  });
@@ -1008,7 +989,7 @@ function showSurveyWithCooldown(options) {
1008
989
  }
1009
990
 
1010
991
  localStorage.setItem(`survey_${options.surveyType}_shown`, Date.now());
1011
- return feedback.showSurvey(options);
992
+ return sdk.showSurvey(options);
1012
993
  }
1013
994
  ```
1014
995
 
package/dist/README.md CHANGED
@@ -1,9 +1,9 @@
1
- # Feedback Widget SDK
1
+ # Product7 JS
2
2
 
3
3
  [![npm version](https://badge.fury.io/js/%40product7%2Fproduct7-js.svg)](https://badge.fury.io/js/%40product7%2Fproduct7-js)
4
4
  [![Bundle Size](https://img.shields.io/bundlephobia/minzip/@product7/product7-js)](https://bundlephobia.com/package/@product7/product7-js)
5
5
 
6
- A lightweight, customizable JavaScript SDK for collecting user feedback on any website. Built for the Product7 feedback platform.
6
+ The official JavaScript SDK for Product7. Collect feedback, chat with users, run surveys, and share changelogs — all through lightweight, embeddable widgets.
7
7
 
8
8
  ---
9
9
 
@@ -30,23 +30,29 @@ A lightweight, customizable JavaScript SDK for collecting user feedback on any w
30
30
 
31
31
  ## Quick Start
32
32
 
33
- ### CDN Installation (Recommended)
33
+ ### CDN Installation
34
34
 
35
35
  ```html
36
- <script src="https://cdn.jsdelivr.net/npm/@product7/product7-js/dist/product7-js.min.js"></script>
36
+ <script src="https://cdn.jsdelivr.net/npm/@product7/product7-js@latest/dist/product7-js.min.js"></script>
37
37
  <script>
38
- const feedback = new Product7({
38
+ const sdk = new window.Product7.Product7SDK({
39
39
  workspace: 'your-workspace-name',
40
- boardName: 'your-board-id',
40
+ metadata: {
41
+ user_id: 'user_123',
42
+ email: 'user@example.com',
43
+ name: 'Jane Doe',
44
+ },
41
45
  });
42
46
 
43
- feedback.init().then(() => {
44
- const widget = feedback.createWidget('button');
45
- widget.mount();
46
- });
47
+ await sdk.init();
48
+
49
+ const widget = sdk.createWidget('button', { position: 'bottom-right' });
50
+ widget.mount();
47
51
  </script>
48
52
  ```
49
53
 
54
+ > `window.Product7.Product7SDK` is the constructable class exposed by the CDN bundle. Do not use `new window.Product7(...)` directly — `window.Product7` is a plain object, not a class.
55
+
50
56
  ### NPM Installation
51
57
 
52
58
  ```bash
@@ -56,32 +62,20 @@ npm install @product7/product7-js
56
62
  ```javascript
57
63
  import { Product7 } from '@product7/product7-js';
58
64
 
59
- const feedback = new Product7({
65
+ const sdk = new Product7({
60
66
  workspace: 'your-workspace-name',
61
- boardName: 'your-board-id',
67
+ metadata: {
68
+ user_id: 'user_123',
69
+ email: 'user@example.com',
70
+ name: 'Jane Doe',
71
+ },
62
72
  });
63
73
 
64
- await feedback.init();
65
- const widget = feedback.createWidget('button');
74
+ await sdk.init();
75
+ const widget = sdk.createWidget('button', { position: 'bottom-right' });
66
76
  widget.mount();
67
77
  ```
68
78
 
69
- ### Auto-Initialization
70
-
71
- ```html
72
- <script>
73
- window.Product7Config = {
74
- workspace: 'your-workspace',
75
- boardName: 'your-board-id',
76
- autoCreate: {
77
- type: 'button',
78
- position: 'bottom-right',
79
- },
80
- };
81
- </script>
82
- <script src="https://cdn.jsdelivr.net/npm/@product7/product7-js/dist/product7-js.min.js"></script>
83
- ```
84
-
85
79
  ---
86
80
 
87
81
  ## Documentation
@@ -98,7 +92,7 @@ widget.mount();
98
92
  **Button Widget with Side Panel**
99
93
 
100
94
  ```javascript
101
- const widget = feedback.createWidget('button', {
95
+ const widget = sdk.createWidget('button', {
102
96
  position: 'bottom-right',
103
97
  displayMode: 'panel', // Slides in from the side
104
98
  size: 'medium',
@@ -109,7 +103,7 @@ widget.mount();
109
103
  **Button Widget with Modal**
110
104
 
111
105
  ```javascript
112
- const widget = feedback.createWidget('button', {
106
+ const widget = sdk.createWidget('button', {
113
107
  position: 'bottom-right',
114
108
  displayMode: 'modal',
115
109
  size: 'large',
@@ -123,14 +117,14 @@ widget.mount();
123
117
  **Inline Widget**
124
118
 
125
119
  ```javascript
126
- const inline = feedback.createWidget('inline');
120
+ const inline = sdk.createWidget('inline');
127
121
  inline.mount('#feedback-container');
128
122
  ```
129
123
 
130
124
  **Messenger Widget**
131
125
 
132
126
  ```javascript
133
- const messenger = feedback.createWidget('messenger', {
127
+ const messenger = sdk.createWidget('messenger', {
134
128
  position: 'bottom-right',
135
129
  theme: 'light',
136
130
  teamName: 'Support',
@@ -165,7 +159,7 @@ messenger.mount();
165
159
  | `position` | string | 'bottom-right' | Button position (see below) |
166
160
  | `backgroundColor` | string | '#ffffff' | Panel/modal background color |
167
161
  | `textColor` | string | '#1F2937' | Text color |
168
- | `primaryColor` | string | ''#21244A | Button and accent color |
162
+ | `primaryColor` | string | '#21244A' | Button and accent color |
169
163
 
170
164
  ### Position Options
171
165
 
@@ -192,11 +186,11 @@ messenger.mount();
192
186
  Instead of predefined themes, use direct color values for full flexibility:
193
187
 
194
188
  ```javascript
195
- const widget = feedback.createWidget('button', {
189
+ const widget = sdk.createWidget('button', {
196
190
  displayMode: 'modal',
197
191
  backgroundColor: '#1a1a2e', // Dark background
198
- textColor: '#ffffff', // White text
199
- primaryColor: '#e94560', // Red accent
192
+ textColor: '#ffffff', // White text
193
+ primaryColor: '#e94560', // Red accent
200
194
  });
201
195
  ```
202
196
 
@@ -213,18 +207,23 @@ This approach works better than predefined themes because:
213
207
  Hide the default floating button and trigger from your own UI:
214
208
 
215
209
  ```javascript
216
- window.Product7.onReady((sdk) => {
217
- const widget = sdk.createWidget('button', {
218
- displayMode: 'modal',
219
- size: 'medium',
220
- });
221
- widget.mount();
222
- widget.hide(); // Hide the floating button
210
+ const sdk = new Product7({
211
+ workspace: 'your-workspace',
212
+ metadata: { user_id: 'user_123', email: 'user@example.com', name: 'Jane Doe' },
213
+ });
223
214
 
224
- // Trigger from your own button
225
- document.getElementById('my-feedback-btn').addEventListener('click', () => {
226
- widget.openPanel();
227
- });
215
+ await sdk.init();
216
+
217
+ const widget = sdk.createWidget('button', {
218
+ displayMode: 'modal',
219
+ size: 'medium',
220
+ });
221
+ widget.mount();
222
+ widget.hide(); // Hide the floating button
223
+
224
+ // Trigger from your own button
225
+ document.getElementById('my-feedback-btn').addEventListener('click', () => {
226
+ widget.openPanel();
228
227
  });
229
228
  ```
230
229
 
@@ -235,14 +234,17 @@ window.Product7.onReady((sdk) => {
235
234
  For development without a backend connection:
236
235
 
237
236
  ```javascript
238
- window.Product7Config = {
237
+ const sdk = new Product7({
239
238
  workspace: 'demo',
240
239
  mock: true, // No backend required
241
240
  metadata: {
242
241
  user_id: 'test_user',
243
242
  email: 'test@example.com',
243
+ name: 'Test User',
244
244
  },
245
- };
245
+ });
246
+
247
+ await sdk.init();
246
248
  ```
247
249
 
248
250
  Mock mode simulates:
@@ -264,9 +266,9 @@ The SDK supports multiple environments for development and production use.
264
266
  ### Production (Default)
265
267
 
266
268
  ```javascript
267
- const feedback = new Product7({
269
+ const sdk = new Product7({
268
270
  workspace: 'your-workspace',
269
- environment: 'production', // Default, can be omitted
271
+ env: 'production', // Default, can be omitted
270
272
  });
271
273
  ```
272
274
 
@@ -278,9 +280,9 @@ const feedback = new Product7({
278
280
  ### Staging
279
281
 
280
282
  ```javascript
281
- const feedback = new Product7({
283
+ const sdk = new Product7({
282
284
  workspace: 'your-workspace',
283
- environment: 'staging',
285
+ env: 'staging',
284
286
  });
285
287
  ```
286
288
 
@@ -294,7 +296,7 @@ const feedback = new Product7({
294
296
  For self-hosted or custom deployments:
295
297
 
296
298
  ```javascript
297
- const feedback = new Product7({
299
+ const sdk = new Product7({
298
300
  workspace: 'your-workspace',
299
301
  apiUrl: 'https://your-custom-api.com/api/v1',
300
302
  });
@@ -308,8 +310,7 @@ Configuration values merge in this order (later overrides earlier):
308
310
 
309
311
  1. **Default values** — Built-in SDK defaults
310
312
  2. **Backend config** — Returned from `/widget/init` API
311
- 3. **SDK config** — `window.Product7Config`
312
- 4. **Widget options** — Passed to `createWidget()`
313
+ 3. **Widget options** — Passed to `createWidget()`
313
314
 
314
315
  This allows backend-managed defaults while permitting per-widget customization.
315
316
 
@@ -318,11 +319,11 @@ This allows backend-managed defaults while permitting per-widget customization.
318
319
  ## Events
319
320
 
320
321
  ```javascript
321
- feedback.eventBus.on('feedback:submitted', (data) => {
322
+ sdk.eventBus.on('feedback:submitted', (data) => {
322
323
  console.log('Feedback submitted:', data);
323
324
  });
324
325
 
325
- feedback.eventBus.on('feedback:error', (error) => {
326
+ sdk.eventBus.on('feedback:error', (error) => {
326
327
  console.error('Submission failed:', error);
327
328
  });
328
329
  ```
@@ -404,7 +405,7 @@ The SDK includes a full-featured messenger widget for real-time customer convers
404
405
  ### Quick Start
405
406
 
406
407
  ```javascript
407
- const feedback = new Product7({
408
+ const sdk = new Product7({
408
409
  workspace: 'your-workspace',
409
410
  metadata: {
410
411
  user_id: 'user_123',
@@ -413,9 +414,9 @@ const feedback = new Product7({
413
414
  },
414
415
  });
415
416
 
416
- await feedback.init();
417
+ await sdk.init();
417
418
 
418
- const messenger = feedback.createWidget('messenger', {
419
+ const messenger = sdk.createWidget('messenger', {
419
420
  position: 'bottom-right',
420
421
  theme: 'light',
421
422
  teamName: 'Support Team',
@@ -486,16 +487,16 @@ messenger.setUnreadCount(3);
486
487
 
487
488
  ```javascript
488
489
  // Message sent
489
- feedback.eventBus.on('messenger:messageSent', (data) => {
490
+ sdk.eventBus.on('messenger:messageSent', (data) => {
490
491
  console.log('Message sent:', data.message);
491
492
  });
492
493
 
493
494
  // Messenger opened/closed
494
- feedback.eventBus.on('messenger:opened', () => {
495
+ sdk.eventBus.on('messenger:opened', () => {
495
496
  console.log('Messenger opened');
496
497
  });
497
498
 
498
- feedback.eventBus.on('messenger:closed', () => {
499
+ sdk.eventBus.on('messenger:closed', () => {
499
500
  console.log('Messenger closed');
500
501
  });
501
502
  ```
@@ -524,13 +525,13 @@ The SDK automatically detects the environment based on the hostname:
524
525
 
525
526
  ```javascript
526
527
  // Auto-detection (recommended)
527
- const feedback = new Product7({
528
+ const sdk = new Product7({
528
529
  workspace: 'your-workspace',
529
530
  // env is auto-detected from window.location.hostname
530
531
  });
531
532
 
532
533
  // Manual override
533
- const feedback = new Product7({
534
+ const sdk = new Product7({
534
535
  workspace: 'your-workspace',
535
536
  env: 'staging', // Force staging environment
536
537
  });
@@ -554,18 +555,21 @@ The SDK includes a powerful survey widget for collecting structured user feedbac
554
555
  ### Quick Start
555
556
 
556
557
  ```javascript
557
- const feedback = new Product7({
558
+ const sdk = new Product7({
558
559
  workspace: 'your-workspace',
559
- boardName: 'your-board-id',
560
+ metadata: {
561
+ user_id: 'user_123',
562
+ email: 'user@example.com',
563
+ name: 'Jane Doe',
564
+ },
560
565
  });
561
566
 
562
- await feedback.init();
567
+ await sdk.init();
563
568
 
564
569
  // Show NPS survey
565
- feedback.showSurvey({
570
+ sdk.showSurvey({
566
571
  surveyType: 'nps',
567
- description:
568
- 'To what extent do you agree or disagree that our tools support the work you do?',
572
+ description: 'To what extent do you agree or disagree that our tools support the work you do?',
569
573
  ratingScale: 5,
570
574
  showTitle: false,
571
575
  showDescription: true,
@@ -581,22 +585,22 @@ feedback.showSurvey({
581
585
  ### Survey Configuration Options
582
586
 
583
587
  ```javascript
584
- feedback.showSurvey({
588
+ sdk.showSurvey({
585
589
  surveyId: 'backend-survey-id', // Optional: links response to backend survey
586
- surveyType: 'nps', // 'nps' | 'csat' | 'ces' | 'custom'
587
- position: 'bottom-right', // 'bottom-right' | 'bottom-left' | 'center' | 'bottom'
588
- theme: 'light', // 'light' | 'dark'
590
+ surveyType: 'nps', // 'nps' | 'csat' | 'ces' | 'custom'
591
+ position: 'bottom-right', // 'bottom-right' | 'bottom-left' | 'center' | 'bottom'
592
+ theme: 'light', // 'light' | 'dark'
589
593
  title: 'Your survey title',
590
594
  description: 'Optional description',
591
- ratingScale: 5, // NPS scale (default 5, set 11 for 0-10)
592
- showTitle: false, // default false for single-step rating surveys
593
- showDescription: true, // default true for single-step rating surveys
594
- showFeedbackInput: false, // default false for single-step rating surveys
595
- showSubmitButton: false, // default false for single-step rating surveys
596
- autoSubmitOnSelect: true, // default true for single-step rating surveys
597
- lowLabel: 'Not likely', // Low end label (NPS/CES)
598
- highLabel: 'Very likely', // High end label (NPS/CES)
599
- customQuestions: [], // For custom surveys
595
+ ratingScale: 5, // NPS scale (default 5, set 11 for 0-10)
596
+ showTitle: false, // default false for single-step rating surveys
597
+ showDescription: true, // default true for single-step rating surveys
598
+ showFeedbackInput: false, // default false for single-step rating surveys
599
+ showSubmitButton: false, // default false for single-step rating surveys
600
+ autoSubmitOnSelect: true, // default true for single-step rating surveys
601
+ lowLabel: 'Not likely', // Low end label (NPS/CES)
602
+ highLabel: 'Very likely', // High end label (NPS/CES)
603
+ customQuestions: [], // For custom surveys
600
604
  onSubmit: (response) => {},
601
605
  onDismiss: () => {},
602
606
  });
@@ -610,8 +614,8 @@ For surveys configured in the Product7 dashboard, use `showSurveyById()` to fetc
610
614
 
611
615
  ```javascript
612
616
  // Show a specific survey by its backend ID
613
- await feedback.showSurveyById('survey_abc123', {
614
- position: 'center', // Override position if needed
617
+ await sdk.showSurveyById('survey_abc123', {
618
+ position: 'center',
615
619
  onSubmit: (response) => {
616
620
  console.log('Survey completed:', response);
617
621
  },
@@ -624,29 +628,17 @@ Retrieve surveys that match the current user's targeting criteria:
624
628
 
625
629
  ```javascript
626
630
  // Get all active surveys for the current context
627
- const surveys = await feedback.getActiveSurveys();
631
+ const surveys = await sdk.getActiveSurveys({ includeEligibility: true });
628
632
 
629
633
  console.log('Available surveys:', surveys);
630
- // [{ id: 'survey_123', type: 'nps', title: '...', ... }]
634
+ // [{ surveyId: 'survey_123', surveyType: 'nps', title: '...', ... }]
631
635
 
632
636
  // Show the first matching survey
633
637
  if (surveys.length > 0) {
634
- await feedback.showSurveyById(surveys[0].id);
638
+ await sdk.showSurveyById(surveys[0].surveyId, { position: 'center' });
635
639
  }
636
640
  ```
637
641
 
638
- With custom targeting context:
639
-
640
- ```javascript
641
- const surveys = await feedback.getActiveSurveys({
642
- url: '/dashboard/settings', // Override current URL
643
- userProperties: {
644
- plan: 'enterprise',
645
- feature_usage: 'high',
646
- },
647
- });
648
- ```
649
-
650
642
  ---
651
643
 
652
644
  ### Survey Types
@@ -654,10 +646,9 @@ const surveys = await feedback.getActiveSurveys({
654
646
  #### NPS Survey (Net Promoter Score)
655
647
 
656
648
  ```javascript
657
- feedback.showSurvey({
649
+ sdk.showSurvey({
658
650
  surveyType: 'nps',
659
- description:
660
- 'To what extent do you agree or disagree that our tools support the work you do?',
651
+ description: 'To what extent do you agree or disagree that our tools support the work you do?',
661
652
  ratingScale: 5,
662
653
  showTitle: false,
663
654
  showDescription: true,
@@ -677,7 +668,7 @@ feedback.showSurvey({
677
668
  #### CSAT Survey (Customer Satisfaction)
678
669
 
679
670
  ```javascript
680
- feedback.showSurvey({
671
+ sdk.showSurvey({
681
672
  surveyType: 'csat',
682
673
  title: 'How satisfied are you with our service?',
683
674
  position: 'center',
@@ -691,7 +682,7 @@ feedback.showSurvey({
691
682
  #### CES Survey (Customer Effort Score)
692
683
 
693
684
  ```javascript
694
- feedback.showSurvey({
685
+ sdk.showSurvey({
695
686
  surveyType: 'ces',
696
687
  title: 'How easy was it to complete your task?',
697
688
  position: 'bottom',
@@ -704,7 +695,7 @@ feedback.showSurvey({
704
695
  #### Custom Survey
705
696
 
706
697
  ```javascript
707
- feedback.showSurvey({
698
+ sdk.showSurvey({
708
699
  surveyType: 'custom',
709
700
  title: 'Quick Feedback',
710
701
  customQuestions: [
@@ -743,7 +734,7 @@ Trigger surveys based on user actions:
743
734
  document.getElementById('checkout-btn').addEventListener('click', async () => {
744
735
  await processPayment();
745
736
 
746
- feedback.showSurvey({
737
+ sdk.showSurvey({
747
738
  surveyType: 'csat',
748
739
  title: 'How was your checkout experience?',
749
740
  position: 'center',
@@ -752,7 +743,7 @@ document.getElementById('checkout-btn').addEventListener('click', async () => {
752
743
 
753
744
  // After closing support chat
754
745
  chatWidget.on('close', () => {
755
- feedback.showSurvey({
746
+ sdk.showSurvey({
756
747
  surveyType: 'ces',
757
748
  title: 'How easy was it to get help?',
758
749
  position: 'bottom-right',
@@ -763,7 +754,7 @@ chatWidget.on('close', () => {
763
754
  document.addEventListener('mouseleave', (e) => {
764
755
  if (e.clientY < 0 && !sessionStorage.getItem('exit_survey_shown')) {
765
756
  sessionStorage.setItem('exit_survey_shown', 'true');
766
- feedback.showSurvey({
757
+ sdk.showSurvey({
767
758
  surveyType: 'nps',
768
759
  title: 'Before you go...',
769
760
  description: 'How likely are you to recommend us?',
@@ -778,7 +769,7 @@ document.addEventListener('mouseleave', (e) => {
778
769
  ```javascript
779
770
  // Show after 60 seconds on page
780
771
  setTimeout(() => {
781
- feedback.showSurvey({
772
+ sdk.showSurvey({
782
773
  surveyType: 'nps',
783
774
  title: 'Enjoying our product?',
784
775
  position: 'bottom-right',
@@ -790,7 +781,7 @@ const pageViews = parseInt(localStorage.getItem('page_views') || '0') + 1;
790
781
  localStorage.setItem('page_views', pageViews);
791
782
 
792
783
  if (pageViews === 5) {
793
- feedback.showSurvey({
784
+ sdk.showSurvey({
794
785
  surveyType: 'csat',
795
786
  title: 'How are you finding things so far?',
796
787
  });
@@ -825,17 +816,11 @@ function useSurvey() {
825
816
  }, []);
826
817
 
827
818
  const showNPS = (options = {}) => {
828
- sdkRef.current?.showSurvey({
829
- surveyType: 'nps',
830
- ...options,
831
- });
819
+ sdkRef.current?.showSurvey({ surveyType: 'nps', ...options });
832
820
  };
833
821
 
834
822
  const showCSAT = (options = {}) => {
835
- sdkRef.current?.showSurvey({
836
- surveyType: 'csat',
837
- ...options,
838
- });
823
+ sdkRef.current?.showSurvey({ surveyType: 'csat', ...options });
839
824
  };
840
825
 
841
826
  return { showNPS, showCSAT };
@@ -881,13 +866,9 @@ function CheckoutSuccess() {
881
866
  });
882
867
 
883
868
  const showSurvey = (type, options = {}) => {
884
- sdk.value?.showSurvey({
885
- surveyType: type,
886
- ...options,
887
- });
869
+ sdk.value?.showSurvey({ surveyType: type, ...options });
888
870
  };
889
871
 
890
- // Trigger on button click
891
872
  const handleFeedbackClick = () => {
892
873
  showSurvey('nps', {
893
874
  title: 'How likely are you to recommend us?',
@@ -903,13 +884,13 @@ function CheckoutSuccess() {
903
884
 
904
885
  ```javascript
905
886
  // Survey displayed
906
- feedback.eventBus.on('survey:shown', (data) => {
887
+ sdk.eventBus.on('survey:shown', (data) => {
907
888
  console.log('Survey displayed:', data.type);
908
889
  analytics.track('Survey Shown', { type: data.type });
909
890
  });
910
891
 
911
892
  // Survey submitted
912
- feedback.eventBus.on('survey:submitted', (data) => {
893
+ sdk.eventBus.on('survey:submitted', (data) => {
913
894
  console.log('Survey submitted:', data.response);
914
895
  analytics.track('Survey Completed', {
915
896
  type: data.response.type,
@@ -918,7 +899,7 @@ feedback.eventBus.on('survey:submitted', (data) => {
918
899
  });
919
900
 
920
901
  // Survey dismissed without completing
921
- feedback.eventBus.on('survey:dismissed', (data) => {
902
+ sdk.eventBus.on('survey:dismissed', (data) => {
922
903
  console.log('Survey dismissed');
923
904
  analytics.track('Survey Dismissed');
924
905
  });
@@ -972,7 +953,7 @@ feedback.eventBus.on('survey:dismissed', (data) => {
972
953
 
973
954
  ```javascript
974
955
  // Create survey widget for later use
975
- const survey = feedback.createWidget('survey', {
956
+ const survey = sdk.createWidget('survey', {
976
957
  surveyType: 'nps',
977
958
  title: 'Rate us',
978
959
  });
@@ -1008,7 +989,7 @@ function showSurveyWithCooldown(options) {
1008
989
  }
1009
990
 
1010
991
  localStorage.setItem(`survey_${options.surveyType}_shown`, Date.now());
1011
- return feedback.showSurvey(options);
992
+ return sdk.showSurvey(options);
1012
993
  }
1013
994
  ```
1014
995
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@product7/product7-js",
3
- "version": "0.2.5",
3
+ "version": "0.2.6",
4
4
  "description": "JavaScript SDK for integrating Product7 feedback widgets into any website",
5
5
  "main": "dist/product7-js.js",
6
6
  "module": "src/index.js",