@product7/feedback-sdk 1.5.0 → 1.5.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@product7/feedback-sdk",
3
- "version": "1.5.0",
3
+ "version": "1.5.2",
4
4
  "description": "JavaScript SDK for integrating Product7 feedback widgets into any website",
5
5
  "main": "dist/feedback-sdk.js",
6
6
  "module": "src/index.js",
@@ -15,11 +15,20 @@ export class SurveyService {
15
15
  return { success: true, data: MOCK_SURVEYS };
16
16
  }
17
17
 
18
+ const respondent = this._getRespondentContext(context);
19
+
18
20
  const params = {
19
21
  url:
20
22
  context.url ||
21
23
  (typeof window !== 'undefined' ? window.location.href : ''),
22
24
  ...getDeviceInfo(),
25
+ ...(respondent.respondent_id && {
26
+ respondent_id: respondent.respondent_id,
27
+ }),
28
+ ...(respondent.email && { email: respondent.email }),
29
+ ...(context.includeEligibility !== undefined && {
30
+ include_eligibility: context.includeEligibility,
31
+ }),
23
32
  ...(context.userProperties && {
24
33
  user_properties: context.userProperties,
25
34
  }),
@@ -37,6 +46,19 @@ export class SurveyService {
37
46
  });
38
47
  }
39
48
 
49
+ _getRespondentContext(context = {}) {
50
+ const userContext =
51
+ typeof this.api.getUserContext === 'function'
52
+ ? this.api.getUserContext() || {}
53
+ : {};
54
+
55
+ return {
56
+ respondent_id:
57
+ context.respondentId || context.userId || userContext.user_id || null,
58
+ email: context.email || userContext.email || null,
59
+ };
60
+ }
61
+
40
62
  async submitSurveyResponse(surveyId, responseData) {
41
63
  if (!surveyId) throw new APIError(400, 'Survey ID is required');
42
64
 
@@ -55,10 +77,16 @@ export class SurveyService {
55
77
  };
56
78
  }
57
79
 
80
+ const respondent = this._getRespondentContext(responseData);
81
+
58
82
  const payload = {
59
83
  rating: responseData.rating,
60
84
  feedback: responseData.feedback || '',
61
85
  answers: responseData.answers || {},
86
+ ...(respondent.respondent_id && {
87
+ respondent_id: respondent.respondent_id,
88
+ }),
89
+ ...(respondent.email && { email: respondent.email }),
62
90
  };
63
91
 
64
92
  return this.api._handleAuthRetry(async () => {
@@ -94,7 +94,11 @@ export class FeedbackSDK {
94
94
 
95
95
  try {
96
96
  const result = await this.apiService.getActiveSurveys(context);
97
- return result.data || [];
97
+ const surveys = result.data || [];
98
+ if (context.includeIneligible) {
99
+ return surveys;
100
+ }
101
+ return surveys.filter((survey) => this._isSurveyEligible(survey));
98
102
  } catch (error) {
99
103
  this.eventBus.emit('sdk:error', { error });
100
104
  throw new SDKError(
@@ -111,7 +115,12 @@ export class FeedbackSDK {
111
115
  );
112
116
  }
113
117
 
114
- const surveys = await this.getActiveSurveys();
118
+ const { context = {}, ...displayOptions } = options;
119
+ const surveys = await this.getActiveSurveys({
120
+ ...context,
121
+ includeEligibility: true,
122
+ includeIneligible: true,
123
+ });
115
124
  const surveyConfig = surveys.find((s) => s.id === surveyId);
116
125
 
117
126
  if (!surveyConfig) {
@@ -120,6 +129,15 @@ export class FeedbackSDK {
120
129
  );
121
130
  }
122
131
 
132
+ if (!this._isSurveyEligible(surveyConfig)) {
133
+ this.eventBus.emit('survey:suppressed', {
134
+ surveyId,
135
+ reason: this._getSurveyIneligibilityReason(surveyConfig),
136
+ survey: surveyConfig,
137
+ });
138
+ return null;
139
+ }
140
+
123
141
  return this.showSurvey({
124
142
  surveyId: surveyConfig.id,
125
143
  surveyType: surveyConfig.type,
@@ -128,7 +146,7 @@ export class FeedbackSDK {
128
146
  lowLabel: surveyConfig.low_label,
129
147
  highLabel: surveyConfig.high_label,
130
148
  customQuestions: surveyConfig.questions,
131
- ...options,
149
+ ...displayOptions,
132
150
  });
133
151
  }
134
152
 
@@ -139,6 +157,15 @@ export class FeedbackSDK {
139
157
  );
140
158
  }
141
159
 
160
+ if (!this._isSurveyEligible(options)) {
161
+ this.eventBus.emit('survey:suppressed', {
162
+ surveyId: options.surveyId || options.id || null,
163
+ reason: this._getSurveyIneligibilityReason(options),
164
+ survey: options,
165
+ });
166
+ return null;
167
+ }
168
+
142
169
  const surveyWidget = this.createWidget('survey', {
143
170
  surveyId: options.surveyId,
144
171
  surveyType: options.surveyType || options.type || 'nps',
@@ -149,6 +176,8 @@ export class FeedbackSDK {
149
176
  lowLabel: options.lowLabel,
150
177
  highLabel: options.highLabel,
151
178
  customQuestions: options.customQuestions,
179
+ respondentId: options.respondentId,
180
+ email: options.email,
152
181
  onSubmit: options.onSubmit,
153
182
  onDismiss: options.onDismiss,
154
183
  });
@@ -159,6 +188,56 @@ export class FeedbackSDK {
159
188
  return surveyWidget;
160
189
  }
161
190
 
191
+ _isSurveyEligible(survey = {}) {
192
+ const shouldShow = this._getSurveyField(survey, ['shouldShow', 'should_show']);
193
+ if (typeof shouldShow === 'boolean') {
194
+ return shouldShow;
195
+ }
196
+
197
+ const eligible = this._getSurveyField(survey, [
198
+ 'eligible',
199
+ 'isEligible',
200
+ 'is_eligible',
201
+ ]);
202
+ if (typeof eligible === 'boolean') {
203
+ return eligible;
204
+ }
205
+
206
+ const isAnswered = this._getSurveyField(survey, ['isAnswered', 'is_answered']);
207
+ if (typeof isAnswered === 'boolean') {
208
+ return !isAnswered;
209
+ }
210
+
211
+ return true;
212
+ }
213
+
214
+ _getSurveyIneligibilityReason(survey = {}) {
215
+ const explicitReason = this._getSurveyField(survey, [
216
+ 'reason',
217
+ 'suppressionReason',
218
+ 'suppression_reason',
219
+ ]);
220
+ if (explicitReason) {
221
+ return explicitReason;
222
+ }
223
+
224
+ const isAnswered = this._getSurveyField(survey, ['isAnswered', 'is_answered']);
225
+ if (isAnswered === true) {
226
+ return 'already_answered';
227
+ }
228
+
229
+ return 'ineligible';
230
+ }
231
+
232
+ _getSurveyField(survey, fields) {
233
+ for (const field of fields) {
234
+ if (survey[field] !== undefined && survey[field] !== null) {
235
+ return survey[field];
236
+ }
237
+ }
238
+ return null;
239
+ }
240
+
162
241
  showChangelog(options = {}) {
163
242
  if (!this.initialized) {
164
243
  throw new SDKError(
@@ -13,6 +13,8 @@ export class SurveyWidget extends BaseWidget {
13
13
  lowLabel: options.lowLabel || null,
14
14
  highLabel: options.highLabel || null,
15
15
  customQuestions: options.customQuestions || [],
16
+ respondentId: options.respondentId || null,
17
+ email: options.email || null,
16
18
  onSubmit: options.onSubmit || null,
17
19
  onDismiss: options.onDismiss || null,
18
20
  };
@@ -381,10 +383,14 @@ export class SurveyWidget extends BaseWidget {
381
383
  return;
382
384
  }
383
385
 
386
+ const respondent = this._getRespondentContext();
387
+
384
388
  const responseData = {
385
389
  rating: this.surveyState.score,
386
390
  feedback: this.surveyState.feedback,
387
391
  answers: this.surveyState.customAnswers,
392
+ ...(respondent.respondentId && { respondentId: respondent.respondentId }),
393
+ ...(respondent.email && { email: respondent.email }),
388
394
  };
389
395
 
390
396
  const response = {
@@ -413,6 +419,34 @@ export class SurveyWidget extends BaseWidget {
413
419
  this._showSuccessNotification();
414
420
  }
415
421
 
422
+ _getRespondentContext() {
423
+ const sdkUserContext =
424
+ typeof this.sdk.getUserContext === 'function'
425
+ ? this.sdk.getUserContext() || {}
426
+ : {};
427
+ const apiUserContext =
428
+ this.apiService &&
429
+ typeof this.apiService.getUserContext === 'function'
430
+ ? this.apiService.getUserContext() || {}
431
+ : {};
432
+ const localUserContext = this.options.userContext || {};
433
+
434
+ return {
435
+ respondentId:
436
+ this.surveyOptions.respondentId ||
437
+ localUserContext.user_id ||
438
+ sdkUserContext.user_id ||
439
+ apiUserContext.user_id ||
440
+ null,
441
+ email:
442
+ this.surveyOptions.email ||
443
+ localUserContext.email ||
444
+ sdkUserContext.email ||
445
+ apiUserContext.email ||
446
+ null,
447
+ };
448
+ }
449
+
416
450
  async _handleDismiss() {
417
451
  if (this.surveyOptions.surveyId) {
418
452
  try {
package/types/index.d.ts CHANGED
@@ -78,6 +78,8 @@ declare module '@product7/feedback-sdk' {
78
78
  lowLabel?: string | null;
79
79
  highLabel?: string | null;
80
80
  customQuestions?: SurveyQuestion[];
81
+ respondentId?: string | null;
82
+ email?: string | null;
81
83
  theme?: 'light' | 'dark';
82
84
  onSubmit?: (response: SurveyWidgetResponse) => void;
83
85
  onDismiss?: () => void;