Transactional NPS Survey

Transactional NPS surveys capture customer sentiment at the moment of truth - right after a purchase or service interaction. Unlike relationship NPS sent periodically, transactional NPS provides immediate feedback tied to specific experiences. This template includes smart conditional logic that adapts follow-up questions based on NPS score, emoji-based quick satisfaction check, and touchpoint analysis to identify what drove the customer's rating.

Customer ExperiencePopular

Try the Form

Your feedback helps us serve you better. This takes less than 2 minutes.
About Your Transaction
Quick Reaction
Recommendation Score
Not at all likely
Extremely likely
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
export function npsTransactionalSurvey(form: FormTs) {
// Transactional NPS Survey - Post-Purchase/Post-Transaction Feedback
// Demonstrates: RatingScale (NPS), EmojiRating, MatrixQuestion, SuggestionChips, Dropdown, dynamic styling
 
// ============================================
// HEADER
// ============================================
form.addRow(row => {
row.addTextPanel('header', {
label: 'How Was Your Experience?',
computedValue: () => 'Your feedback helps us serve you better. This takes less than 2 minutes.',
customStyles: {
backgroundColor: '#0ea5e9',
color: 'white',
padding: '24px',
borderRadius: '12px',
textAlign: 'center'
}
});
});
 
// ============================================
// SECTION 1: Transaction Context
// ============================================
const contextSection = form.addSubform('context', {
title: 'About Your Transaction'
});
 
contextSection.addRow(row => {
row.addDropdown('transactionType', {
label: 'What type of transaction did you complete?',
options: [
{ id: 'purchase', name: 'Product Purchase' },
{ id: 'service', name: 'Service Appointment' },
{ id: 'return', name: 'Return/Exchange' },
{ id: 'support', name: 'Support Interaction' },
{ id: 'subscription', name: 'Subscription Renewal' },
{ id: 'other', name: 'Other' }
],
placeholder: 'Select transaction type',
isRequired: true
}, '1fr');
row.addDropdown('channel', {
label: 'How did you complete this transaction?',
options: [
{ id: 'online', name: 'Website' },
{ id: 'mobile', name: 'Mobile App' },
{ id: 'store', name: 'In-Store' },
{ id: 'phone', name: 'Phone' },
{ id: 'chat', name: 'Live Chat' }
],
placeholder: 'Select channel',
isRequired: true
}, '1fr');
});
 
// ============================================
// SECTION 2: Quick Sentiment (Emoji Rating)
// ============================================
const sentimentSection = form.addSubform('sentiment', {
title: 'Quick Reaction',
customStyles: { backgroundColor: '#f0f9ff', padding: '16px', borderRadius: '8px' }
});
 
sentimentSection.addRow(row => {
row.addEmojiRating('quickSentiment', {
label: 'How do you feel about your recent transaction?',
preset: 'satisfaction',
size: 'lg',
showLabels: true,
alignment: 'center'
});
});
 
// ============================================
// SECTION 3: NPS Score
// ============================================
const npsSection = form.addSubform('npsSection', {
title: 'Recommendation Score',
customStyles: () => {
const category = npsSection.ratingScale('npsScore')?.npsCategory();
if (category === 'promoter') return { backgroundColor: '#dcfce7', padding: '16px', borderRadius: '8px' };
if (category === 'passive') return { backgroundColor: '#fef9c3', padding: '16px', borderRadius: '8px' };
if (category === 'detractor') return { backgroundColor: '#fee2e2', padding: '16px', borderRadius: '8px' };
return { padding: '16px', borderRadius: '8px', border: '1px dashed #e2e8f0' };
}
});
 
npsSection.addRow(row => {
row.addRatingScale('npsScore', {
preset: 'nps',
label: () => {
const type = contextSection.dropdown('transactionType')?.value();
if (type === 'purchase') return 'Based on this purchase, how likely are you to recommend us?';
if (type === 'service') return 'Based on this service, how likely are you to recommend us?';
if (type === 'return') return 'Based on your return experience, how likely are you to recommend us?';
if (type === 'support') return 'Based on this support interaction, how likely are you to recommend us?';
return 'How likely are you to recommend us based on this experience?';
},
showCategoryLabel: true,
showSegmentColors: true,
showConfettiOnPromoter: true,
isRequired: true
});
});
 
// Dynamic follow-up based on NPS category
npsSection.addSpacer({ height: '16px' });
 
npsSection.addRow(row => {
row.addTextarea('npsReason', {
label: () => {
const category = npsSection.ratingScale('npsScore')?.npsCategory();
switch (category) {
case 'promoter': return "We're thrilled! What made this transaction great?";
case 'passive': return "Thanks for your feedback! What could have made it a 9 or 10?";
case 'detractor': return "We're sorry to hear that. What went wrong?";
default: return 'Tell us more about your experience';
}
},
placeholder: () => {
const category = npsSection.ratingScale('npsScore')?.npsCategory();
if (category === 'promoter') return 'Share what exceeded your expectations...';
if (category === 'passive') return 'What one thing would improve your experience...';
if (category === 'detractor') return 'Help us understand so we can make it right...';
return 'Your feedback...';
},
rows: 3,
autoExpand: true,
isVisible: () => npsSection.ratingScale('npsScore')?.value() !== null
});
});
 
// ============================================
// SECTION 4: Touchpoint Ratings (Matrix)
// ============================================
const touchpointsSection = form.addSubform('touchpoints', {
title: 'Rate Your Experience',
isVisible: () => npsSection.ratingScale('npsScore')?.value() !== null
});
 
touchpointsSection.addRow(row => {
row.addMatrixQuestion('touchpointRatings', {
label: 'How would you rate each aspect of your transaction?',
rows: () => {
const channel = contextSection.dropdown('channel')?.value();
const baseRows = [
{ id: 'ease', label: 'Ease of transaction', isRequired: true },
{ id: 'speed', label: 'Speed/Timeliness' },
{ id: 'staff', label: 'Staff helpfulness' },
{ id: 'communication', label: 'Communication' }
];
 
if (channel === 'online' || channel === 'mobile') {
return [
...baseRows,
{ id: 'website', label: 'Website/App experience' },
{ id: 'checkout', label: 'Checkout process' }
];
}
if (channel === 'store') {
return [
...baseRows,
{ id: 'store_layout', label: 'Store layout' },
{ id: 'product_availability', label: 'Product availability' }
];
}
return baseRows;
},
columns: [
{ id: 'poor', label: 'Poor' },
{ id: 'fair', label: 'Fair' },
{ id: 'good', label: 'Good' },
{ id: 'excellent', label: 'Excellent' }
],
striped: true,
fullWidth: true
});
});
 
// ============================================
// SECTION 5: What Influenced Your Score (Promoters)
// ============================================
const promoterSection = form.addSubform('promoterDrivers', {
title: 'What Made It Great?',
isVisible: () => npsSection.ratingScale('npsScore')?.npsCategory() === 'promoter',
customStyles: { backgroundColor: '#dcfce7', padding: '16px', borderRadius: '8px' }
});
 
promoterSection.addRow(row => {
row.addSuggestionChips('positiveDrivers', {
label: 'Select what stood out (pick up to 4)',
suggestions: [
{ id: 'quality', name: 'Product/Service quality' },
{ id: 'value', name: 'Great value' },
{ id: 'staff', name: 'Helpful staff' },
{ id: 'fast', name: 'Fast service' },
{ id: 'easy', name: 'Easy process' },
{ id: 'selection', name: 'Good selection' },
{ id: 'location', name: 'Convenient location' },
{ id: 'communication', name: 'Clear communication' }
],
max: 4,
alignment: 'center'
});
});
 
// ============================================
// SECTION 6: Improvement Areas (Detractors/Passives)
// ============================================
const improvementSection = form.addSubform('improvementDrivers', {
title: 'What Could We Improve?',
isVisible: () => {
const category = npsSection.ratingScale('npsScore')?.npsCategory();
return category === 'detractor' || category === 'passive';
},
customStyles: () => {
const category = npsSection.ratingScale('npsScore')?.npsCategory();
if (category === 'detractor') return { backgroundColor: '#fee2e2', padding: '16px', borderRadius: '8px' };
return { backgroundColor: '#fef9c3', padding: '16px', borderRadius: '8px' };
}
});
 
improvementSection.addRow(row => {
row.addSuggestionChips('improvementAreas', {
label: 'Select areas that need improvement',
suggestions: [
{ id: 'quality', name: 'Product/Service quality' },
{ id: 'price', name: 'Pricing' },
{ id: 'staff', name: 'Staff attitude' },
{ id: 'wait', name: 'Wait time' },
{ id: 'process', name: 'Complex process' },
{ id: 'availability', name: 'Availability' },
{ id: 'location', name: 'Location/Access' },
{ id: 'communication', name: 'Poor communication' }
],
alignment: 'center'
});
});
 
// Specific issue for detractors
improvementSection.addSpacer({ height: '12px' });
 
improvementSection.addRow(row => {
row.addTextarea('specificIssue', {
label: 'Please describe the specific issue (optional)',
placeholder: 'Tell us exactly what happened so we can address it...',
rows: 3,
isVisible: () => npsSection.ratingScale('npsScore')?.npsCategory() === 'detractor'
});
});
 
// ============================================
// SECTION 7: Follow-up Consent
// ============================================
const followupSection = form.addSubform('followup', {
title: 'Stay Connected',
isVisible: () => npsSection.ratingScale('npsScore')?.value() !== null
});
 
followupSection.addRow(row => {
row.addThumbRating('wouldReturn', {
label: 'Would you transact with us again?',
showLabels: true,
upLabel: 'Yes',
downLabel: 'No',
size: 'md',
alignment: 'center'
});
});
 
followupSection.addRow(row => {
row.addCheckbox('allowContact', {
label: () => {
const category = npsSection.ratingScale('npsScore')?.npsCategory();
if (category === 'detractor') return 'I would like someone to contact me about my experience';
return 'You may contact me about special offers and updates';
}
});
});
 
followupSection.addRow(row => {
row.addEmail('contactEmail', {
label: 'Email address',
placeholder: 'your@email.com',
isRequired: () => followupSection.checkbox('allowContact')?.value() === true,
isVisible: () => followupSection.checkbox('allowContact')?.value() === true
});
});
 
// ============================================
// SECTION 8: Summary
// ============================================
const summarySection = form.addSubform('summary', {
title: 'Feedback Summary',
isVisible: () => npsSection.ratingScale('npsScore')?.value() !== null
});
 
summarySection.addRow(row => {
row.addTextPanel('summaryContent', {
computedValue: () => {
const score = npsSection.ratingScale('npsScore')?.value();
const category = npsSection.ratingScale('npsScore')?.npsCategory();
const sentiment = sentimentSection.emojiRating('quickSentiment')?.value();
const transactionType = contextSection.dropdown('transactionType')?.value();
const channel = contextSection.dropdown('channel')?.value();
const wouldReturn = followupSection.thumbRating('wouldReturn')?.value();
 
if (score === null || score === undefined) return '';
 
let emoji = category === 'promoter' ? '🎉' : category === 'passive' ? '🤔' : '😔';
 
let summary = `${emoji} Transaction Feedback Summary\n`;
summary += `${'═'.repeat(30)}\n\n`;
summary += `📊 NPS Score: ${score}/10 (${category?.charAt(0).toUpperCase()}${category?.slice(1)})\n`;
 
if (transactionType) {
const typeLabels: Record<string, string> = {
'purchase': 'Product Purchase',
'service': 'Service Appointment',
'return': 'Return/Exchange',
'support': 'Support Interaction',
'subscription': 'Subscription Renewal',
'other': 'Other'
};
summary += `🛒 Transaction: ${typeLabels[transactionType] || transactionType}\n`;
}
 
if (channel) {
const channelLabels: Record<string, string> = {
'online': 'Website',
'mobile': 'Mobile App',
'store': 'In-Store',
'phone': 'Phone',
'chat': 'Live Chat'
};
summary += `📱 Channel: ${channelLabels[channel] || channel}\n`;
}
 
if (sentiment) {
const sentimentLabels: Record<string, string> = {
'very-bad': '😢 Very Unsatisfied',
'bad': '😕 Unsatisfied',
'neutral': '😐 Neutral',
'good': '😊 Satisfied',
'excellent': '😃 Very Satisfied'
};
summary += `\n💭 Quick Sentiment: ${sentimentLabels[sentiment] || sentiment}`;
}
 
if (wouldReturn !== null && wouldReturn !== undefined) {
summary += `\n🔄 Would Return: ${wouldReturn === 'up' ? 'Yes' : 'No'}`;
}
 
return summary;
},
customStyles: () => {
const category = npsSection.ratingScale('npsScore')?.npsCategory();
const baseStyles = {
padding: '16px',
borderRadius: '8px',
whiteSpace: 'pre-wrap',
fontFamily: 'monospace',
fontSize: '14px'
};
 
if (category === 'promoter') {
return { ...baseStyles, backgroundColor: '#dcfce7', borderLeft: '4px solid #22c55e' };
} else if (category === 'passive') {
return { ...baseStyles, backgroundColor: '#fef9c3', borderLeft: '4px solid #eab308' };
} else if (category === 'detractor') {
return { ...baseStyles, backgroundColor: '#fee2e2', borderLeft: '4px solid #ef4444' };
}
return baseStyles;
}
});
});
 
// ============================================
// FORM CONFIGURATION
// ============================================
form.configureSubmitButton({
label: () => {
const category = npsSection.ratingScale('npsScore')?.npsCategory();
if (category === 'promoter') return 'Submit & Share the Love!';
if (category === 'detractor') return 'Submit Feedback';
return 'Submit';
},
isVisible: () => npsSection.ratingScale('npsScore')?.value() !== null
});
 
form.configureCompletionScreen({
type: 'text',
title: () => {
const category = npsSection.ratingScale('npsScore')?.npsCategory();
if (category === 'promoter') return 'Thank you for your amazing feedback!';
if (category === 'detractor') return 'Thank you for letting us know';
return 'Thank you for your feedback!';
},
message: () => {
const category = npsSection.ratingScale('npsScore')?.npsCategory();
if (category === 'promoter') return "We're so glad you had a great experience! Your recommendation means the world to us.";
if (category === 'detractor') return "We're sorry your experience wasn't up to par. A team member will review your feedback and may reach out to make things right.";
return 'Your feedback helps us improve. We appreciate you taking the time to share your thoughts.';
}
});
}
 

Frequently Asked Questions

What is Transactional NPS vs Relationship NPS?

Transactional NPS measures satisfaction with a specific interaction (purchase, support call, delivery), sent immediately after the event. Relationship NPS measures overall brand loyalty, sent periodically (quarterly/annually). Both are valuable - transactional for operational improvements, relationship for strategic insights.

When should I send a Transactional NPS survey?

Send within 24 hours of the transaction while the experience is fresh. Ideal triggers: order confirmation, delivery completion, support ticket closure, checkout completion, or service appointment end. Avoid sending during business hours when customers may be busy.

How do I avoid survey fatigue with Transactional NPS?

Implement rules: survey each customer max once per 30 days, regardless of transaction count. Prioritize first-time customers and high-value purchases. Keep surveys short (under 2 minutes). Consider sampling 10-20% of transactions for high-volume businesses.

What's a good response rate for Transactional NPS?

Transactional NPS typically sees 20-40% response rates - higher than relationship NPS (10-15%) because the experience is recent. Mobile-optimized forms and timely delivery boost rates. Incentives can help but may bias results toward positive scores.

How do I act on Transactional NPS feedback?

Create alerts for detractor responses (0-6) for immediate follow-up. Analyze trends by touchpoint to identify systemic issues. Close the loop with unhappy customers within 24-48 hours. Share promoter feedback with frontline staff for motivation.