@product7/product7-js 0.1.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.
Files changed (58) hide show
  1. package/README.md +1025 -0
  2. package/dist/README.md +1025 -0
  3. package/dist/product7-js.js +14658 -0
  4. package/dist/product7-js.js.map +1 -0
  5. package/dist/product7-js.min.js +2 -0
  6. package/dist/product7-js.min.js.map +1 -0
  7. package/package.json +114 -0
  8. package/src/api/mock-data/index.js +360 -0
  9. package/src/api/services/ChangelogService.js +28 -0
  10. package/src/api/services/FeedbackService.js +44 -0
  11. package/src/api/services/HelpService.js +50 -0
  12. package/src/api/services/MessengerService.js +279 -0
  13. package/src/api/services/SurveyService.js +127 -0
  14. package/src/api/utils/helpers.js +30 -0
  15. package/src/core/APIService.js +303 -0
  16. package/src/core/BaseAPIService.js +298 -0
  17. package/src/core/EventBus.js +54 -0
  18. package/src/core/Product7.js +812 -0
  19. package/src/core/WebSocketService.js +275 -0
  20. package/src/docs/api.md +226 -0
  21. package/src/docs/example.md +461 -0
  22. package/src/docs/framework-integrations.md +714 -0
  23. package/src/docs/installation.md +281 -0
  24. package/src/index.js +894 -0
  25. package/src/styles/base.js +50 -0
  26. package/src/styles/changelog.js +665 -0
  27. package/src/styles/components.js +553 -0
  28. package/src/styles/design-tokens.js +124 -0
  29. package/src/styles/feedback.js +325 -0
  30. package/src/styles/messenger-components.js +632 -0
  31. package/src/styles/messenger-core.js +233 -0
  32. package/src/styles/messenger-features.js +169 -0
  33. package/src/styles/messenger-views.js +877 -0
  34. package/src/styles/messenger.js +17 -0
  35. package/src/styles/messengerCustomStyles.js +114 -0
  36. package/src/styles/styles.js +26 -0
  37. package/src/styles/survey.js +894 -0
  38. package/src/utils/errors.js +142 -0
  39. package/src/utils/helpers.js +219 -0
  40. package/src/widgets/BaseWidget.js +548 -0
  41. package/src/widgets/ButtonWidget.js +104 -0
  42. package/src/widgets/ChangelogWidget.js +615 -0
  43. package/src/widgets/InlineWidget.js +148 -0
  44. package/src/widgets/MessengerWidget.js +979 -0
  45. package/src/widgets/SurveyWidget.js +1325 -0
  46. package/src/widgets/TabWidget.js +45 -0
  47. package/src/widgets/WidgetFactory.js +70 -0
  48. package/src/widgets/messenger/MessengerState.js +323 -0
  49. package/src/widgets/messenger/components/MessengerLauncher.js +124 -0
  50. package/src/widgets/messenger/components/MessengerPanel.js +111 -0
  51. package/src/widgets/messenger/components/NavigationTabs.js +130 -0
  52. package/src/widgets/messenger/views/ChangelogView.js +167 -0
  53. package/src/widgets/messenger/views/ChatView.js +592 -0
  54. package/src/widgets/messenger/views/ConversationsView.js +244 -0
  55. package/src/widgets/messenger/views/HelpView.js +239 -0
  56. package/src/widgets/messenger/views/HomeView.js +300 -0
  57. package/src/widgets/messenger/views/PreChatFormView.js +109 -0
  58. package/types/index.d.ts +341 -0
package/dist/README.md ADDED
@@ -0,0 +1,1025 @@
1
+ # Feedback Widget SDK
2
+
3
+ [![npm version](https://badge.fury.io/js/%40product7%2Fproduct7-js.svg)](https://badge.fury.io/js/%40product7%2Fproduct7-js)
4
+ [![Bundle Size](https://img.shields.io/bundlephobia/minzip/@product7/product7-js)](https://bundlephobia.com/package/@product7/product7-js)
5
+
6
+ A lightweight, customizable JavaScript SDK for collecting user feedback on any website. Built for the Product7 feedback platform.
7
+
8
+ ---
9
+
10
+ ## Features
11
+
12
+ - **Display modes** — Side panel or centered modal
13
+ - **Size options** — Small, medium, or large widget sizes
14
+ - **Full color customization** — Background, text, and primary colors
15
+ - **Custom triggers** — Use your own buttons instead of floating widget
16
+ - **Mock mode** — Development without backend connection
17
+ - **Multiple positions** — 7 position options including center
18
+ - **Responsive design** — Works on desktop, tablet, and mobile
19
+ - **Easy integration** — Simple JavaScript API, minimal setup
20
+ - **Lightweight** — ~12KB gzipped
21
+ - **TypeScript support** — Full type definitions included
22
+ - **Accessible** — WCAG 2.1 compliant
23
+ - **Secure** — CSP friendly, no `eval()` usage
24
+ - **Messenger widget** — Real-time chat with WebSocket support
25
+ - **Help center** — Integrated help articles and collections
26
+ - **Changelog** — Display product updates and announcements
27
+ - **Environment auto-detection** — Automatic staging/production switching
28
+
29
+ ---
30
+
31
+ ## Quick Start
32
+
33
+ ### CDN Installation (Recommended)
34
+
35
+ ```html
36
+ <script src="https://cdn.jsdelivr.net/npm/@product7/product7-js/dist/product7-js.min.js"></script>
37
+ <script>
38
+ const feedback = new Product7({
39
+ workspace: 'your-workspace-name',
40
+ boardName: 'your-board-id',
41
+ });
42
+
43
+ feedback.init().then(() => {
44
+ const widget = feedback.createWidget('button');
45
+ widget.mount();
46
+ });
47
+ </script>
48
+ ```
49
+
50
+ ### NPM Installation
51
+
52
+ ```bash
53
+ npm install @product7/product7-js
54
+ ```
55
+
56
+ ```javascript
57
+ import { Product7 } from '@product7/product7-js';
58
+
59
+ const feedback = new Product7({
60
+ workspace: 'your-workspace-name',
61
+ boardName: 'your-board-id',
62
+ });
63
+
64
+ await feedback.init();
65
+ const widget = feedback.createWidget('button');
66
+ widget.mount();
67
+ ```
68
+
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
+ ---
86
+
87
+ ## Documentation
88
+
89
+ - [Installation Guide](src/docs/installation.md)
90
+ - [Framework Integrations](src/docs/framework-integrations.md)
91
+ - [API Reference](src/docs/api.md)
92
+ - [Examples](src/docs/example.md)
93
+
94
+ ---
95
+
96
+ ## Widget Types
97
+
98
+ **Button Widget with Side Panel**
99
+
100
+ ```javascript
101
+ const widget = feedback.createWidget('button', {
102
+ position: 'bottom-right',
103
+ displayMode: 'panel', // Slides in from the side
104
+ size: 'medium',
105
+ });
106
+ widget.mount();
107
+ ```
108
+
109
+ **Button Widget with Modal**
110
+
111
+ ```javascript
112
+ const widget = feedback.createWidget('button', {
113
+ position: 'bottom-right',
114
+ displayMode: 'modal',
115
+ size: 'large',
116
+ backgroundColor: '#ffffff',
117
+ textColor: '#1F2937',
118
+ primaryColor: '#21244A',
119
+ });
120
+ widget.mount();
121
+ ```
122
+
123
+ **Inline Widget**
124
+
125
+ ```javascript
126
+ const inline = feedback.createWidget('inline');
127
+ inline.mount('#feedback-container');
128
+ ```
129
+
130
+ **Messenger Widget**
131
+
132
+ ```javascript
133
+ const messenger = feedback.createWidget('messenger', {
134
+ position: 'bottom-right',
135
+ theme: 'light',
136
+ teamName: 'Support',
137
+ enableHelp: true,
138
+ enableChangelog: true,
139
+ });
140
+ messenger.mount();
141
+ ```
142
+
143
+ ---
144
+
145
+ ## Configuration
146
+
147
+ ### SDK Configuration
148
+
149
+ | Option | Type | Required | Default | Description |
150
+ | ----------- | ------- | -------- | ----------- | -------------------------------------- |
151
+ | `workspace` | string | ✅ | - | Your workspace subdomain |
152
+ | `boardName` | string | ❌ | 'general' | Target board for feedback |
153
+ | `metadata` | object | ❌ | null | User identification data |
154
+ | `mock` | boolean | ❌ | false | Enable mock mode for development |
155
+ | `debug` | boolean | ❌ | false | Enable debug logging |
156
+ | `env` | string | ❌ | auto-detect | Environment: 'production' or 'staging' |
157
+ | `apiUrl` | string | ❌ | null | Custom API URL (overrides env) |
158
+
159
+ ### Widget Configuration
160
+
161
+ | Option | Type | Default | Description |
162
+ | ----------------- | ------ | -------------- | ---------------------------------------------- |
163
+ | `displayMode` | string | 'panel' | `'panel'` (side slide) or `'modal'` (centered) |
164
+ | `size` | string | 'medium' | `'small'`, `'medium'`, or `'large'` |
165
+ | `position` | string | 'bottom-right' | Button position (see below) |
166
+ | `backgroundColor` | string | '#ffffff' | Panel/modal background color |
167
+ | `textColor` | string | '#1F2937' | Text color |
168
+ | `primaryColor` | string | ''#21244A | Button and accent color |
169
+
170
+ ### Position Options
171
+
172
+ - `bottom-right` (default)
173
+ - `bottom-left`
174
+ - `top-right`
175
+ - `top-left`
176
+ - `bottom-center`
177
+ - `top-center`
178
+ - `center`
179
+
180
+ ### Size Variants
181
+
182
+ | Size | Modal Width | Panel Width |
183
+ | ------ | ----------- | ----------- |
184
+ | small | 360px | 320px |
185
+ | medium | 480px | 420px |
186
+ | large | 600px | 520px |
187
+
188
+ ---
189
+
190
+ ## Color Customization
191
+
192
+ Instead of predefined themes, use direct color values for full flexibility:
193
+
194
+ ```javascript
195
+ const widget = feedback.createWidget('button', {
196
+ displayMode: 'modal',
197
+ backgroundColor: '#1a1a2e', // Dark background
198
+ textColor: '#ffffff', // White text
199
+ primaryColor: '#e94560', // Red accent
200
+ });
201
+ ```
202
+
203
+ This approach works better than predefined themes because:
204
+
205
+ - Supports any brand color
206
+ - Works with both light and dark designs
207
+ - No restrictions on color combinations
208
+
209
+ ---
210
+
211
+ ## Custom Triggers
212
+
213
+ Hide the default floating button and trigger from your own UI:
214
+
215
+ ```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
223
+
224
+ // Trigger from your own button
225
+ document.getElementById('my-feedback-btn').addEventListener('click', () => {
226
+ widget.openPanel();
227
+ });
228
+ });
229
+ ```
230
+
231
+ ---
232
+
233
+ ## Mock Mode
234
+
235
+ For development without a backend connection:
236
+
237
+ ```javascript
238
+ window.Product7Config = {
239
+ workspace: 'demo',
240
+ mock: true, // No backend required
241
+ metadata: {
242
+ user_id: 'test_user',
243
+ email: 'test@example.com',
244
+ },
245
+ };
246
+ ```
247
+
248
+ Mock mode simulates:
249
+
250
+ - Session initialization
251
+ - Feedback submission (with 500ms delay)
252
+ - Default configuration values
253
+ - Messenger conversations and messages
254
+ - Help articles and collections
255
+ - Changelog entries
256
+ - Agent availability status
257
+
258
+ ---
259
+
260
+ ## Environments
261
+
262
+ The SDK supports multiple environments for development and production use.
263
+
264
+ ### Production (Default)
265
+
266
+ ```javascript
267
+ const feedback = new Product7({
268
+ workspace: 'your-workspace',
269
+ environment: 'production', // Default, can be omitted
270
+ });
271
+ ```
272
+
273
+ **API URLs:**
274
+
275
+ - `https://api.product7.io/api/v1`
276
+ - `https://{workspace}.api.product7.io/api/v1`
277
+
278
+ ### Staging
279
+
280
+ ```javascript
281
+ const feedback = new Product7({
282
+ workspace: 'your-workspace',
283
+ environment: 'staging',
284
+ });
285
+ ```
286
+
287
+ **API URLs:**
288
+
289
+ - `https://staging.api.product7.io/api/v1`
290
+ - `https://{workspace}.staging.api.product7.io/api/v1`
291
+
292
+ ### Custom API URL
293
+
294
+ For self-hosted or custom deployments:
295
+
296
+ ```javascript
297
+ const feedback = new Product7({
298
+ workspace: 'your-workspace',
299
+ apiUrl: 'https://your-custom-api.com/api/v1',
300
+ });
301
+ ```
302
+
303
+ ---
304
+
305
+ ## Configuration Priority
306
+
307
+ Configuration values merge in this order (later overrides earlier):
308
+
309
+ 1. **Default values** — Built-in SDK defaults
310
+ 2. **Backend config** — Returned from `/widget/init` API
311
+ 3. **SDK config** — `window.Product7Config`
312
+ 4. **Widget options** — Passed to `createWidget()`
313
+
314
+ This allows backend-managed defaults while permitting per-widget customization.
315
+
316
+ ---
317
+
318
+ ## Events
319
+
320
+ ```javascript
321
+ feedback.eventBus.on('feedback:submitted', (data) => {
322
+ console.log('Feedback submitted:', data);
323
+ });
324
+
325
+ feedback.eventBus.on('feedback:error', (error) => {
326
+ console.error('Submission failed:', error);
327
+ });
328
+ ```
329
+
330
+ ---
331
+
332
+ ## Development
333
+
334
+ ```bash
335
+ git clone https://github.com/product7/product7-js.git
336
+ cd product7-js
337
+ npm install
338
+ npm run dev
339
+ npm run build
340
+ npm test
341
+ npm run size
342
+ ```
343
+
344
+ ---
345
+
346
+ ## Browser Support
347
+
348
+ - Chrome 60+
349
+ - Firefox 55+
350
+ - Safari 12+
351
+ - Edge 79+
352
+ - iOS Safari 12+
353
+ - Android Chrome 60+
354
+
355
+ ---
356
+
357
+ ## Bundle Size
358
+
359
+ - **Minified**: ~41KB
360
+ - **Minified + Gzipped**: ~12KB
361
+
362
+ ---
363
+
364
+ ## Contributing
365
+
366
+ We welcome contributions! See [Contributing Guide](CONTRIBUTING.md).
367
+
368
+ 1. Fork the repository
369
+ 2. Create your feature branch (`git checkout -b feature/amazing-feature`)
370
+ 3. Commit your changes (`git commit -m 'Add some amazing feature'`)
371
+ 4. Push to the branch (`git push origin feature/amazing-feature`)
372
+ 5. Open a Pull Request
373
+
374
+ ---
375
+
376
+ ## License
377
+
378
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
379
+
380
+ ---
381
+
382
+ ## Support
383
+
384
+ - Docs: [docs.product7.io/product7-js](https://docs.product7.io/product7-js)
385
+ - Issues: [GitHub Issues](https://github.com/product7/product7-js/issues)
386
+ - Discord: [Join our community](https://discord.gg/product7)
387
+ - Email: [support@product7.io](mailto:support@product7.io)
388
+
389
+ ---
390
+
391
+ ## Messenger Widget
392
+
393
+ The SDK includes a full-featured messenger widget for real-time customer conversations, help articles, and changelog updates.
394
+
395
+ ### Features
396
+
397
+ - **Real-time messaging** — WebSocket-powered live chat with typing indicators
398
+ - **Conversation management** — View and manage multiple conversations
399
+ - **Help center integration** — Browse help articles and collections
400
+ - **Changelog updates** — Display product updates and announcements
401
+ - **Agent availability** — Show online status and response times
402
+ - **Customizable UI** — Theme, colors, and position options
403
+
404
+ ### Quick Start
405
+
406
+ ```javascript
407
+ const feedback = new Product7({
408
+ workspace: 'your-workspace',
409
+ metadata: {
410
+ user_id: 'user_123',
411
+ email: 'user@example.com',
412
+ name: 'John Doe',
413
+ },
414
+ });
415
+
416
+ await feedback.init();
417
+
418
+ const messenger = feedback.createWidget('messenger', {
419
+ position: 'bottom-right',
420
+ theme: 'light',
421
+ teamName: 'Support Team',
422
+ welcomeMessage: 'How can we help you today?',
423
+ enableHelp: true,
424
+ enableChangelog: true,
425
+ primaryColor: '#155EEF',
426
+ });
427
+
428
+ messenger.mount();
429
+ ```
430
+
431
+ ### Messenger Configuration Options
432
+
433
+ | Option | Type | Default | Description |
434
+ | ------------------ | -------- | ------------------ | --------------------------------------- |
435
+ | `position` | string | 'bottom-right' | Widget position on screen |
436
+ | `theme` | string | 'light' | 'light' or 'dark' |
437
+ | `teamName` | string | 'Support' | Team name displayed in header |
438
+ | `teamAvatars` | array | [] | Array of team member avatar URLs |
439
+ | `welcomeMessage` | string | 'How can we help?' | Welcome message on home view |
440
+ | `enableHelp` | boolean | true | Show help articles section |
441
+ | `enableChangelog` | boolean | true | Show changelog section |
442
+ | `enableNews` | boolean | - | Alias for `enableChangelog` |
443
+ | `autoLoadData` | boolean | true | Auto-fetch conversations/help/changelog |
444
+ | `initialView` | string | 'home' | Initial view on mount |
445
+ | `previewData` | object | null | Seed deterministic local data |
446
+ | `logoUrl` | string | - | Custom logo URL |
447
+ | `primaryColor` | string | '#155EEF' | Primary accent color |
448
+ | `onSendMessage` | function | null | Callback when message is sent |
449
+ | `onArticleClick` | function | null | Callback when help article is clicked |
450
+ | `onChangelogClick` | function | null | Callback when changelog item is clicked |
451
+
452
+ ### Messenger Views
453
+
454
+ The messenger widget includes multiple views:
455
+
456
+ | View | Description |
457
+ | ----------- | --------------------------------- |
458
+ | `home` | Welcome screen with quick actions |
459
+ | `messages` | List of all conversations |
460
+ | `chat` | Individual conversation chat view |
461
+ | `help` | Help articles and collections |
462
+ | `changelog` | Product updates and announcements |
463
+
464
+ ### Programmatic Control
465
+
466
+ ```javascript
467
+ // Open/close messenger
468
+ messenger.open();
469
+ messenger.close();
470
+ messenger.toggle();
471
+
472
+ // Navigate to specific view
473
+ messenger.navigateTo('messages');
474
+ messenger.navigateTo('help');
475
+ messenger.navigateTo('changelog');
476
+
477
+ // Get current state
478
+ const state = messenger.getState();
479
+ console.log(state.isOpen, state.currentView, state.unreadCount);
480
+
481
+ // Update unread count
482
+ messenger.setUnreadCount(3);
483
+ ```
484
+
485
+ ### Real-time Events
486
+
487
+ ```javascript
488
+ // Message sent
489
+ feedback.eventBus.on('messenger:messageSent', (data) => {
490
+ console.log('Message sent:', data.message);
491
+ });
492
+
493
+ // Messenger opened/closed
494
+ feedback.eventBus.on('messenger:opened', () => {
495
+ console.log('Messenger opened');
496
+ });
497
+
498
+ feedback.eventBus.on('messenger:closed', () => {
499
+ console.log('Messenger closed');
500
+ });
501
+ ```
502
+
503
+ ### WebSocket Connection
504
+
505
+ The messenger automatically establishes a WebSocket connection for real-time features:
506
+
507
+ - **Incoming messages** — New messages appear instantly
508
+ - **Typing indicators** — See when agents are typing
509
+ - **Presence updates** — Real-time agent availability
510
+
511
+ The WebSocket connection is managed automatically and reconnects on disconnection.
512
+
513
+ ---
514
+
515
+ ## Environment Auto-Detection
516
+
517
+ The SDK automatically detects the environment based on the hostname:
518
+
519
+ | Hostname Pattern | Environment |
520
+ | ----------------------------------- | ----------- |
521
+ | `localhost`, `127.0.0.1`, `*.local` | staging |
522
+ | Contains `staging` | staging |
523
+ | All other hostnames | production |
524
+
525
+ ```javascript
526
+ // Auto-detection (recommended)
527
+ const feedback = new Product7({
528
+ workspace: 'your-workspace',
529
+ // env is auto-detected from window.location.hostname
530
+ });
531
+
532
+ // Manual override
533
+ const feedback = new Product7({
534
+ workspace: 'your-workspace',
535
+ env: 'staging', // Force staging environment
536
+ });
537
+ ```
538
+
539
+ ---
540
+
541
+ ## Survey Widget
542
+
543
+ 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.
544
+
545
+ ### Survey Types
546
+
547
+ | Type | Description | Scale |
548
+ | ---------- | --------------------- | ------------------------------------------------- |
549
+ | **NPS** | Net Promoter Score | 1-5 numeric scale (default; configurable to 0-10) |
550
+ | **CSAT** | Customer Satisfaction | 5-point emoji scale |
551
+ | **CES** | Customer Effort Score | 5-level difficulty scale |
552
+ | **Custom** | Multi-question forms | Flexible input types |
553
+
554
+ ### Quick Start
555
+
556
+ ```javascript
557
+ const feedback = new Product7({
558
+ workspace: 'your-workspace',
559
+ boardName: 'your-board-id',
560
+ });
561
+
562
+ await feedback.init();
563
+
564
+ // Show NPS survey
565
+ feedback.showSurvey({
566
+ surveyType: 'nps',
567
+ description:
568
+ 'To what extent do you agree or disagree that our tools support the work you do?',
569
+ ratingScale: 5,
570
+ showTitle: false,
571
+ showDescription: true,
572
+ showFeedbackInput: false,
573
+ showSubmitButton: false,
574
+ autoSubmitOnSelect: true,
575
+ onSubmit: (response) => {
576
+ console.log('Survey submitted:', response);
577
+ },
578
+ });
579
+ ```
580
+
581
+ ### Survey Configuration Options
582
+
583
+ ```javascript
584
+ feedback.showSurvey({
585
+ 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'
589
+ title: 'Your survey title',
590
+ 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
600
+ onSubmit: (response) => {},
601
+ onDismiss: () => {},
602
+ });
603
+ ```
604
+
605
+ ---
606
+
607
+ ### Backend-Driven Surveys
608
+
609
+ For surveys configured in the Product7 dashboard, use `showSurveyById()` to fetch and display them:
610
+
611
+ ```javascript
612
+ // Show a specific survey by its backend ID
613
+ await feedback.showSurveyById('survey_abc123', {
614
+ position: 'center', // Override position if needed
615
+ onSubmit: (response) => {
616
+ console.log('Survey completed:', response);
617
+ },
618
+ });
619
+ ```
620
+
621
+ ### Fetching Active Surveys
622
+
623
+ Retrieve surveys that match the current user's targeting criteria:
624
+
625
+ ```javascript
626
+ // Get all active surveys for the current context
627
+ const surveys = await feedback.getActiveSurveys();
628
+
629
+ console.log('Available surveys:', surveys);
630
+ // [{ id: 'survey_123', type: 'nps', title: '...', ... }]
631
+
632
+ // Show the first matching survey
633
+ if (surveys.length > 0) {
634
+ await feedback.showSurveyById(surveys[0].id);
635
+ }
636
+ ```
637
+
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
+ ---
651
+
652
+ ### Survey Types
653
+
654
+ #### NPS Survey (Net Promoter Score)
655
+
656
+ ```javascript
657
+ feedback.showSurvey({
658
+ surveyType: 'nps',
659
+ description:
660
+ 'To what extent do you agree or disagree that our tools support the work you do?',
661
+ ratingScale: 5,
662
+ showTitle: false,
663
+ showDescription: true,
664
+ showFeedbackInput: false,
665
+ showSubmitButton: false,
666
+ autoSubmitOnSelect: true,
667
+ lowLabel: 'Strongly Disagree',
668
+ highLabel: 'Strongly Agree',
669
+ position: 'bottom-right',
670
+ onSubmit: (response) => {
671
+ console.log('Score:', response.score); // 1-5 by default
672
+ console.log('Feedback:', response.feedback);
673
+ },
674
+ });
675
+ ```
676
+
677
+ #### CSAT Survey (Customer Satisfaction)
678
+
679
+ ```javascript
680
+ feedback.showSurvey({
681
+ surveyType: 'csat',
682
+ title: 'How satisfied are you with our service?',
683
+ position: 'center',
684
+ theme: 'dark',
685
+ onSubmit: (response) => {
686
+ console.log('Satisfaction:', response.score); // 1-5
687
+ },
688
+ });
689
+ ```
690
+
691
+ #### CES Survey (Customer Effort Score)
692
+
693
+ ```javascript
694
+ feedback.showSurvey({
695
+ surveyType: 'ces',
696
+ title: 'How easy was it to complete your task?',
697
+ position: 'bottom',
698
+ onSubmit: (response) => {
699
+ console.log('Effort score:', response.score); // 1-5
700
+ },
701
+ });
702
+ ```
703
+
704
+ #### Custom Survey
705
+
706
+ ```javascript
707
+ feedback.showSurvey({
708
+ surveyType: 'custom',
709
+ title: 'Quick Feedback',
710
+ customQuestions: [
711
+ {
712
+ id: 'feature',
713
+ type: 'select',
714
+ label: 'Which feature do you use most?',
715
+ options: [
716
+ { value: 'dashboard', label: 'Dashboard' },
717
+ { value: 'reports', label: 'Reports' },
718
+ { value: 'settings', label: 'Settings' },
719
+ ],
720
+ },
721
+ {
722
+ id: 'improvement',
723
+ type: 'text',
724
+ label: 'What could we improve?',
725
+ placeholder: 'Your suggestions...',
726
+ },
727
+ ],
728
+ onSubmit: (response) => {
729
+ console.log('Answers:', response.customAnswers);
730
+ // { feature: 'dashboard', improvement: 'Better charts' }
731
+ },
732
+ });
733
+ ```
734
+
735
+ ---
736
+
737
+ ### Event-Triggered Surveys
738
+
739
+ Trigger surveys based on user actions:
740
+
741
+ ```javascript
742
+ // After completing a purchase
743
+ document.getElementById('checkout-btn').addEventListener('click', async () => {
744
+ await processPayment();
745
+
746
+ feedback.showSurvey({
747
+ surveyType: 'csat',
748
+ title: 'How was your checkout experience?',
749
+ position: 'center',
750
+ });
751
+ });
752
+
753
+ // After closing support chat
754
+ chatWidget.on('close', () => {
755
+ feedback.showSurvey({
756
+ surveyType: 'ces',
757
+ title: 'How easy was it to get help?',
758
+ position: 'bottom-right',
759
+ });
760
+ });
761
+
762
+ // On page exit intent
763
+ document.addEventListener('mouseleave', (e) => {
764
+ if (e.clientY < 0 && !sessionStorage.getItem('exit_survey_shown')) {
765
+ sessionStorage.setItem('exit_survey_shown', 'true');
766
+ feedback.showSurvey({
767
+ surveyType: 'nps',
768
+ title: 'Before you go...',
769
+ description: 'How likely are you to recommend us?',
770
+ position: 'center',
771
+ });
772
+ }
773
+ });
774
+ ```
775
+
776
+ ### Time-Based Surveys
777
+
778
+ ```javascript
779
+ // Show after 60 seconds on page
780
+ setTimeout(() => {
781
+ feedback.showSurvey({
782
+ surveyType: 'nps',
783
+ title: 'Enjoying our product?',
784
+ position: 'bottom-right',
785
+ });
786
+ }, 60000);
787
+
788
+ // Show after N page views
789
+ const pageViews = parseInt(localStorage.getItem('page_views') || '0') + 1;
790
+ localStorage.setItem('page_views', pageViews);
791
+
792
+ if (pageViews === 5) {
793
+ feedback.showSurvey({
794
+ surveyType: 'csat',
795
+ title: 'How are you finding things so far?',
796
+ });
797
+ }
798
+ ```
799
+
800
+ ---
801
+
802
+ ### React Integration
803
+
804
+ ```jsx
805
+ import { useEffect, useRef } from 'react';
806
+ import { Product7 } from '@product7/product7-js';
807
+
808
+ function useSurvey() {
809
+ const sdkRef = useRef(null);
810
+
811
+ useEffect(() => {
812
+ const sdk = new Product7({
813
+ workspace: 'your-workspace',
814
+ metadata: {
815
+ user_id: currentUser.id,
816
+ email: currentUser.email,
817
+ },
818
+ });
819
+
820
+ sdk.init().then(() => {
821
+ sdkRef.current = sdk;
822
+ });
823
+
824
+ return () => sdk.destroy();
825
+ }, []);
826
+
827
+ const showNPS = (options = {}) => {
828
+ sdkRef.current?.showSurvey({
829
+ surveyType: 'nps',
830
+ ...options,
831
+ });
832
+ };
833
+
834
+ const showCSAT = (options = {}) => {
835
+ sdkRef.current?.showSurvey({
836
+ surveyType: 'csat',
837
+ ...options,
838
+ });
839
+ };
840
+
841
+ return { showNPS, showCSAT };
842
+ }
843
+
844
+ // Usage in component
845
+ function CheckoutSuccess() {
846
+ const { showCSAT } = useSurvey();
847
+
848
+ useEffect(() => {
849
+ showCSAT({
850
+ title: 'How was your checkout experience?',
851
+ position: 'center',
852
+ });
853
+ }, []);
854
+
855
+ return <div>Thank you for your purchase!</div>;
856
+ }
857
+ ```
858
+
859
+ ### Vue.js Integration
860
+
861
+ ```vue
862
+ <script setup>
863
+ import { onMounted, onUnmounted, ref } from 'vue';
864
+ import { Product7 } from '@product7/product7-js';
865
+
866
+ const sdk = ref(null);
867
+
868
+ onMounted(async () => {
869
+ sdk.value = new Product7({
870
+ workspace: 'your-workspace',
871
+ metadata: {
872
+ user_id: currentUser.value.id,
873
+ email: currentUser.value.email,
874
+ },
875
+ });
876
+ await sdk.value.init();
877
+ });
878
+
879
+ onUnmounted(() => {
880
+ sdk.value?.destroy();
881
+ });
882
+
883
+ const showSurvey = (type, options = {}) => {
884
+ sdk.value?.showSurvey({
885
+ surveyType: type,
886
+ ...options,
887
+ });
888
+ };
889
+
890
+ // Trigger on button click
891
+ const handleFeedbackClick = () => {
892
+ showSurvey('nps', {
893
+ title: 'How likely are you to recommend us?',
894
+ position: 'center',
895
+ });
896
+ };
897
+ </script>
898
+ ```
899
+
900
+ ---
901
+
902
+ ### Survey Events
903
+
904
+ ```javascript
905
+ // Survey displayed
906
+ feedback.eventBus.on('survey:shown', (data) => {
907
+ console.log('Survey displayed:', data.type);
908
+ analytics.track('Survey Shown', { type: data.type });
909
+ });
910
+
911
+ // Survey submitted
912
+ feedback.eventBus.on('survey:submitted', (data) => {
913
+ console.log('Survey submitted:', data.response);
914
+ analytics.track('Survey Completed', {
915
+ type: data.response.type,
916
+ score: data.response.score,
917
+ });
918
+ });
919
+
920
+ // Survey dismissed without completing
921
+ feedback.eventBus.on('survey:dismissed', (data) => {
922
+ console.log('Survey dismissed');
923
+ analytics.track('Survey Dismissed');
924
+ });
925
+ ```
926
+
927
+ ### Response Data Format
928
+
929
+ ```javascript
930
+ // NPS/CSAT/CES response
931
+ {
932
+ type: 'nps',
933
+ score: 9,
934
+ feedback: 'Great product!',
935
+ timestamp: '2025-01-26T10:30:00.000Z'
936
+ }
937
+
938
+ // Custom survey response
939
+ {
940
+ type: 'custom',
941
+ score: null,
942
+ feedback: 'Additional comments here',
943
+ customAnswers: {
944
+ feature: 'dashboard',
945
+ improvement: 'Better mobile support'
946
+ },
947
+ timestamp: '2025-01-26T10:30:00.000Z'
948
+ }
949
+ ```
950
+
951
+ ---
952
+
953
+ ### Position Options
954
+
955
+ | Position | Description |
956
+ | -------------- | ----------------------------- |
957
+ | `bottom-right` | Bottom right corner (default) |
958
+ | `bottom-left` | Bottom left corner |
959
+ | `center` | Centered modal with backdrop |
960
+ | `bottom` | Full-width bottom bar |
961
+
962
+ ### Theme Options
963
+
964
+ | Theme | Description |
965
+ | ------- | ------------------------------------- |
966
+ | `light` | White background, dark text (default) |
967
+ | `dark` | Dark background, light text |
968
+
969
+ ---
970
+
971
+ ### Programmatic Control
972
+
973
+ ```javascript
974
+ // Create survey widget for later use
975
+ const survey = feedback.createWidget('survey', {
976
+ surveyType: 'nps',
977
+ title: 'Rate us',
978
+ });
979
+ survey.mount();
980
+
981
+ // Show when ready
982
+ survey.show();
983
+
984
+ // Hide programmatically
985
+ survey.hide();
986
+
987
+ // Destroy when done
988
+ survey.destroy();
989
+ ```
990
+
991
+ ### Survey Rate Limiting
992
+
993
+ Avoid survey fatigue by tracking when surveys were last shown:
994
+
995
+ ```javascript
996
+ const SURVEY_COOLDOWN = 7 * 24 * 60 * 60 * 1000; // 7 days
997
+
998
+ function canShowSurvey(surveyType) {
999
+ const lastShown = localStorage.getItem(`survey_${surveyType}_shown`);
1000
+ if (!lastShown) return true;
1001
+ return Date.now() - parseInt(lastShown) > SURVEY_COOLDOWN;
1002
+ }
1003
+
1004
+ function showSurveyWithCooldown(options) {
1005
+ if (!canShowSurvey(options.surveyType)) {
1006
+ console.log('Survey on cooldown');
1007
+ return null;
1008
+ }
1009
+
1010
+ localStorage.setItem(`survey_${options.surveyType}_shown`, Date.now());
1011
+ return feedback.showSurvey(options);
1012
+ }
1013
+ ```
1014
+
1015
+ ---
1016
+
1017
+ ## Related
1018
+
1019
+ - [Product7 Platform](https://product7.io)
1020
+ - [Vue.js Example](https://github.com/product7/product7-js-vue-example)
1021
+ - [React Example](https://github.com/product7/product7-js-react-example)
1022
+
1023
+ ---
1024
+
1025
+ Made by the [Product7 Team](https://product7.io)