@product7/product7-js 0.2.5 → 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.
- package/README.md +71 -961
- package/dist/README.md +71 -961
- package/package.json +1 -1
package/dist/README.md
CHANGED
|
@@ -1,1024 +1,134 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Product7 JS
|
|
2
2
|
|
|
3
3
|
[](https://badge.fury.io/js/%40product7%2Fproduct7-js)
|
|
4
4
|
[](https://bundlephobia.com/package/@product7/product7-js)
|
|
5
5
|
|
|
6
|
-
|
|
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
|
-
##
|
|
10
|
+
## Installation
|
|
11
11
|
|
|
12
|
-
|
|
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
|
|
12
|
+
**npm**
|
|
51
13
|
|
|
52
14
|
```bash
|
|
53
15
|
npm install @product7/product7-js
|
|
54
16
|
```
|
|
55
17
|
|
|
56
|
-
|
|
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
|
|
18
|
+
**CDN**
|
|
70
19
|
|
|
71
20
|
```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
|
-
};
|
|
21
|
+
<script src="https://cdn.jsdelivr.net/npm/@product7/product7-js@latest/dist/product7-js.min.js"></script>
|
|
246
22
|
```
|
|
247
23
|
|
|
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
24
|
---
|
|
259
25
|
|
|
260
|
-
##
|
|
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`
|
|
26
|
+
## Quick Start
|
|
277
27
|
|
|
278
|
-
###
|
|
28
|
+
### npm / framework
|
|
279
29
|
|
|
280
30
|
```javascript
|
|
281
|
-
|
|
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:
|
|
31
|
+
import { Product7 } from '@product7/product7-js';
|
|
295
32
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
33
|
+
const sdk = new Product7({
|
|
34
|
+
workspace: 'your-workspace',
|
|
35
|
+
metadata: {
|
|
36
|
+
user_id: 'user_123',
|
|
37
|
+
email: 'user@example.com',
|
|
38
|
+
name: 'Jane Doe',
|
|
39
|
+
},
|
|
300
40
|
});
|
|
301
|
-
```
|
|
302
|
-
|
|
303
|
-
---
|
|
304
41
|
|
|
305
|
-
|
|
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
|
-
---
|
|
42
|
+
await sdk.init();
|
|
317
43
|
|
|
318
|
-
|
|
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
|
-
});
|
|
44
|
+
const widget = sdk.createWidget('button', { position: 'bottom-right' });
|
|
45
|
+
widget.mount();
|
|
328
46
|
```
|
|
329
47
|
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
## Development
|
|
48
|
+
### CDN
|
|
333
49
|
|
|
334
|
-
```
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
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>
|
|
342
67
|
```
|
|
343
68
|
|
|
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)
|
|
69
|
+
> Use `window.Product7.Product7SDK` on CDN — `window.Product7` is a plain object, not a constructor.
|
|
388
70
|
|
|
389
71
|
---
|
|
390
72
|
|
|
391
|
-
##
|
|
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
|
|
73
|
+
## Widgets
|
|
403
74
|
|
|
404
|
-
|
|
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 |
|
|
405
81
|
|
|
406
82
|
```javascript
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
},
|
|
83
|
+
// Messenger
|
|
84
|
+
const messenger = sdk.createWidget('messenger', {
|
|
85
|
+
position: 'bottom-right',
|
|
86
|
+
teamName: 'Support Team',
|
|
87
|
+
enableHelp: true,
|
|
88
|
+
enableChangelog: true,
|
|
414
89
|
});
|
|
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
90
|
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
91
|
|
|
481
|
-
//
|
|
482
|
-
|
|
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
|
|
92
|
+
// Survey — fetch active surveys and show on load
|
|
93
|
+
const surveys = await sdk.getActiveSurveys({ includeEligibility: true });
|
|
633
94
|
if (surveys.length > 0) {
|
|
634
|
-
|
|
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
|
-
});
|
|
95
|
+
sdk.showSurveyById(surveys[0].surveyId, { position: 'center' });
|
|
797
96
|
}
|
|
798
97
|
```
|
|
799
98
|
|
|
800
99
|
---
|
|
801
100
|
|
|
802
|
-
|
|
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
|
|
101
|
+
## Key Options
|
|
903
102
|
|
|
904
103
|
```javascript
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
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'
|
|
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' },
|
|
946
111
|
},
|
|
947
|
-
|
|
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',
|
|
112
|
+
debug: false, // enable console logging
|
|
113
|
+
mock: false, // run without a backend (dev/testing)
|
|
978
114
|
});
|
|
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
115
|
```
|
|
990
116
|
|
|
991
|
-
|
|
117
|
+
---
|
|
992
118
|
|
|
993
|
-
|
|
119
|
+
## Cleanup
|
|
994
120
|
|
|
995
121
|
```javascript
|
|
996
|
-
|
|
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
|
-
}
|
|
122
|
+
sdk.destroy(); // call on app unmount to prevent memory leaks
|
|
1013
123
|
```
|
|
1014
124
|
|
|
1015
125
|
---
|
|
1016
126
|
|
|
1017
|
-
##
|
|
127
|
+
## Docs & Support
|
|
1018
128
|
|
|
1019
|
-
- [
|
|
1020
|
-
- [
|
|
1021
|
-
- [
|
|
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)
|
|
1022
132
|
|
|
1023
133
|
---
|
|
1024
134
|
|