@product7/product7-js 0.2.6 → 0.2.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +55 -925
- package/dist/README.md +55 -925
- package/dist/product7-js.js +176 -40
- package/dist/product7-js.js.map +1 -1
- package/dist/product7-js.min.js +1 -1
- package/dist/product7-js.min.js.map +1 -1
- package/package.json +1 -1
- package/src/styles/design-tokens.js +3 -3
- package/src/styles/messenger-components.js +82 -3
- package/src/styles/messenger-core.js +2 -2
- package/src/widgets/MessengerWidget.js +25 -4
- package/src/widgets/messenger/MessengerState.js +3 -1
- package/src/widgets/messenger/views/ChatView.js +57 -17
- package/src/widgets/messenger/views/HomeView.js +4 -10
package/README.md
CHANGED
|
@@ -3,67 +3,35 @@
|
|
|
3
3
|
[](https://badge.fury.io/js/%40product7%2Fproduct7-js)
|
|
4
4
|
[](https://bundlephobia.com/package/@product7/product7-js)
|
|
5
5
|
|
|
6
|
-
The official JavaScript SDK for Product7.
|
|
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
|
-
##
|
|
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
|
-
|
|
12
|
+
**npm**
|
|
30
13
|
|
|
31
|
-
|
|
14
|
+
```bash
|
|
15
|
+
npm install @product7/product7-js
|
|
16
|
+
```
|
|
32
17
|
|
|
33
|
-
|
|
18
|
+
**CDN**
|
|
34
19
|
|
|
35
20
|
```html
|
|
36
21
|
<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
22
|
```
|
|
53
23
|
|
|
54
|
-
|
|
24
|
+
---
|
|
55
25
|
|
|
56
|
-
|
|
26
|
+
## Quick Start
|
|
57
27
|
|
|
58
|
-
|
|
59
|
-
npm install @product7/product7-js
|
|
60
|
-
```
|
|
28
|
+
### npm / framework
|
|
61
29
|
|
|
62
30
|
```javascript
|
|
63
31
|
import { Product7 } from '@product7/product7-js';
|
|
64
32
|
|
|
65
33
|
const sdk = new Product7({
|
|
66
|
-
workspace: 'your-workspace
|
|
34
|
+
workspace: 'your-workspace',
|
|
67
35
|
metadata: {
|
|
68
36
|
user_id: 'user_123',
|
|
69
37
|
email: 'user@example.com',
|
|
@@ -71,935 +39,97 @@ const sdk = new Product7({
|
|
|
71
39
|
},
|
|
72
40
|
});
|
|
73
41
|
|
|
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**
|
|
125
|
-
|
|
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();
|
|
135
|
-
```
|
|
136
|
-
|
|
137
|
-
---
|
|
138
|
-
|
|
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
|
|
185
|
-
|
|
186
|
-
Instead of predefined themes, use direct color values for full flexibility:
|
|
187
|
-
|
|
188
|
-
```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:
|
|
208
|
-
|
|
209
|
-
```javascript
|
|
210
|
-
const sdk = new Product7({
|
|
211
|
-
workspace: 'your-workspace',
|
|
212
|
-
metadata: { user_id: 'user_123', email: 'user@example.com', name: 'Jane Doe' },
|
|
213
|
-
});
|
|
214
|
-
|
|
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
46
|
```
|
|
229
47
|
|
|
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
|
-
});
|
|
48
|
+
### CDN
|
|
246
49
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
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
|
-
---
|
|
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
|
+
});
|
|
332
61
|
|
|
333
|
-
|
|
62
|
+
await sdk.init();
|
|
334
63
|
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
npm install
|
|
339
|
-
npm run dev
|
|
340
|
-
npm run build
|
|
341
|
-
npm test
|
|
342
|
-
npm run size
|
|
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
|
|
69
|
+
> Use `window.Product7.Product7SDK` on CDN — `window.Product7` is a plain object, not a constructor.
|
|
374
70
|
|
|
375
71
|
---
|
|
376
72
|
|
|
377
|
-
##
|
|
73
|
+
## Widgets
|
|
378
74
|
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
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)
|
|
389
|
-
|
|
390
|
-
---
|
|
391
|
-
|
|
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
|
|
404
|
-
|
|
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
|
-
|
|
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
85
|
position: 'bottom-right',
|
|
421
|
-
theme: 'light',
|
|
422
86
|
teamName: 'Support Team',
|
|
423
|
-
welcomeMessage: 'How can we help you today?',
|
|
424
87
|
enableHelp: true,
|
|
425
88
|
enableChangelog: true,
|
|
426
|
-
primaryColor: '#155EEF',
|
|
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
|
-
|
|
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
91
|
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
});
|
|
532
|
-
|
|
533
|
-
// Manual override
|
|
534
|
-
const sdk = new Product7({
|
|
535
|
-
workspace: 'your-workspace',
|
|
536
|
-
env: 'staging', // Force staging environment
|
|
537
|
-
});
|
|
92
|
+
// Survey — fetch active surveys and show on load
|
|
93
|
+
const surveys = await sdk.getActiveSurveys({ includeEligibility: true });
|
|
94
|
+
if (surveys.length > 0) {
|
|
95
|
+
sdk.showSurveyById(surveys[0].surveyId, { position: 'center' });
|
|
96
|
+
}
|
|
538
97
|
```
|
|
539
98
|
|
|
540
99
|
---
|
|
541
100
|
|
|
542
|
-
##
|
|
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
|
|
101
|
+
## Key Options
|
|
556
102
|
|
|
557
103
|
```javascript
|
|
558
|
-
|
|
559
|
-
workspace: 'your-workspace',
|
|
104
|
+
new Product7({
|
|
105
|
+
workspace: 'your-workspace', // required
|
|
560
106
|
metadata: {
|
|
107
|
+
// recommended — identifies the user
|
|
561
108
|
user_id: 'user_123',
|
|
562
109
|
email: 'user@example.com',
|
|
563
110
|
name: 'Jane Doe',
|
|
111
|
+
custom_fields: { plan: 'pro' },
|
|
564
112
|
},
|
|
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
|
-
},
|
|
113
|
+
debug: false, // enable console logging
|
|
114
|
+
mock: false, // run without a backend (dev/testing)
|
|
622
115
|
});
|
|
623
116
|
```
|
|
624
117
|
|
|
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
|
|
631
|
-
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
|
-
if (surveys.length > 0) {
|
|
638
|
-
await sdk.showSurveyById(surveys[0].surveyId, { position: 'center' });
|
|
639
|
-
}
|
|
640
|
-
```
|
|
641
|
-
|
|
642
118
|
---
|
|
643
119
|
|
|
644
|
-
|
|
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)
|
|
120
|
+
## Cleanup
|
|
683
121
|
|
|
684
122
|
```javascript
|
|
685
|
-
sdk.
|
|
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
|
-
});
|
|
123
|
+
sdk.destroy(); // call on app unmount to prevent memory leaks
|
|
724
124
|
```
|
|
725
125
|
|
|
726
126
|
---
|
|
727
127
|
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
Trigger surveys based on user actions:
|
|
128
|
+
## Docs & Support
|
|
731
129
|
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
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
|
-
});
|
|
788
|
-
}
|
|
789
|
-
```
|
|
790
|
-
|
|
791
|
-
---
|
|
792
|
-
|
|
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
|
|
909
|
-
|
|
910
|
-
```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'
|
|
927
|
-
},
|
|
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',
|
|
959
|
-
});
|
|
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
|
-
```
|
|
971
|
-
|
|
972
|
-
### Survey Rate Limiting
|
|
973
|
-
|
|
974
|
-
Avoid survey fatigue by tracking when surveys were last shown:
|
|
975
|
-
|
|
976
|
-
```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
|
-
}
|
|
994
|
-
```
|
|
995
|
-
|
|
996
|
-
---
|
|
997
|
-
|
|
998
|
-
## Related
|
|
999
|
-
|
|
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)
|
|
130
|
+
- Full documentation: [docs.product7.io](https://docs.product7.io)
|
|
131
|
+
- Issues: [GitHub Issues](https://github.com/product7/product7-js/issues)
|
|
132
|
+
- Email: [support@product7.io](mailto:support@product7.io)
|
|
1003
133
|
|
|
1004
134
|
---
|
|
1005
135
|
|