@product7/product7-js 0.2.6 → 0.2.7

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