Blog
Contact form testing: the pre-launch checklist
· 3 min read
A broken contact form is the worst kind of bug: it throws no alerts, breaks no layouts, and announces itself only as silence - which looks exactly like "nobody's enquiring." Sites have run for weeks with dead forms while everyone assumed business was slow. Fifteen minutes before launch prevents all of it.
1. The happy path - from the real site
Submit a genuine test from the deployed production URL, not localhost. This single test exercises the things local testing can't: DNS, TLS, and above all CORS - if your form backend uses an origin allowlist (it should), production is the only place you'll discover the domain isn't on it. Test both www and apex if you serve both.
Confirm all three ends: the success state shows in the browser, the submission appears in the dashboard, and the notification (push or email) actually arrives on the device you'll really be carrying.
2. Validation - try to break it
- Submit empty. Every
requiredfield should complain, in the right place, in language matching the site (a Serbian site with English browser-default messages is a classic miss - set custom messages if it matters). - Submit
not-an-emailin the email field. - Paste a genuinely long message - 5,000 characters - and confirm it's accepted or fails gracefully with a clear limit, not a silent truncation.
- If you have a file field: right type, wrong type, and an oversized file. The oversized one should fail with a message, ideally before a slow upload completes.
3. The failure path - the test everyone skips
Temporarily point the form at a nonsense endpoint (or block the request in devtools) and submit. What does the visitor see? The unacceptable answer is "nothing" - a button that does nothing, or a spinner forever. There should be an error state with a fallback ("or email us at …"). This is the state your real users hit during an outage or a botched deploy, and it's the difference between a lost lead and a recovered one. Check your backend's error reference so your handling matches what it actually returns.
4. Spam defenses - confirm they're on, and not too on
- Honeypot: fill the hidden field via devtools and submit - it should be silently swallowed, never appearing in the dashboard.
- Rate limit: submit several times fast; confirm throttling kicks in and that the limit is generous enough for a legitimate correction-and-resend.
- Turnstile (if enabled): test in a normal window and a private one; confirm the token failure path shows a human-readable message.
(How each layer works: contact form spam protection.)
5. Mobile, keyboard, and the unglamorous rest
- Full submit from a real phone: correct keyboards (
type="email"summons the @ keyboard), tappable button, visible success state without scrolling hunt. - Keyboard-only pass: Tab order sane, Enter submits, focus states visible - and Tab should skip the honeypot (if it lands there, add
tabindex="-1"). - Autofill: let the browser fill the form; confirm names map sensibly.
- The thank-you redirect, if any, resolves and isn't blocked by the backend's redirect validation.
6. Leave a canary
After launch, send yourself one real submission a month - calendar reminder, thirty seconds. Deploys, DNS changes, and expired keys all happen; the canary catches the silent failure before a fortnight of "slow business" does.
Total time: about fifteen minutes at launch, thirty seconds a month after. Cheapest insurance in web development.
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
- Contact form spam: honeypots, rate limits & TurnstileHow form spam actually works and the three layers that stop it: honeypot fields, rate limiting, and Cloudflare Turnstile - without punishing real visitors.
- 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.
- Migrating from Formspree to Formhook: the ten-minute guideSwitching form backends is a one-line change. The full Formspree to Formhook migration: export, endpoint swap, spam settings, and testing - in ten minutes.