Feature Voting & Prioritization Form

The Feature Voting & Prioritization Form helps product teams make data-driven roadmap decisions by collecting structured user input. Users can vote on proposed features, rate their importance, and share their specific use cases. The weighted voting system reveals which features matter most to your users, while the impact assessment questions help you understand why. With matrix-based comparisons and optional detailed feedback, you'll have everything needed to prioritize with confidence.

Product FeedbackPopular

Try the Form

Vote on the features you want most. Your input directly shapes our product roadmap.
Select Your Top Features (0/3)
Choose up to 3 features that would help you the most.
 
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 featureVotingForm(form: FormTs) {
// Feature Voting & Prioritization Form
// Demonstrates: MatrixQuestion, CheckboxList, StarRating, RatingScale,
// SuggestionChips, Slider, RadioButton, computed values, dynamic styling
 
// State for tracking votes
const votesState = form.state<string[]>([]);
const maxVotes = 3;
 
// ============================================
// HEADER
// ============================================
form.addRow(row => {
row.addTextPanel('header', {
label: 'Help Us Build What Matters',
computedValue: () => 'Vote on the features you want most. Your input directly shapes our product roadmap.',
customStyles: {
backgroundColor: '#7c3aed',
color: 'white',
padding: '28px',
borderRadius: '12px',
textAlign: 'center',
fontSize: '15px'
}
});
});
 
// ============================================
// SECTION 1: Feature Voting
// ============================================
const votingSection = form.addSubform('voting', {
title: () => {
const votes = votingSection.checkboxList('featureVotes')?.value() || [];
return `Select Your Top Features (${votes.length}/${maxVotes})`;
},
customStyles: () => {
const votes = votingSection.checkboxList('featureVotes')?.value() || [];
if (votes.length === maxVotes) {
return { backgroundColor: '#ecfdf5', padding: '20px', borderRadius: '10px', border: '2px solid #10b981' };
}
return { backgroundColor: '#faf5ff', padding: '20px', borderRadius: '10px' };
}
});
 
votingSection.addRow(row => {
row.addTextPanel('votingInstructions', {
computedValue: () => {
const votes = votingSection.checkboxList('featureVotes')?.value() || [];
if (votes.length === 0) return `Choose up to ${maxVotes} features that would help you the most.`;
if (votes.length < maxVotes) return `${maxVotes - votes.length} vote${maxVotes - votes.length > 1 ? 's' : ''} remaining.`;
return `✓ All ${maxVotes} votes cast! You can change your selections below.`;
},
customStyles: () => {
const votes = votingSection.checkboxList('featureVotes')?.value() || [];
if (votes.length === maxVotes) return { color: '#10b981', fontWeight: '500' };
return { color: '#6b7280', fontStyle: 'italic' };
}
});
});
 
votingSection.addRow(row => {
row.addCheckboxList('featureVotes', {
label: 'Available features to vote on:',
options: [
{ id: 'dark-mode', name: '🌙 Dark Mode - Full dark theme for the application' },
{ id: 'mobile-app', name: '📱 Mobile App - Native iOS and Android applications' },
{ id: 'api-access', name: '🔌 API Access - Public API for integrations' },
{ id: 'collaboration', name: '👥 Real-time Collaboration - Work together with team' },
{ id: 'templates', name: '📋 Template Library - Pre-built templates and examples' },
{ id: 'analytics', name: '📊 Advanced Analytics - Detailed reports and insights' },
{ id: 'integrations', name: '🔗 More Integrations - Connect with popular tools' },
{ id: 'ai-features', name: '🤖 AI-Powered Features - Smart automation and suggestions' },
{ id: 'offline-mode', name: '📴 Offline Mode - Work without internet connection' },
{ id: 'export-options', name: '📤 Export Options - More formats and customization' }
],
orientation: 'vertical',
max: maxVotes
});
});
 
// ============================================
// SECTION 2: Priority Ranking Matrix
// ============================================
const prioritySection = form.addSubform('priority', {
title: 'Rate Feature Importance',
isVisible: () => {
const votes = votingSection.checkboxList('featureVotes')?.value() || [];
return votes.length > 0;
}
});
 
prioritySection.addRow(row => {
row.addTextPanel('priorityIntro', {
computedValue: () => 'Rate how important each of your selected features is to you:',
customStyles: { color: '#6b7280', marginBottom: '12px' }
});
});
 
prioritySection.addRow(row => {
row.addMatrixQuestion('featureImportance', {
label: '',
rows: () => {
const votes = votingSection.checkboxList('featureVotes')?.value() || [];
const featureLabels: Record<string, string> = {
'dark-mode': 'Dark Mode',
'mobile-app': 'Mobile App',
'api-access': 'API Access',
'collaboration': 'Real-time Collaboration',
'templates': 'Template Library',
'analytics': 'Advanced Analytics',
'integrations': 'More Integrations',
'ai-features': 'AI-Powered Features',
'offline-mode': 'Offline Mode',
'export-options': 'Export Options'
};
return votes.map(v => ({
id: v,
label: featureLabels[v] || v,
isRequired: true
}));
},
columns: [
{ id: 'nice', label: 'Nice to Have' },
{ id: 'important', label: 'Important' },
{ id: 'critical', label: 'Critical' }
],
striped: true,
fullWidth: true
});
});
 
// ============================================
// SECTION 3: Use Case Details
// ============================================
const useCaseSection = form.addSubform('useCase', {
title: 'Your Use Case',
isVisible: () => {
const votes = votingSection.checkboxList('featureVotes')?.value() || [];
return votes.length > 0;
},
customStyles: { backgroundColor: '#f5f3ff', padding: '20px', borderRadius: '10px' }
});
 
useCaseSection.addRow(row => {
row.addRadioButton('userRole', {
label: 'What best describes your role?',
options: [
{ id: 'individual', name: 'Individual User' },
{ id: 'team-lead', name: 'Team Lead / Manager' },
{ id: 'developer', name: 'Developer / Technical' },
{ id: 'designer', name: 'Designer / Creative' },
{ id: 'business', name: 'Business / Strategy' },
{ id: 'other', name: 'Other' }
],
orientation: 'horizontal'
}, '1fr');
row.addRadioButton('teamSize', {
label: 'Team size',
options: [
{ id: 'solo', name: 'Just me' },
{ id: 'small', name: '2-10' },
{ id: 'medium', name: '11-50' },
{ id: 'large', name: '50+' }
],
orientation: 'horizontal'
}, '1fr');
});
 
useCaseSection.addRow(row => {
row.addSlider('usageFrequency', {
label: 'How often do you use our product?',
min: 1,
max: 5,
step: 1,
showValue: false,
defaultValue: 3
}, '1fr');
row.addTextPanel('usageLabel', {
computedValue: () => {
const freq = useCaseSection.slider('usageFrequency')?.value();
const labels: Record<number, string> = {
1: 'Rarely (monthly)',
2: 'Occasionally (weekly)',
3: 'Regularly (few times/week)',
4: 'Frequently (daily)',
5: 'Constantly (multiple times/day)'
};
return labels[freq ?? 3] || '';
},
customStyles: { fontSize: '14px', color: '#7c3aed', fontWeight: '500' }
}, '1fr');
});
 
// ============================================
// SECTION 4: Impact Assessment
// ============================================
const impactSection = form.addSubform('impact', {
title: 'Potential Impact',
isVisible: () => {
const votes = votingSection.checkboxList('featureVotes')?.value() || [];
return votes.length > 0;
}
});
 
impactSection.addRow(row => {
row.addRatingScale('productivityImpact', {
label: 'How much would your top feature improve your productivity?',
preset: 'likert-5',
lowLabel: 'Minimal impact',
highLabel: 'Game changer',
alignment: 'center',
size: 'md'
});
});
 
impactSection.addRow(row => {
row.addSuggestionChips('benefitAreas', {
label: 'Which areas would benefit most?',
suggestions: [
{ id: 'speed', name: 'Work faster' },
{ id: 'quality', name: 'Better output' },
{ id: 'collaborate', name: 'Team collaboration' },
{ id: 'organize', name: 'Stay organized' },
{ id: 'automate', name: 'Automate tasks' },
{ id: 'insights', name: 'Get insights' }
],
alignment: 'center',
max: 3
});
});
 
// ============================================
// SECTION 5: Willingness to Pay
// ============================================
const paySection = form.addSubform('pay', {
title: 'Value Assessment',
isVisible: () => {
const votes = votingSection.checkboxList('featureVotes')?.value() || [];
return votes.length > 0;
},
customStyles: { backgroundColor: '#fefce8', padding: '20px', borderRadius: '10px' }
});
 
paySection.addRow(row => {
row.addRadioButton('willingToPay', {
label: 'Would you be willing to pay more for your top voted feature?',
options: [
{ id: 'yes-upgrade', name: 'Yes, I\'d upgrade my plan for it' },
{ id: 'yes-addon', name: 'Yes, as a paid add-on' },
{ id: 'included', name: 'Only if included in current plan' },
{ id: 'switch', name: 'I\'d consider switching from a competitor for it' }
],
orientation: 'vertical'
});
});
 
paySection.addRow(row => {
row.addStarRating('satisfactionWithRoadmap', {
label: 'How satisfied are you with our product direction overall?',
maxStars: 5,
size: 'lg',
alignment: 'center',
filledColor: '#eab308',
showConfettiOnMax: true
});
});
 
// ============================================
// SECTION 6: Feature Request
// ============================================
const requestSection = form.addSubform('request', {
title: 'Missing Something?',
isVisible: () => {
const votes = votingSection.checkboxList('featureVotes')?.value() || [];
return votes.length > 0;
}
});
 
requestSection.addRow(row => {
row.addTextarea('newFeatureIdea', {
label: 'Is there a feature you want that\'s not on the list?',
placeholder: 'Describe the feature you wish we would build...',
rows: 3,
autoExpand: true
});
});
 
requestSection.addRow(row => {
row.addTextarea('useCaseDescription', {
label: 'Tell us how you would use your top voted feature',
placeholder: 'Describe a specific scenario or workflow...',
rows: 3,
autoExpand: true
});
});
 
// ============================================
// SECTION 7: Summary
// ============================================
const summarySection = form.addSubform('summary', {
title: 'Your Votes Summary',
isVisible: () => {
const votes = votingSection.checkboxList('featureVotes')?.value() || [];
return votes.length > 0;
}
});
 
summarySection.addRow(row => {
row.addTextPanel('summaryContent', {
computedValue: () => {
const votes = votingSection.checkboxList('featureVotes')?.value() || [];
const importance = prioritySection.matrixQuestion('featureImportance')?.value() || {};
const productivity = impactSection.ratingScale('productivityImpact')?.value();
const benefits = impactSection.suggestionChips('benefitAreas')?.value() || [];
const payPref = paySection.radioButton('willingToPay')?.value();
const satisfaction = paySection.starRating('satisfactionWithRoadmap')?.value();
 
if (votes.length === 0) return '';
 
const featureLabels: Record<string, string> = {
'dark-mode': '🌙 Dark Mode',
'mobile-app': '📱 Mobile App',
'api-access': '🔌 API Access',
'collaboration': '👥 Collaboration',
'templates': '📋 Templates',
'analytics': '📊 Analytics',
'integrations': '🔗 Integrations',
'ai-features': '🤖 AI Features',
'offline-mode': '📴 Offline Mode',
'export-options': '📤 Export Options'
};
 
const importanceLabels: Record<string, string> = {
'nice': '○', 'important': '◐', 'critical': '●'
};
 
let summary = '🗳️ Feature Voting Summary\n';
summary += `${'═'.repeat(30)}\n\n`;
 
summary += `📊 Your Votes (${votes.length}/${maxVotes}):\n`;
summary += `${'─'.repeat(25)}\n`;
 
votes.forEach(v => {
const imp = importance[v] as string | undefined;
const impSymbol = imp ? importanceLabels[imp] || '' : '';
summary += `${featureLabels[v] || v} ${impSymbol}\n`;
});
 
summary += `\n○ Nice to Have ◐ Important ● Critical\n`;
 
if (productivity !== null && productivity !== undefined) {
summary += `\n⚡ Productivity Impact: ${productivity}/5`;
}
 
if (benefits.length > 0) {
summary += `\n🎯 Benefit Areas: ${benefits.length} selected`;
}
 
if (payPref) {
const payLabels: Record<string, string> = {
'yes-upgrade': 'Would upgrade plan',
'yes-addon': 'Would pay as add-on',
'included': 'If included only',
'switch': 'Would switch from competitor'
};
summary += `\n💰 Payment: ${payLabels[payPref] || payPref}`;
}
 
if (satisfaction !== null && satisfaction !== undefined) {
summary += `\n\n⭐ Roadmap Satisfaction: ${'★'.repeat(satisfaction)}${'☆'.repeat(5 - satisfaction)}`;
}
 
return summary;
},
customStyles: {
padding: '20px',
borderRadius: '10px',
backgroundColor: '#f5f3ff',
whiteSpace: 'pre-wrap',
fontFamily: 'monospace',
fontSize: '14px',
borderLeft: '4px solid #7c3aed'
}
});
});
 
// ============================================
// FORM CONFIGURATION
// ============================================
form.configureSubmitButton({
label: () => {
const votes = votingSection.checkboxList('featureVotes')?.value() || [];
if (votes.length === 0) return 'Please select at least one feature';
return `Submit ${votes.length} Vote${votes.length > 1 ? 's' : ''}`;
},
isVisible: () => {
const votes = votingSection.checkboxList('featureVotes')?.value() || [];
return votes.length > 0;
}
});
 
form.configureCompletionScreen({
type: 'text',
title: 'Thank you for voting!',
message: 'Your votes help us prioritize what to build next. We review all feature votes monthly and share updates on our roadmap. Watch for announcements about features you voted for!'
});
}
 

Frequently Asked Questions

How do I use this data for roadmap prioritization?

Combine voting data with: user segment weighting (enterprise votes may count more), effort estimates from engineering, strategic alignment scores, and revenue impact. Create a weighted score formula that balances user demand with business objectives.

Should I limit how many features users can vote for?

Yes, limiting votes (3-5 max) forces users to make trade-offs, revealing their true priorities. Unlimited votes often result in users selecting everything, providing less useful differentiation data.

How do I prevent recency bias in feature voting?

Randomize the order features appear to each user. Include features from different time periods. Provide equal context for each option. Consider running multiple voting rounds over time to smooth out temporal biases.

What if the most-voted feature isn't feasible to build?

Be transparent with users. Communicate why their top choice can't be prioritized (technical constraints, strategic misalignment). Show the features you are building based on their input. This builds trust even when you can't deliver everything.

How often should I run feature voting surveys?

Quarterly works well for most products. Run ad-hoc surveys when facing major prioritization decisions. Avoid survey fatigue by targeting different user segments. Keep the same core methodology for trend analysis.

Should feature voting be anonymous?

Allow optional identification. Anonymous voting increases honest responses. Identified responses let you segment by user type, plan, or usage patterns - valuable for understanding different user needs. Offer both options.