Before you polish a contact form's design, inspect it in three places — where people stop, and where enquiries disappear. That tells you the order to fix things in.
| Stage | Loss | How visible it is |
|---|---|---|
| Before input | People see many fields, many of them required, and never start | Visible if you measure |
| During input | People get stuck on errors, or struggle on a phone | Visible through measurement and testing on real devices |
| After sending | The submission succeeded, but the notification email never reaches you | Nobody notices |
This article covers the form alone. Working out where enquiries are lost across the whole site — impressions, page content and so on — is covered in why your website gets no enquiries: seven causes and how to fix them.
The first five minutes: send one enquiry yourself today
Before improving anything, send a real enquiry through your own form. Ideally try both a smartphone and an email address outside the company. Check four things.
- The confirmation screen says what happens next (for example, when to expect a reply)
- The internal notification arrived in the inbox (not the spam folder)
- The auto-reply to the visitor arrived (if you send one)
- The content arrived without garbled or missing text
If it did not arrive, fix the sending mechanism before touching fields or design. Read "Why notification emails stop arriving without a sound" below.
Losing people at the form?
Contact-form fixes, measured through to successful submission
Checklist 1: fields and ease of input
| What to check | Why | How to fix |
|---|---|---|
| Are only the fields needed for the first reply required? | The more required fields, the more people leave before starting | Ask "could we reply without this?" and make everything else optional or delete it |
| Are optional fields labelled "optional"? | When people cannot tell what to skip, they try to fill everything | Mark both required and optional in text (not by colour alone) |
| Does the free-text box show what to write? | A blank box is hard to start | "Your enquiry (e.g. I'd like a quote for …)" |
| Are phone and postcode formats strictly enforced? | Errors over hyphens or full-width characters make people stuck | Normalise on the server and accept the input |
| Do inputs have autocomplete set? | Browser autofill works and saves effort on phones | Set proper values for name, email, phone and company (WCAG 2.2 criterion 1.3.5) |
| Do you need a confirmation screen? | Each extra screen is another chance to leave | If people can see their input before sending, you can often drop it |
| Does the button label say what happens? | "Submit" alone does not predict the result | "Send this enquiry", for example |
Cutting fields is the most reliable improvement and the least work. But if you cut information sales needs, enquiries may rise while follow-up calls to re-ask grow. Agree internally that anything you cut will be asked in the first reply, and there will be no argument.
Checklist 2: error messages and WCAG 2.2
WCAG is the accessibility standard published by W3C, the body that sets web standards. These are the criteria that apply directly to a contact form; I checked their wording against the WCAG 2.2 text on w3.org.
| Success criterion | Level | Gist | What it means on a form |
|---|---|---|---|
| 3.3.1 Error Identification | A | If an input error is detected automatically, identify the item in error and describe the error in text | Say which field is wrong and how, not just "there is an error". Do not rely on a red border alone |
| 3.3.2 Labels or Instructions | A | Provide labels or instructions when content requires input | Do not use the faint example text inside a field (placeholder) as the label; it disappears once typing starts |
| 3.3.3 Error Suggestion | AA | If a correction is known, suggest it unless that would jeopardise security or purpose | Say how to fix it: "The email address is missing an @" |
| 3.3.7 Redundant Entry | A (new in 2.2) | Information entered earlier in the same process and required again is auto-populated or selectable | In multi-step forms, or when returning from a confirmation screen, input must not vanish |
| 3.3.8 Accessible Authentication (Minimum) | AA (new in 2.2) | No cognitive function test, such as memorising or solving a puzzle, in an authentication step without an alternative or similar | It is a criterion for authentication (login), so it does not apply directly to a contact form without login. It is still useful guidance when choosing a CAPTCHA |
Timing matters too. Turning a field red on every keystroke gets in the way, so the usual practice is to show errors when the user leaves the field or when they press send. If there are errors on send, list them at the top of the screen with links to each field, so fewer people give up without noticing an error off-screen.
A technical trap: a form that blocks submission when a value breaks the rules, while showing nothing on screen. It tends to happen with how an unchosen optional option is represented, and is invisible in the developer's own testing. Test both a submission with every optional field empty and one with every field filled.
Checklist 3: spam protection
Layer spam measures starting with the ones that cost users nothing.
| Method | How it works | Effort for users | Caution |
|---|---|---|---|
| Honeypot | Add a field people cannot see and discard submissions that fill it | None | Hide it from screen readers too, and keep keyboard focus out of it. If it is perceivable, disabled users get treated as spam |
| Time-to-submit check | Discard submissions sent implausibly soon after the page opened | None | Too strict a threshold rejects people using autofill |
| Rate limiting | Stop rapid repeated submissions from the same sender | None | Make sure your own tests over a shared office connection do not trip it |
| Server-side validation | Check format and length on the server, not the browser | None | Browser-side checks are easy to bypass, so always validate on the server |
| CAPTCHA | A test to decide whether the sender is human | Some to little | See below |
On CAPTCHA, W3C's document "Inaccessibility of CAPTCHA" points out that schemes asking people to read text or images are barriers for people with visual and cognitive disabilities, and that automation increasingly defeats them. There are low-interaction scoring services, but their external scripts send visitor data to a third party, which you must disclose in your privacy policy. The sensible course is to consider CAPTCHA only when the four measures above cannot hold the volume.
Another easy one to miss is the auto-reply to the visitor. It goes to whatever address was entered, so if someone repeatedly submits a third party's address, your form becomes a spam cannon. Do not echo the submitted content in the auto-reply, and apply rate limiting.
Checklist 4: CSRF in plain words
CSRF (cross-site request forgery) is an attack that makes a user, while browsing another site, send a request to your site without knowing it. On an admin screen behind a login it is serious, because settings can be changed with that person's privileges. On a contact form without login the damage is smaller, but OWASP advises protecting requests that register or change data with tokens or similar, and using your framework's built-in protection where it exists.
As an owner, one question to your vendor is enough:
"What protects the form and the admin screen against CSRF? Have you disabled the standard protection in the framework or plug-in?"
Checklist 5: why notification emails stop arriving without a sound
Even when a submission succeeds, if the notification never reaches you, the enquiry may as well not exist. The visitor was told "sent", so nobody notices.
Gmail's sender guidelines require all senders to authenticate with SPF or DKIM, and senders of more than 5,000 messages a day to use all of SPF, DKIM and DMARC.
| Term | What it does |
|---|---|
| SPF | Publishes in DNS which servers may send mail for your domain |
| DKIM | Signs mail so the receiver can verify the sending domain and that it was not altered |
| DMARC | Lets the domain owner say how receivers should handle mail that fails SPF or DKIM |
Typical failures with form notifications:
| Symptom | Cause | Fix |
|---|---|---|
| Enquiries from certain visitors never arrive | The From address is the visitor's own. The mail claims another company's domain or a Gmail address and may fail authentication | Fix From to a sending address on your own domain and put the visitor's address in Reply-To |
| Everything stopped from one day | A site move or server change took the sender out of SPF | Add the sender to SPF, or switch to a sending service authenticated for your domain |
| It lands in spam | No DKIM signature, or the sending server has a poor reputation | Set up DKIM. Gmail requires a key of 1024 bits or longer for personal Gmail accounts and recommends 2048 bits |
| Some staff don't get it | Receiving filter rules, forwarding on a shared address, a full mailbox | Notify a shared intake address rather than one person, and record the forwarding settings |
Two things belong in the design: do not rely on email alone (also record each enquiry in a database or spreadsheet so the content survives a lost email), and check regularly that it arrives.
A regular test submission
The most reliable check is to send one test enquiry at a fixed time and confirm it reached the inbox. If you can automate it, have an external monitoring service or scheduled job submit the form and alert someone if the notification does not arrive within a set time. Even without automation, deciding to send one every Monday morning and logging it prevents "we didn't notice for months". Put [TEST] in the subject of test enquiries so you can exclude them from measurement.
Checklist 6: show the purpose of use before sending
The Personal Information Protection Commission's guidelines (General Rules) give, as an example where the purpose of use must be clearly shown to the person in advance, the case of collecting personal information directly through an input screen on your own website (Article 21(2) of Japan's Act on the Protection of Personal Information; guideline 3-3-4). They add that when collecting over a network, it is desirable to place the purpose of use (or a link that reaches it in about one action) where the person will see it before pressing the send button.
In practice, put a sentence and link near the send button, such as "We use the information you enter to answer your enquiry and contact you. See our privacy policy for details." If a CAPTCHA or analytics tool sends data outside, cover that in the policy too. Whether your handling fits these rules is a question for a professional. (This is Japanese law; readers elsewhere should check their own jurisdiction's equivalent.)
Measurement: GA4's automatic events cannot tell you "success"
GA4's enhanced measurement includes two form events. According to Google's help, form_start is recorded the first time a user interacts with a form in a session, and form_submit when a form is submitted.
The point to watch is that form_submit records the act of submitting and does not show whether the server accepted it. It carries nothing that separates a submission that failed through a server fault or a validation error from one that succeeded. Confirm which actions trigger the automatic events by operating your own form with GA4's DebugView or similar.
To count reliably, design your own events.
| Event | Type | When it is sent | What it tells you |
|---|---|---|---|
| form_start | GA4 automatic (enhanced measurement) | The first time a user interacts with a form in a session | How many started interacting with any form |
| form_submit | GA4 automatic (enhanced measurement) | When a form is submitted | How many tried to submit (not whether it succeeded) |
| contact_form_start | Custom | When the first field of the contact form is touched | How many started the contact form specifically |
| contact_form_error | Custom | When validation stops it (field name as a parameter; never the input values) | Which field people get stuck on |
| generate_lead | Sent by you under GA4's recommended event name | When the server returns a successful acceptance | How many were actually accepted |
Do not give your own events the names form_start or form_submit. They mix with the automatic events and you can no longer tell which number is which. I recommend keeping the two automatic events as reference figures and using the three custom ones for decisions. The automatic events cover every form on the site and do not separate successful acceptance, so they are poorly suited to reading enquiry counts. generate_lead is a name GA4 defines as a recommended event, so success is recorded under a shared, meaningful name.
Always reconcile GA4's numbers against the enquiries actually received. If generate_lead shows 10 and the inbox has 7, notifications are being lost somewhere. Overall measurement design is covered in how to see your site's traffic and enquiries with Search Console and GA4.
Judging an improvement on a low-traffic site
"Test it with an A/B test" does not work on a site that gets a few enquiries a month. Calculating the numbers needed shows why.
Hypothetical example: 20% of people who open the form currently submit it, and you want to confirm an improvement to 30%. Comparing two proportions with common settings (5% significance, two-sided, 80% power), the numbers needed are:
| Before → after (hypothetical example) | Needed per arm | Total | At 100 form views a month | At 300 a month |
|---|---|---|---|---|
| 20% → 30% | 294 | 588 | about 5.9 months | about 2.0 months |
| 20% → 25% | 1,094 | 2,188 | about 21.9 months | about 7.3 months |
| 10% → 15% | 686 | 1,372 | about 13.7 months | about 4.6 months |
The smaller the improvement, the faster the numbers grow. While you wait months, other factors — season, advertising, sales activity — mix in, and even if a difference appears you cannot say the change caused it.
The figures above come from this short script (it runs on the Python standard library alone).
from math import ceil, sqrt
from statistics import NormalDist
def visitors_per_arm(p_before, p_after, alpha=0.05, power=0.8):
"""Two-sided test of two proportions (normal approximation): visitors per arm"""
z_a = NormalDist().inv_cdf(1 - alpha / 2)
z_b = NormalDist().inv_cdf(power)
p_bar = (p_before + p_after) / 2
num = z_a * sqrt(2 * p_bar * (1 - p_bar)) + z_b * sqrt(
p_before * (1 - p_before) + p_after * (1 - p_after)
)
return ceil(num**2 / (p_before - p_after) ** 2)
for before, after in [(0.20, 0.30), (0.20, 0.25), (0.10, 0.15)]:
n = visitors_per_arm(before, after)
print(f"{before:.0%} -> {after:.0%}: {n} per arm, {2 * n} total")
What to do instead
- A fixed-window before/after comparison: compare, say, four weeks before with four weeks after, with the same length and the same mix of weekdays. Log any change to advertising or campaigns during the window. This does not prove cause; it shows whether things got worse or changed a lot.
- Watch error counts: per-field
contact_form_errorcounts tell you directly where people get stuck, even at low volume. If errors cluster on one field, fix that field. - Review sessions: with a session-recording analytics tool, watch around ten sessions of people who opened the form and did not send. You will find confusing fields and buttons that are hard to tap on a phone. If you install one, set it to mask input fields and disclose it in your privacy policy.
- Ask people to fill it in: have an acquaintance outside the company fill in the form on a phone and tell you where they hesitated.
Change only one or two things at a time, so you know what to roll back if things get worse.
Work that needs outside help: SPF/DKIM setup, server-side validation, success events
What you can do yourselves: today's test submission, reviewing fields, rewriting error messages, and adding the purpose-of-use sentence and link can often be done in the settings of a form plug-in such as those for WordPress.
When a ready-made service is enough: form-builder services often come with spam protection and storage of submissions. Even embedded in your site, submissions stay on the service, so you can see them if a notification email goes missing.
When to consider outsourcing: setting up email authentication (SPF, DKIM, DMARC), server-side validation and rate limiting, implementing success events, and automating test submissions often cannot be done from a settings screen alone. Cost depends on the number of forms, integration with existing systems, the scope of measurement, and how far test automation goes. Scope and how costs are set are on website fixes and maintenance.
Time how long the notification takes to reach the inbox
First send one enquiry from your own phone and time how long the notification takes to reach the inbox. If it did not arrive, or landed in spam, that is the first thing to fix.