@product7/product7-js 0.3.2 → 0.3.5

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.
@@ -5,67 +5,66 @@
5
5
  ### Simple Setup
6
6
 
7
7
  ```javascript
8
- import Product7 from '@product7/product7-js';
8
+ import { Product7 } from '@product7/product7-js';
9
9
 
10
10
  const sdk = new Product7({
11
11
  workspace: 'my-workspace',
12
- metadata: {
13
- user_id: 'user_123',
14
- email: 'user@example.com',
15
- },
12
+ boardName: 'feature-requests',
16
13
  });
17
14
 
18
15
  await sdk.init();
16
+ await sdk.identify({
17
+ user_id: 'user_123',
18
+ email: 'user@example.com',
19
+ name: 'John Doe',
20
+ });
19
21
 
20
- const widget = sdk.createWidget('button');
22
+ const widget = sdk.createFeedbackWidget();
21
23
  widget.mount();
22
24
  ```
23
25
 
24
26
  ---
25
27
 
26
- ## User Context
28
+ ## User Identity
27
29
 
28
- ### Basic User Context
30
+ ### Basic Identify Call
29
31
 
30
32
  ```javascript
31
- const sdk = new Product7({
32
- workspace: 'my-workspace',
33
- metadata: {
34
- user_id: 'user_123',
35
- email: 'user@example.com',
36
- name: 'John Doe',
37
- },
33
+ await sdk.identify({
34
+ user_id: 'user_123',
35
+ email: 'user@example.com',
36
+ name: 'John Doe',
38
37
  });
39
38
  ```
40
39
 
41
40
  ### With Custom Fields
42
41
 
43
42
  ```javascript
44
- metadata: {
43
+ await sdk.identify({
45
44
  user_id: 'user_123',
46
45
  email: 'user@example.com',
47
46
  name: 'John Doe',
48
47
  custom_fields: {
49
48
  role: 'admin',
50
49
  plan: 'pro',
51
- signup_date: '2024-01-01'
52
- }
53
- }
50
+ signup_date: '2024-01-01',
51
+ },
52
+ });
54
53
  ```
55
54
 
56
55
  ### With Company Data
57
56
 
58
57
  ```javascript
59
- metadata: {
58
+ await sdk.identify({
60
59
  user_id: 'user_123',
61
60
  email: 'user@example.com',
62
61
  name: 'John Doe',
63
62
  company: {
64
63
  id: 'company_456',
65
64
  name: 'Acme Corp',
66
- monthly_spend: 1000
67
- }
68
- }
65
+ monthly_spend: 1000,
66
+ },
67
+ });
69
68
  ```
70
69
 
71
70
  ### Extract from Auth
@@ -80,36 +79,29 @@ const authData = {
80
79
 
81
80
  const metadata = Product7.extractMetadataFromAuth(authData);
82
81
 
83
- const sdk = new Product7({
84
- workspace: 'my-workspace',
85
- metadata,
86
- });
82
+ await sdk.identify(metadata);
87
83
  ```
88
84
 
89
85
  ---
90
86
 
91
- ## Widget Customization
87
+ ## Feedback Widget
92
88
 
93
89
  ### Different Positions
94
90
 
95
91
  ```javascript
96
- // Bottom right (default)
97
- const widget1 = sdk.createWidget('button', {
92
+ const widget1 = sdk.createFeedbackWidget({
98
93
  position: 'bottom-right',
99
94
  });
100
95
 
101
- // Bottom left
102
- const widget2 = sdk.createWidget('button', {
96
+ const widget2 = sdk.createFeedbackWidget({
103
97
  position: 'bottom-left',
104
98
  });
105
99
 
106
- // Top right
107
- const widget3 = sdk.createWidget('button', {
100
+ const widget3 = sdk.createFeedbackWidget({
108
101
  position: 'top-right',
109
102
  });
110
103
 
111
- // Top left
112
- const widget4 = sdk.createWidget('button', {
104
+ const widget4 = sdk.createFeedbackWidget({
113
105
  position: 'top-left',
114
106
  });
115
107
  ```
@@ -117,7 +109,7 @@ const widget4 = sdk.createWidget('button', {
117
109
  ### Dark Theme
118
110
 
119
111
  ```javascript
120
- const widget = sdk.createWidget('button', {
112
+ const widget = sdk.createFeedbackWidget({
121
113
  theme: 'dark',
122
114
  });
123
115
  widget.mount();
@@ -126,24 +118,37 @@ widget.mount();
126
118
  ### Custom Board
127
119
 
128
120
  ```javascript
129
- const widget = sdk.createWidget('button', {
121
+ const widget = sdk.createFeedbackWidget({
122
+ boardName: 'bug-reports',
123
+ });
124
+ widget.mount();
125
+ ```
126
+
127
+ ### Headless Feedback
128
+
129
+ ```javascript
130
+ const widget = sdk.createFeedbackWidget({
131
+ headless: true,
130
132
  boardName: 'feature-requests',
131
133
  });
134
+
132
135
  widget.mount();
136
+
137
+ document
138
+ .querySelector('#feedback-trigger')
139
+ ?.addEventListener('click', () => widget.open());
133
140
  ```
134
141
 
135
- ### Multiple Widgets
142
+ ### Multiple Feedback Widgets
136
143
 
137
144
  ```javascript
138
- // Feedback button
139
- const feedbackWidget = sdk.createWidget('button', {
145
+ const feedbackWidget = sdk.createFeedbackWidget({
140
146
  position: 'bottom-right',
141
147
  boardName: 'general',
142
148
  });
143
149
  feedbackWidget.mount();
144
150
 
145
- // Bug report button
146
- const bugWidget = sdk.createWidget('button', {
151
+ const bugWidget = sdk.createFeedbackWidget({
147
152
  position: 'bottom-left',
148
153
  boardName: 'bug-reports',
149
154
  });
@@ -151,177 +156,221 @@ bugWidget.updateText('Report Bug');
151
156
  bugWidget.mount();
152
157
  ```
153
158
 
154
- ### Update Widget
159
+ ### Update the Widget
155
160
 
156
161
  ```javascript
157
- const widget = sdk.createWidget('button');
162
+ const widget = sdk.createFeedbackWidget();
158
163
  widget.mount();
159
164
 
160
- // Update text
161
165
  widget.updateText('Send Feedback');
162
-
163
- // Update position
164
166
  widget.updatePosition('top-right');
165
-
166
- // Show/hide
167
167
  widget.hide();
168
168
  widget.show();
169
169
  ```
170
170
 
171
171
  ---
172
172
 
173
- ## Event Handling
173
+ ## Survey Widget
174
174
 
175
- ### Track Submissions
175
+ ### Create and Open a Survey
176
176
 
177
177
  ```javascript
178
- sdk.on('feedback:submitted', ({ widget, feedback }) => {
179
- console.log('Feedback submitted:', feedback.id);
180
-
181
- // Track in analytics
182
- analytics.track('Feedback Submitted', {
183
- feedbackId: feedback.id,
184
- board: feedback.board,
185
- });
178
+ const survey = sdk.createSurveyWidget({
179
+ surveyType: 'nps',
180
+ position: 'center',
181
+ title: 'Quick question',
182
+ description: 'How likely are you to recommend us?',
183
+ showSubmitButton: true,
186
184
  });
185
+
186
+ survey.mount();
187
+ survey.open();
187
188
  ```
188
189
 
189
- ### Handle Errors
190
+ ### Show Active Surveys
190
191
 
191
192
  ```javascript
192
- sdk.on('feedback:error', ({ widget, error }) => {
193
- console.error('Submission failed:', error.message);
194
-
195
- // Show custom error notification
196
- toast.error('Failed to submit feedback. Please try again.');
193
+ const surveys = await sdk.getActiveSurveys({
194
+ includeEligibility: true,
197
195
  });
196
+
197
+ if (surveys.length > 0) {
198
+ await sdk.showSurveyById(surveys[0].surveyId, {
199
+ position: 'center',
200
+ });
201
+ }
198
202
  ```
199
203
 
200
- ### Widget Lifecycle
204
+ ---
205
+
206
+ ## Messenger Widget
207
+
208
+ ### Basic Messenger
201
209
 
202
210
  ```javascript
203
- sdk.on('widget:mounted', ({ widget }) => {
204
- console.log('Widget mounted:', widget.id);
211
+ const messenger = sdk.createMessengerWidget({
212
+ position: 'bottom-right',
213
+ teamName: 'Support Team',
214
+ enableHelp: true,
215
+ enableChangelog: true,
205
216
  });
206
217
 
207
- sdk.on('widget:destroyed', ({ widget }) => {
208
- console.log('Widget destroyed:', widget.id);
218
+ messenger.mount();
219
+ ```
220
+
221
+ ### Headless Messenger
222
+
223
+ ```javascript
224
+ const messenger = sdk.createMessengerWidget({
225
+ headless: true,
226
+ enableHelp: true,
209
227
  });
228
+
229
+ messenger.mount();
230
+
231
+ document
232
+ .querySelector('#support-link')
233
+ ?.addEventListener('click', () => messenger.open());
210
234
  ```
211
235
 
212
- ### Multiple Events
236
+ ### Programmatic Messenger Navigation
213
237
 
214
238
  ```javascript
215
- sdk
216
- .on('feedback:submitted', handleSubmit)
217
- .on('feedback:error', handleError)
218
- .on('config:updated', handleConfigUpdate);
239
+ messenger.open();
240
+ messenger.navigateTo('help');
241
+ messenger.close();
242
+ ```
243
+
244
+ ---
245
+
246
+ ## Changelog Widget
247
+
248
+ ### Basic Changelog
249
+
250
+ ```javascript
251
+ const changelog = sdk.createChangelogWidget({
252
+ position: 'bottom-left',
253
+ triggerText: "What's New",
254
+ showBadge: true,
255
+ });
256
+
257
+ changelog.mount();
219
258
  ```
220
259
 
221
- ### One-time Events
260
+ ### Open Changelog Programmatically
222
261
 
223
262
  ```javascript
224
- sdk.once('sdk:initialized', (data) => {
225
- console.log('SDK ready!', data.config);
263
+ const changelog = sdk.createChangelogWidget({
264
+ headless: true,
226
265
  });
266
+
267
+ changelog.mount();
268
+ changelog.open();
227
269
  ```
228
270
 
229
271
  ---
230
272
 
231
- ## Authentication Flows
273
+ ## Event Handling
232
274
 
233
- ### On Login
275
+ ### Track Feedback Submissions
234
276
 
235
277
  ```javascript
236
- async function handleLogin(authResponse) {
237
- const metadata = Product7.extractMetadataFromAuth(authResponse);
238
- await sdk.reinitialize(metadata);
239
-
240
- // Create widget after login
241
- const widget = sdk.createWidget('button');
242
- widget.mount();
243
- }
278
+ sdk.on('feedback:submitted', ({ feedback }) => {
279
+ console.log('Feedback submitted:', feedback);
280
+ });
244
281
  ```
245
282
 
246
- ### On Logout
283
+ ### Track Survey Events
247
284
 
248
285
  ```javascript
249
- function handleLogout() {
250
- sdk.apiService.clearSession();
251
- sdk.destroyAllWidgets();
252
- }
286
+ sdk.on('survey:submitted', ({ response }) => {
287
+ console.log('Survey submitted:', response);
288
+ });
289
+
290
+ sdk.on('survey:questionAnswered', (data) => {
291
+ console.log('Question answered:', data.pageId, data.answer);
292
+ });
253
293
  ```
254
294
 
255
- ### Check Session
295
+ ### SDK Lifecycle
256
296
 
257
297
  ```javascript
258
- if (!sdk.apiService.isSessionValid()) {
259
- await sdk.init();
260
- }
298
+ sdk.on('sdk:initialized', (data) => {
299
+ console.log('SDK ready:', data.sessionToken);
300
+ });
301
+
302
+ sdk.on('sdk:identified', (data) => {
303
+ console.log('User identified:', data.metadata);
304
+ });
261
305
  ```
262
306
 
263
307
  ---
264
308
 
265
- ## Configuration Updates
309
+ ## Authentication Flows
266
310
 
267
- ### Update Theme
311
+ ### On Login
268
312
 
269
313
  ```javascript
270
- sdk.updateConfig({ theme: 'dark' });
314
+ async function handleLogin(authResponse) {
315
+ const metadata = Product7.extractMetadataFromAuth(authResponse);
316
+
317
+ await sdk.init();
318
+ await sdk.identify(metadata);
319
+
320
+ const widget = sdk.createFeedbackWidget();
321
+ widget.mount();
322
+ }
271
323
  ```
272
324
 
273
- ### Update Multiple Options
325
+ ### On User Change
274
326
 
275
327
  ```javascript
276
- sdk.updateConfig({
277
- theme: 'dark',
278
- position: 'top-right',
279
- showBackdrop: false,
280
- });
328
+ async function handleUserChanged(user) {
329
+ await sdk.identify({
330
+ user_id: user.id,
331
+ email: user.email,
332
+ name: user.name,
333
+ });
334
+ }
281
335
  ```
282
336
 
283
- ### Update User Context
337
+ ### On Logout
284
338
 
285
339
  ```javascript
286
- sdk.setMetadata({
287
- user_id: 'user_456',
288
- email: 'newuser@example.com',
289
- name: 'Jane Smith',
290
- });
340
+ function handleLogout() {
341
+ sdk.destroyAllWidgets();
342
+ sdk.destroy();
343
+ }
291
344
  ```
292
345
 
293
346
  ---
294
347
 
295
348
  ## Programmatic Control
296
349
 
297
- ### Open Panel Programmatically
350
+ ### Open Feedback from Code
298
351
 
299
352
  ```javascript
300
- const widget = sdk.createWidget('button');
353
+ const widget = sdk.createFeedbackWidget({
354
+ headless: true,
355
+ });
356
+
301
357
  widget.mount();
302
358
 
303
- // Open panel from code
304
359
  setTimeout(() => {
305
- widget.openPanel();
360
+ widget.open();
306
361
  }, 3000);
307
362
  ```
308
363
 
309
- ### Close Panel
310
-
311
- ```javascript
312
- widget.closePanel();
313
- ```
314
-
315
- ### Trigger from Custom Button
364
+ ### Toggle Survey
316
365
 
317
366
  ```javascript
318
- const customButton = document.getElementById('feedback-btn');
319
- customButton.addEventListener('click', () => {
320
- const widget = sdk.getWidget('widget_123');
321
- if (widget) {
322
- widget.openPanel();
323
- }
367
+ const survey = sdk.createSurveyWidget({
368
+ surveyType: 'csat',
369
+ showSubmitButton: true,
324
370
  });
371
+
372
+ survey.mount();
373
+ survey.toggle();
325
374
  ```
326
375
 
327
376
  ---
@@ -333,16 +382,15 @@ customButton.addEventListener('click', () => {
333
382
  ```javascript
334
383
  try {
335
384
  await sdk.init();
336
- const widget = sdk.createWidget('button');
385
+ await sdk.identify({
386
+ user_id: 'user_123',
387
+ email: 'user@example.com',
388
+ });
389
+
390
+ const widget = sdk.createFeedbackWidget();
337
391
  widget.mount();
338
392
  } catch (error) {
339
- if (error instanceof ConfigError) {
340
- console.error('Config error:', error.message);
341
- } else if (error instanceof APIError) {
342
- console.error('API error:', error.status);
343
- } else {
344
- console.error('Unexpected error:', error);
345
- }
393
+ console.error('Product7 error:', error);
346
394
  }
347
395
  ```
348
396
 
@@ -395,39 +443,39 @@ const widget = sdk.createWidget('custom');
395
443
  widget.mount();
396
444
  ```
397
445
 
398
- ### Conditional Widget Loading
446
+ ### Conditional Loading
399
447
 
400
448
  ```javascript
401
- // Only show feedback for authenticated users
402
449
  if (user.isAuthenticated) {
403
450
  const sdk = new Product7({
404
451
  workspace: 'my-workspace',
405
- metadata: {
406
- user_id: user.id,
407
- email: user.email,
408
- },
409
452
  });
410
453
 
411
454
  await sdk.init();
412
- const widget = sdk.createWidget('button');
455
+ await sdk.identify({
456
+ user_id: user.id,
457
+ email: user.email,
458
+ });
459
+
460
+ const widget = sdk.createFeedbackWidget();
413
461
  widget.mount();
414
462
  }
415
463
  ```
416
464
 
417
- ### Environment-based Configuration
465
+ ### Environment-Based Config
418
466
 
419
467
  ```javascript
420
- const config = {
468
+ const sdk = new Product7({
421
469
  workspace: 'my-workspace',
422
- metadata: getMetadata(),
423
470
  apiUrl:
424
471
  process.env.NODE_ENV === 'production'
425
472
  ? 'https://api.product7.io/api/v1'
426
473
  : 'https://staging.api.product7.io/api/v1',
427
474
  debug: process.env.NODE_ENV === 'development',
428
- };
475
+ });
429
476
 
430
- const sdk = new Product7(config);
477
+ await sdk.init();
478
+ await sdk.identify(getMetadata());
431
479
  ```
432
480
 
433
481
  ---
@@ -437,15 +485,17 @@ const sdk = new Product7(config);
437
485
  ### Mock SDK
438
486
 
439
487
  ```javascript
440
- // In tests
441
488
  jest.mock('@product7/product7-js');
442
489
 
443
490
  test('should initialize SDK', async () => {
444
491
  const sdk = new Product7({
445
492
  workspace: 'test',
446
- metadata: { user_id: '123' },
493
+ mock: true,
447
494
  });
495
+
448
496
  await sdk.init();
497
+ await sdk.identify({ user_id: '123' });
498
+
449
499
  expect(sdk.initialized).toBe(true);
450
500
  });
451
501
  ```
@@ -453,7 +503,7 @@ test('should initialize SDK', async () => {
453
503
  ### Check Widget Exists
454
504
 
455
505
  ```javascript
456
- const widget = sdk.createWidget('button');
506
+ const widget = sdk.createFeedbackWidget();
457
507
  widget.mount();
458
508
 
459
509
  const found = sdk.getWidget(widget.id);