How to Build a Customer Onboarding Form
First impressions matter. An onboarding form is often a customer's first real interaction with your product after signing up. Done right, it collects what you need to personalize their experience while making them feel welcomed, not interrogated.
The goal isn't just data collection - it's setting customers up for success. Ask about their goals, preferences, and context. Use that information to customize their dashboard, recommend features, and skip irrelevant setup steps.
Welcome and Company Info
Start with a friendly greeting and basic company information. Keep it light - you can always ask more later.
const welcomeSection = form.addSubform('welcome', {
title: 'Welcome to Acme'
});
welcomeSection.addRow(row => {
row.addTextPanel('greeting', {
label: '',
computedValue: () =>
'Let\'s get you set up. This takes about 2 minutes ' +
'and helps us personalize your experience.'
});
});
welcomeSection.addRow(row => {
row.addTextbox('companyName', {
label: 'Company Name',
isRequired: true,
placeholder: 'Your company or organization'
});
});
welcomeSection.addRow(row => {
row.addDropdown('companySize', {
label: 'Company Size',
isRequired: true,
options: [
{ id: 'solo', name: 'Just me' },
{ id: 'small', name: '2-10 employees' },
{ id: 'medium', name: '11-50 employees' },
{ id: 'large', name: '51-200 employees' },
{ id: 'enterprise', name: '200+ employees' }
]
});
});The text panel sets expectations: "This takes about 2 minutes." Company size helps you understand their context and needs - a solo founder has different requirements than an enterprise team.
Pro tip
Tell users how long onboarding takes. "2 minutes" is specific and honest. "Quick setup" is vague and often a lie.
Role and Team Context
Understanding who you're talking to helps personalize everything that follows. An owner sees different features than an individual contributor.
welcomeSection.addRow(row => {
row.addDropdown('role', {
label: 'Your Role',
isRequired: true,
options: [
{ id: 'owner', name: 'Owner / Founder' },
{ id: 'executive', name: 'Executive (C-level, VP)' },
{ id: 'manager', name: 'Manager / Team Lead' },
{ id: 'individual', name: 'Individual Contributor' },
{ id: 'freelancer', name: 'Freelancer / Consultant' }
]
});
});
const role = welcomeSection.dropdown('role');
welcomeSection.addRow(row => {
row.addTextbox('teamName', {
label: 'Team Name',
isVisible: () => {
const r = role?.value();
return r === 'manager' || r === 'executive';
},
placeholder: 'e.g., Marketing, Engineering'
});
});The team name field appears only for managers and executives - people who actually lead teams. Solo users and individual contributors don't see it.
Goals and Use Cases
This is the most valuable section. Knowing why someone signed up lets you guide them to the right features and skip irrelevant ones.
const goalsSection = form.addSubform('goals', {
title: 'What brings you here?'
});
goalsSection.addRow(row => {
row.addCheckboxList('primaryGoals', {
label: 'Select your main goals',
isRequired: true,
min: 1,
max: 3,
options: [
{ id: 'leads', name: 'Generate more leads' },
{ id: 'automate', name: 'Automate manual processes' },
{ id: 'feedback', name: 'Collect customer feedback' },
{ id: 'quotes', name: 'Create instant quotes' },
{ id: 'bookings', name: 'Accept online bookings' },
{ id: 'surveys', name: 'Run surveys' }
],
orientation: 'vertical'
});
});
const goals = goalsSection.checkboxList('primaryGoals');
goalsSection.addRow(row => {
row.addTextarea('goalDetails', {
label: 'Tell us more (optional)',
placeholder: 'Any specific challenges or use cases?',
rows: 3,
isVisible: () => (goals?.value()?.length || 0) > 0
});
});Limiting to 3 goals forces prioritization. "Everything" isn't a useful answer. The optional details field appears after they've made selections, inviting elaboration without requiring it.
Industry-Specific Suggestions
When you know someone's industry, you can show relevant examples and use cases. An agency has different needs than an e-commerce store.
welcomeSection.addRow(row => {
row.addDropdown('industry', {
label: 'Industry',
options: [
{ id: 'agency', name: 'Agency / Consulting' },
{ id: 'ecommerce', name: 'E-commerce / Retail' },
{ id: 'saas', name: 'SaaS / Software' },
{ id: 'services', name: 'Professional Services' },
{ id: 'healthcare', name: 'Healthcare' },
{ id: 'education', name: 'Education' },
{ id: 'nonprofit', name: 'Nonprofit' },
{ id: 'other', name: 'Other' }
]
});
});
const industry = welcomeSection.dropdown('industry');
// Show industry-specific suggestions
goalsSection.addRow(row => {
row.addTextPanel('suggestion', {
label: 'Popular with your industry',
isVisible: () => !!industry?.value(),
computedValue: () => {
const ind = industry?.value();
if (ind === 'agency') return 'Client intake forms, project quotes';
if (ind === 'ecommerce') return 'Product feedback, return requests';
if (ind === 'saas') return 'Feature requests, NPS surveys';
if (ind === 'services') return 'Booking forms, service quotes';
if (ind === 'healthcare') return 'Patient intake, satisfaction surveys';
return 'Contact forms, feedback collection';
}
});
});The suggestion panel shows what's popular in their industry. This validates their choice and gives them ideas for what's possible.
See more form examples in our gallery.
Preferences and Communication
Technical experience affects how much guidance to show. Communication preferences respect their inbox while keeping engaged users informed.
const prefsSection = form.addSubform('preferences', {
title: 'Your Preferences'
});
prefsSection.addRow(row => {
row.addRadioButton('experienceLevel', {
label: 'Technical experience',
options: [
{ id: 'beginner', name: 'New to this - guide me' },
{ id: 'intermediate', name: 'Some experience' },
{ id: 'advanced', name: 'I know what I\'m doing' }
],
orientation: 'vertical'
});
});
prefsSection.addRow(row => {
row.addCheckboxList('communications', {
label: 'Keep me updated on',
options: [
{ id: 'tips', name: 'Tips & tutorials' },
{ id: 'features', name: 'New features' },
{ id: 'webinars', name: 'Webinars & events' }
],
orientation: 'vertical'
});
});"New to this - guide me" vs "I know what I'm doing" changes onboarding flows, tooltip frequency, and suggested next steps. Let users self-select their experience level.
Setup Checklist
Some setup steps are optional. Data import and team invites aren't needed by everyone. Use checkboxes to let users opt into these flows.
const setupSection = form.addSubform('setup', {
title: 'Quick Setup'
});
setupSection.addRow(row => {
row.addCheckbox('importData', {
label: 'I have existing data to import'
});
});
const importData = setupSection.checkbox('importData');
setupSection.addRow(row => {
row.addDropdown('importSource', {
label: 'Import from',
isVisible: () => importData?.value() === true,
options: [
{ id: 'spreadsheet', name: 'Spreadsheet (CSV, Excel)' },
{ id: 'typeform', name: 'Typeform' },
{ id: 'google', name: 'Google Forms' },
{ id: 'other', name: 'Other tool' }
]
});
});
setupSection.addRow(row => {
row.addCheckbox('inviteTeam', {
label: 'I want to invite team members'
});
});
const inviteTeam = setupSection.checkbox('inviteTeam');
setupSection.addRow(row => {
row.addTextarea('teamEmails', {
label: 'Team member emails',
isVisible: () => inviteTeam?.value() === true,
placeholder: 'one@example.com\ntwo@example.com',
rows: 3
});
});Import source and team emails fields appear only when relevant. Users who don't need these features never see them - the form stays short and focused.
Multi-Page Approach
For longer onboarding, split into pages. Each page focuses on one topic, reducing cognitive load.
const pages = form.addPages('onboarding');
// Page 1: Company Info
const companyPage = pages.addPage('company');
companyPage.addRow(row => {
row.addTextbox('companyName', {
label: 'Company Name',
isRequired: true
});
});
companyPage.addRow(row => {
row.addDropdown('companySize', {
label: 'Company Size',
isRequired: true,
options: [
{ id: 'small', name: '1-10' },
{ id: 'medium', name: '11-50' },
{ id: 'large', name: '51+' }
]
});
});
// Page 2: Goals
const goalsPage = pages.addPage('goals');
goalsPage.addRow(row => {
row.addCheckboxList('goals', {
label: 'What do you want to achieve?',
isRequired: true,
min: 1,
options: [
{ id: 'leads', name: 'More leads' },
{ id: 'feedback', name: 'Better feedback' },
{ id: 'automation', name: 'Less manual work' }
]
});
});
// Page 3: Preferences
const prefsPage = pages.addPage('prefs');
prefsPage.addRow(row => {
row.addRadioButton('experience', {
label: 'Your experience level',
options: [
{ id: 'new', name: 'Brand new' },
{ id: 'some', name: 'Used similar tools' },
{ id: 'expert', name: 'Power user' }
]
});
});Three pages: Company Info, Goals, Preferences. Users see progress and can focus on one thing at a time. This works better than a single long form for comprehensive onboarding.
Progress Tracking
Show users how far they've come. A simple progress indicator motivates completion and sets expectations.
// Show completion progress
const companyName = welcomeSection.textbox('companyName');
const companySize = welcomeSection.dropdown('companySize');
const role = welcomeSection.dropdown('role');
const goals = goalsSection.checkboxList('primaryGoals');
const completedSteps = form.computedValue(() => {
let count = 0;
if (companyName?.value()) count++;
if (companySize?.value()) count++;
if (role?.value()) count++;
if ((goals?.value()?.length || 0) > 0) count++;
return count;
});
const totalSteps = 4;
welcomeSection.addRow(row => {
row.addTextPanel('progress', {
label: 'Setup Progress',
computedValue: () => {
const done = completedSteps();
const pct = Math.round((done / totalSteps) * 100);
return done + ' of ' + totalSteps + ' steps (' + pct + '%)';
}
});
});The computed value counts filled fields and shows "2 of 4 steps (50%)". As users complete each field, they see progress. This gamification works - people want to reach 100%.
What to Do With Onboarding Data
Collecting data is pointless if you don't use it. Here's what good onboarding enables:
Personalized dashboards: Show features relevant to their goals. Someone focused on "quotes" sees the calculator builder prominently. Someone focused on "feedback" sees survey templates first.
Customized onboarding flows: Beginners get tooltips and guided tours. Experts skip straight to building. Technical experience level drives this.
Relevant communication: Only email about features they care about. Don't spam the "quotes" person with survey tips.
Sales context: When someone upgrades or contacts support, your team knows their company size, role, and goals without asking again.
Keep It Short
The biggest mistake in onboarding forms is asking too much. Every field increases abandonment. Ask only what you'll actually use.
Must have: Company name, role, primary goal. These are needed to personalize the experience meaningfully.
Nice to have: Company size, industry, experience level. Useful for segmentation but not critical.
Ask later: Team details, integrations, advanced preferences. Get these when they're contextually relevant, not upfront.
If you can't articulate how a field improves the customer's experience, don't include it.
Common Questions
Should onboarding be required or optional?
Required for fields that genuinely improve their experience (like primary goal). Optional for nice-to-haves. Never block product access entirely - let users skip and come back later. A partial profile is better than an abandoned signup.
How do I handle users who skip onboarding?
Store incomplete state and prompt them later. Show a gentle reminder in the dashboard: 'Complete your profile to get personalized recommendations.' Make it easy to finish what they started without re-entering data.
Should I ask for payment information during onboarding?
Usually no. Onboarding should reduce friction, not add it. Let users experience value first. Ask for payment when they hit usage limits or want premium features. Exception: if your product requires payment to function at all.
How many questions is too many?
More than 2 minutes of work is too many for initial onboarding. 5-8 fields is typical. If you need more, use multiple pages or defer some questions to later in the customer lifecycle.