export function trialExitSurvey(form: FormTs) {
// Trial Exit Survey - Understanding why users don't convert
// Demonstrates: Pages (multi-page), RadioButton, CheckboxList, MatrixQuestion, conditional flows, dynamic content
// ============================================
// STATE
// ============================================
const primaryReason = form.state<string | null>(null);
const trialRating = form.state<number | null>(null);
// ============================================
// HEADER
// ============================================
form.addRow(row => {
row.addTextPanel('header', {
label: 'Before You Go...',
computedValue: () => "We'd love to understand your experience to make our product better.",
customStyles: {
background: 'linear-gradient(135deg, #f093fb 0%, #f5576c 100%)',
color: 'white',
padding: '24px',
borderRadius: '12px',
textAlign: 'center'
}
});
});
// ============================================
// MULTI-PAGE WIZARD
// ============================================
const pages = form.addPages('trialPages');
// ============================================
// PAGE 1: Primary Reason
// ============================================
const page1 = pages.addPage('reason');
const reasonSection = page1.addSubform('reasonSection', {
title: 'Step 1: Why Are You Leaving?'
});
reasonSection.addRow(row => {
row.addRadioButton('primaryReason', {
label: 'What is the main reason you decided not to continue?',
options: [
{ id: 'pricing', name: 'Pricing is too high for my budget' },
{ id: 'features', name: 'Missing features I need' },
{ id: 'complex', name: 'Too complex or hard to learn' },
{ id: 'time', name: "Didn't have enough time to evaluate" },
{ id: 'alternative', name: 'Found a better alternative' },
{ id: 'project', name: 'Project or priorities changed' },
{ id: 'other', name: 'Other reason' }
],
orientation: 'vertical',
isRequired: true,
onValueChange: (val) => primaryReason.set(val ?? null)
});
});
reasonSection.addRow(row => {
row.addTextarea('otherReason', {
label: 'Please specify:',
placeholder: 'Tell us more about your reason...',
rows: 2,
isVisible: () => reasonSection.radioButton('primaryReason')?.value() === 'other',
isRequired: () => reasonSection.radioButton('primaryReason')?.value() === 'other'
});
});
// ============================================
// PAGE 2: Reason-specific follow-up
// ============================================
const page2 = pages.addPage('details');
// --- Pricing Follow-up ---
const pricingSection = page2.addSubform('pricingDetails', {
title: 'Step 2: Pricing Feedback',
isVisible: () => primaryReason() === 'pricing'
});
pricingSection.addRow(row => {
row.addRadioButton('budgetFit', {
label: 'At what price point would you consider subscribing?',
options: [
{ id: 'half', name: 'At 50% of current price' },
{ id: 'third', name: 'At 30% less than current' },
{ id: 'quarter', name: 'At 25% less than current' },
{ id: 'free', name: 'Only if free' },
{ id: 'never', name: 'Would not subscribe at any price' }
],
orientation: 'vertical'
});
});
pricingSection.addRow(row => {
row.addCheckboxList('pricingFactors', {
label: 'What would make the current price acceptable?',
options: [
{ id: 'more_features', name: 'More features included' },
{ id: 'better_support', name: 'Better customer support' },
{ id: 'more_storage', name: 'More storage/limits' },
{ id: 'team_discount', name: 'Team/volume discounts' },
{ id: 'annual_discount', name: 'Bigger annual discount' },
{ id: 'nothing', name: 'Nothing - price is just too high' }
],
orientation: 'vertical'
});
});
// --- Missing Features Follow-up ---
const featuresSection = page2.addSubform('featuresDetails', {
title: 'Step 2: Missing Features',
isVisible: () => primaryReason() === 'features'
});
featuresSection.addRow(row => {
row.addCheckboxList('missingFeatures', {
label: 'Which features were you looking for?',
options: [
{ id: 'integrations', name: 'Integrations with other tools' },
{ id: 'reporting', name: 'Advanced reporting/analytics' },
{ id: 'automation', name: 'Automation capabilities' },
{ id: 'mobile', name: 'Mobile app' },
{ id: 'collaboration', name: 'Team collaboration' },
{ id: 'api', name: 'API access' },
{ id: 'custom', name: 'Customization options' },
{ id: 'other', name: 'Other features' }
],
orientation: 'vertical'
});
});
featuresSection.addSpacer({ height: '16px' });
featuresSection.addRow(row => {
row.addTextarea('featureDetails', {
label: 'Please describe the features you need:',
placeholder: 'Be as specific as possible - this helps our product team...',
rows: 3,
autoExpand: true
});
});
// --- Complexity Follow-up ---
const complexitySection = page2.addSubform('complexityDetails', {
title: 'Step 2: Usability Feedback',
isVisible: () => primaryReason() === 'complex'
});
complexitySection.addRow(row => {
row.addRatingScale('easeOfUse', {
label: 'How easy was the product to use?',
preset: 'ces',
size: 'md',
alignment: 'center'
});
});
complexitySection.addRow(row => {
row.addCheckboxList('complexityAreas', {
label: 'Which areas were most confusing?',
options: [
{ id: 'setup', name: 'Initial setup' },
{ id: 'navigation', name: 'Finding features/navigation' },
{ id: 'terminology', name: 'Understanding terminology' },
{ id: 'workflow', name: 'Creating workflows' },
{ id: 'docs', name: 'Documentation/help' },
{ id: 'all', name: 'Everything felt overwhelming' }
],
orientation: 'vertical'
});
});
complexitySection.addRow(row => {
row.addRadioButton('wouldHelp', {
label: 'Would personalized onboarding help you succeed?',
options: [
{ id: 'yes', name: 'Yes, I would try again with help' },
{ id: 'maybe', name: 'Maybe, depends on time investment' },
{ id: 'no', name: 'No, the product is not for me' }
],
orientation: 'vertical'
});
});
// --- Time Follow-up ---
const timeSection = page2.addSubform('timeDetails', {
title: 'Step 2: Trial Duration',
isVisible: () => primaryReason() === 'time'
});
timeSection.addRow(row => {
row.addRadioButton('trialLength', {
label: 'How much more time would you have needed?',
options: [
{ id: 'week', name: '1 more week' },
{ id: 'two_weeks', name: '2 more weeks' },
{ id: 'month', name: 'About a month' },
{ id: 'longer', name: 'More than a month' }
],
orientation: 'vertical'
});
});
timeSection.addRow(row => {
row.addCheckbox('extendTrial', {
label: 'I would like a trial extension to properly evaluate the product'
});
});
// --- Alternative Follow-up ---
const alternativeSection = page2.addSubform('alternativeDetails', {
title: 'Step 2: Competitive Insights',
isVisible: () => primaryReason() === 'alternative'
});
alternativeSection.addRow(row => {
row.addTextbox('competitor', {
label: 'Which alternative are you considering?',
placeholder: 'Product name (optional)'
});
});
alternativeSection.addRow(row => {
row.addCheckboxList('alternativeReasons', {
label: 'What makes the alternative more attractive?',
options: [
{ id: 'price', name: 'Better pricing' },
{ id: 'features', name: 'Has features I need' },
{ id: 'easier', name: 'Easier to use' },
{ id: 'familiar', name: 'Already familiar with it' },
{ id: 'team', name: 'Team already uses it' },
{ id: 'support', name: 'Better support/community' }
],
orientation: 'vertical'
});
});
// --- Project Changed (brief) ---
const projectSection = page2.addSubform('projectDetails', {
title: 'Step 2: Project Status',
isVisible: () => primaryReason() === 'project'
});
projectSection.addRow(row => {
row.addRadioButton('projectStatus', {
label: 'What happened to your project?',
options: [
{ id: 'paused', name: 'Project paused, may resume later' },
{ id: 'cancelled', name: 'Project cancelled' },
{ id: 'different', name: 'Going in a different direction' },
{ id: 'budget', name: 'Lost budget/funding' }
],
orientation: 'vertical'
});
});
projectSection.addRow(row => {
row.addCheckbox('keepInTouch', {
label: 'Keep me updated about product changes - I may return'
});
});
// ============================================
// PAGE 3: Trial Experience Rating
// ============================================
const page3 = pages.addPage('experience');
const experienceSection = page3.addSubform('experienceSection', {
title: 'Step 3: Your Trial Experience'
});
experienceSection.addRow(row => {
row.addStarRating('overallExperience', {
label: 'How would you rate your overall trial experience?',
maxStars: 5,
size: 'lg',
alignment: 'center',
onValueChange: (val) => trialRating.set(val ?? null)
});
});
experienceSection.addRow(row => {
row.addMatrixQuestion('featureRatings', {
label: 'Rate the features you tried:',
rows: [
{ id: 'ui', label: 'User Interface' },
{ id: 'performance', label: 'Speed & Performance' },
{ id: 'docs', label: 'Documentation & Help' },
{ id: 'onboarding', label: 'Onboarding Experience' }
],
columns: [
{ id: 'na', label: "Didn't Try" },
{ id: 'poor', label: 'Poor' },
{ id: 'ok', label: 'OK' },
{ id: 'good', label: 'Good' },
{ id: 'great', label: 'Great' }
],
striped: true,
fullWidth: true
});
});
experienceSection.addRow(row => {
row.addEmojiRating('emotionalResponse', {
label: 'How did using our product make you feel?',
preset: 'satisfaction',
size: 'lg',
showLabels: true,
alignment: 'center'
});
});
// ============================================
// PAGE 4: Final Thoughts & Contact
// ============================================
const page4 = pages.addPage('final');
const finalSection = page4.addSubform('finalSection', {
title: 'Step 4: Final Thoughts'
});
finalSection.addRow(row => {
row.addSlider('returnLikelihood', {
label: 'How likely are you to try us again in the future?',
min: 0,
max: 10,
step: 1,
defaultValue: 5,
showValue: true
});
});
finalSection.addSpacer({ height: '16px' });
finalSection.addRow(row => {
row.addTextarea('additionalFeedback', {
label: 'Any additional feedback or suggestions?',
placeholder: 'Your honest feedback helps us improve...',
rows: 3,
autoExpand: true
});
});
// --- Contact for follow-up ---
const contactSection = page4.addSubform('contactSection', {
title: 'Stay Connected',
isVisible: () => {
// Show if they rated highly or want to return
return trialRating() !== null && trialRating()! >= 3;
}
});
contactSection.addRow(row => {
row.addCheckbox('allowContact', {
label: 'You may contact me about product updates or special offers'
});
});
contactSection.addRow(row => {
row.addEmail('email', {
label: 'Email address',
placeholder: 'your@email.com',
isVisible: () => contactSection.checkbox('allowContact')?.value() === true,
isRequired: () => contactSection.checkbox('allowContact')?.value() === true
});
});
// ============================================
// SUMMARY SECTION
// ============================================
const summarySection = page4.addSubform('summary', {
title: 'Feedback Summary'
});
summarySection.addRow(row => {
row.addTextPanel('summaryContent', {
computedValue: () => {
const reason = primaryReason();
const rating = trialRating();
const returnChance = finalSection.slider('returnLikelihood')?.value() ?? 5;
const reasonLabels: Record<string, string> = {
'pricing': 'Pricing concerns',
'features': 'Missing features',
'complex': 'Complexity issues',
'time': 'Needed more time',
'alternative': 'Found alternative',
'project': 'Project changed',
'other': 'Other reason'
};
let summary = `Trial Exit Summary\n${'═'.repeat(25)}\n\n`;
summary += `Primary Reason: ${reasonLabels[reason || ''] || 'Not specified'}\n`;
if (rating) {
summary += `Experience Rating: ${'★'.repeat(rating)}${'☆'.repeat(5 - rating)}\n`;
}
summary += `Return Likelihood: ${returnChance}/10\n`;
if (returnChance >= 7) {
summary += '\n💚 High chance of return - nurture this lead!';
} else if (returnChance <= 3) {
summary += '\n🔴 Low return likelihood - focus on feedback';
}
return summary;
},
customStyles: () => {
const returnChance = finalSection.slider('returnLikelihood')?.value() ?? 5;
const baseStyles = {
padding: '16px',
borderRadius: '8px',
whiteSpace: 'pre-wrap',
fontFamily: 'monospace',
fontSize: '13px'
};
if (returnChance >= 7) {
return { ...baseStyles, backgroundColor: '#d1fae5', borderLeft: '4px solid #10b981' };
} else if (returnChance <= 3) {
return { ...baseStyles, backgroundColor: '#fee2e2', borderLeft: '4px solid #ef4444' };
}
return { ...baseStyles, backgroundColor: '#fef3c7', borderLeft: '4px solid #f59e0b' };
}
});
});
// ============================================
// FORM CONFIGURATION
// ============================================
form.configureSubmitButton({
label: 'Submit Feedback'
});
form.configureCompletionScreen({
type: 'text',
title: 'Thank You for Your Feedback!',
message: 'Your insights help us build a better product. We hope to see you again in the future. If your circumstances change, your trial data will be here waiting for you.'
});
}