Blog
Contact form best practices that actually increase conversions
· 5 min read
Most contact forms are designed backward: fields get added because someone in a meeting thought they would be "nice to have," not because the person on the other end of the message needs them to act. The forms that actually convert are built the opposite way - stripped down to what is required, then tested against real devices and real people trying to break them.
None of what follows is exotic. It is mostly things a checklist would catch, if anyone ran one.
Ask for less than you think you need
Every field on a form is a decision point, and a decision point is a chance to stop. A visitor three sentences into typing a genuine enquiry will still close the tab rather than dig up a phone number or explain "how did you hear about us" on the spot. For most contact forms, name, email, and message is the whole form. Everything else is optional at best and postponable at worst - a phone number belongs in the reply, not a gate on the enquiry.
If a field genuinely earns its place - a budget range for a sales enquiry, say - ask whether it needs to be required. A required field with a confusing label or vague validation is a required field people abandon on.
Labels and validation that do not punish
Placeholder text is not a label. It disappears the moment someone clicks into the field, so anyone who gets interrupted - which is most people, most of the time - loses the only clue about what they were filling in. It also breaks autofill in many browsers, and screen readers often skip it entirely. Use a real <label> element for every field, visible above or beside the input, always. Placeholder text, if you use it at all, is for an example format ("jane@company.com"), not instructions.
Validate on blur - when someone leaves a field - not on every keystroke. Flagging an email address as invalid while someone is three characters into typing it just trains people to ignore your error states. Errors should also be specific and attached to the field they describe, not a single "please check the form" banner that leaves the visitor hunting.
Get mobile right - it is most of your traffic
A contact form on a phone should produce the right keyboard without being told twice. That is what type and inputmode are for: type="email" brings up the @ key, and inputmode="tel" brings up a numeric pad for a phone number. Pair every field with a matching autocomplete value (autocomplete="email", autocomplete="name") so the browser can offer to fill it in from data it already holds - on mobile especially, autofill is often the difference between a completed form and an abandoned one.
Tap targets matter as much as keyboards do. An input that is comfortable to click with a cursor can be genuinely hard to hit with a thumb, so keep interactive elements generously sized and spaced.
The honeypot field, done without punishing real visitors
A honeypot is a form field invisible to humans and irresistible to bots: a field named something plausible ("website" or "company") that a scripted submission fills in and a real visitor never sees. Done badly, a honeypot punishes exactly the people it is supposed to protect - display: none and type="hidden" are both filtered out by well-behaved bots that read computed CSS, while some screen readers and browser extensions do surface hidden fields, so a real visitor using assistive technology can end up filling one in and getting silently rejected as spam.
Hide it correctly instead: position it off-screen with CSS rather than display:none, mark it tabindex="-1" so keyboard navigation skips it, and aria-hidden="true" so screen readers never announce it. A field like that is invisible to every real visitor - keyboard, mouse, or screen reader - and still catches the unsophisticated bots behind most spam. Formhook's own spam protection, honeypot plus rate limiting with Turnstile available if you need more, is on by default on every form - but this markup pattern is worth using regardless of backend.
Do not let the form go silent on success
The button is clicked, the request goes out - and then what does the visitor see? A form that shows nothing, or dumps someone onto a blank "Thanks" page with no context, reads as broken even when it worked - more than one visitor has resubmitted a form three times because nothing told them the first attempt succeeded. Show an inline confirmation in place of the form, or send people to a real thank-you state that says what happens next ("we will reply within one business day"). That confirmation is also the last chance to keep the conversation going - a link back to your work or a booking page costs nothing, and some visitors will take it.
None of this needs a framework or a redesign - most of it is markup and fifteen minutes of attention. If you would rather not build the backend piece yourself - delivery, spam filtering, a dashboard, storage - that is what Formhook is for; see pricing for what is on the free tier. For what to verify before you ship, the pre-launch checklist covers it, and if you are deciding between a form and a plain mailto: link, mailto vs contact form makes the case either way.
Ship a working form in one line
EU-hosted, submissions kept forever, push notifications on every tier.
Start freeNo credit card · read the docs
Keep reading
- Mailto links vs contact forms: which loses fewer leads?Mailto links fail silently without a mail client and expose your address to spam bots. When a mailto is fine, and when a contact form pays for itself.
- Contact form testing: the pre-launch checklistA broken contact form fails silently and costs leads for weeks. The 15-minute pre-launch checklist: happy path, validation, spam, mobile, and notifications.
- AJAX form submission: send a form without a page reloadThe default HTML form submit reloads the page. Here's how to submit a form with fetch() instead - inline success/error states, progressive enhancement, and accessible status updates.