Fixing Enquiry and Booking Forms That AI Agents Cannot Fill
Enquiry forms, quote requests, appointment bookings and newsletter sign-ups are where an agent turns interest into a lead for you.
They are also where agents fail most often, because many forms only make sense visually: a grey word inside a box instead of a label, a dropdown drawn from styled divs, a date picker that needs a mouse, or an anti-spam trap that agents fall into. This guide explains how an agent decides what each field is for, the specific patterns that confuse it, and how to rebuild a form so an agent, a screen reader user and a hurried person on a phone can all complete it first time.
How an agent decides what a field is for
An agent looking at a form has to answer two questions for every control: what is this, and what should go in it? Browser-driving agents answer mainly from the accessibility tree, which the browser builds from your HTML. For each element it records a role (text box, checkbox, combo box, button), an accessible name (the label), a value and a state (required, invalid, checked, expanded). A screenshot helps the agent, but the tree is where it gets names it can rely on.
The accessible name comes from, in rough order of priority:
aria-labelledby, pointing at other text on the page;aria-label, a name written into an attribute;- a
labelelement linked byforandid, or wrapping the input; - the
titleattribute, and in some cases theplaceholder, as a weak last resort.
If none of these exist, the field has no name. The agent may guess from nearby text on the screenshot,
and it will sometimes guess wrongly: putting a phone number in the postcode box, or a message in the
name field. Fetch-based tools that read the HTML directly use the same signals plus the name
attribute and the input type.
Form patterns that trip agents up
| Pattern | Why it fails | Better approach |
|---|---|---|
| Placeholder as the only label | Not reliably exposed as a name; vanishes once typing starts | Visible
label above the field; placeholder only for an example |
Floating labels built from a span | Looks like a label but is not linked to the input | Use a real label and animate that instead |
Dropdown made of styled div elements | No combo box role, no options in the tree, often needs a mouse | Native select, or a pattern following the ARIA combobox
guidance |
| Star or slider inputs for ratings and budgets | Drag-only controls, no values exposed | Radio buttons with text values, or a number input |
| Calendar-only date picker | Typing is blocked; days are unlabelled cells | Allow typed dates; label each day button with its full date |
| Checkboxes replaced by images | Checked state not exposed | Style a real input type="checkbox" |
Submit button that is an icon or a div | No name, sometimes no button role | A
button element with text such as "Send enquiry" |
| Grouped questions with no group name | Radio options such as "Yes" and "No" with no question attached | fieldset with a legend holding the question |
Many of these come from form builders and page builder widgets rather than hand-written code, so check the output HTML rather than the settings screen.
A well-built booking enquiry form
Here is a short enquiry form for a fictional dog grooming salon. It uses nothing unusual, which is the point: plain HTML elements carry everything an agent needs.
<form action="/enquiry" method="post" novalidate>
<p id="req-note">Fields marked "required" must be filled in.</p>
<label for="enq-name">Your name (required)</label>
<input id="enq-name" name="name" autocomplete="name" required aria-describedby="req-note">
<label for="enq-email">Email address (required)</label>
<input id="enq-email" name="email" type="email" autocomplete="email" required>
<label for="enq-dog-size">Size of dog</label>
<select id="enq-dog-size" name="dog_size">
<option value="">Choose a size</option>
<option value="small">Small (under 10 kg)</option>
<option value="medium">Medium (10 to 25 kg)</option>
<option value="large">Large (over 25 kg)</option>
</select>
<fieldset>
<legend>Which service do you need?</legend>
<input type="radio" id="svc-full" name="service" value="full-groom">
<label for="svc-full">Full groom</label>
<input type="radio" id="svc-bath" name="service" value="bath-and-brush">
<label for="svc-bath">Bath and brush</label>
</fieldset>
<label for="enq-date">Preferred date</label>
<input id="enq-date" name="preferred_date" type="date" min="2026-10-01">
<label for="enq-msg">Anything we should know?</label>
<textarea id="enq-msg" name="message" rows="4"></textarea>
<button type="submit">Send enquiry</button>
</form>
Every field has a visible, linked label. The radio buttons sit in a fieldset whose legend
is the question, so "Full groom" is understood as an answer to "Which service do you need?". The date
uses the native date input, which accepts typed dates and exposes a proper value. The novalidate
attribute lets your own error messages, described below, replace the browser's default bubbles; leave
it out if you rely on browser validation.
The fix, step by step
Step 1
Inspect the accessible name of every field
Run the AI Agent Compatibility audit on the page with the form and note every field or button it reports as unlabelled. Then open the browser's Accessibility pane and click through each control in turn, writing down its role and computed name. Pay particular attention to dropdowns, date pickers, checkboxes and the submit button. Any control whose name is empty, generic such as "button", or different from its visible label needs fixing before anything else on this list.
Step 2
Give each field a real, linked label
Add a visible label element for every input, select and textarea, joined by
matching for and id values, and put the word "required" or "optional" in the
label text itself. Group related radio buttons and checkboxes inside a fieldset with a legend
that asks the question. Use aria-label only where a visible label is truly impossible, such
as a single search box beside a clearly marked search button, and keep its wording identical to what
people see.
Step 3
Swap custom widgets for native controls
Replace dropdowns built from div elements with a native select,
image checkboxes with styled real checkboxes, sliders and star ratings with radio buttons or number inputs,
and icon-only submit links with a button element carrying text. If a design really needs
a custom widget, follow the matching pattern in the WAI-ARIA Authoring Practices Guide so it has the
right role, state and keyboard behaviour. Test each replaced control using only the keyboard before moving
on.
Step 4
Keep IDs and names stable between loads
Reload the page a few times and compare the id and name of each
field. Some form builders and frameworks generate random values such as input_8f3a2c on
every load, which breaks saved selectors and can break label links if the server and browser disagree.
Give fields meaningful, fixed names like email and preferred_date. In React,
generate IDs with useId so the server-rendered and client-rendered values match, and check
that each label still points at its input.
Step 5
Make errors specific and attached to fields
When a submission fails, show a short summary at the top listing each problem, move
focus to it, and repeat each message next to its field. Link the message to the input with aria-describedby
and set aria-invalid="true" on the field. Write messages that say how to fix the problem,
such as "Enter a date after 1 October", not "Invalid input". Keep everything the person or agent already
entered, so only the wrong field needs changing.
Step 6
Fix honeypots and timing traps
Check
any hidden honeypot field, which catches bots that fill in every box. If it is hidden only by moving
it off screen, agents reading the accessibility tree may see it and fill it, and your form then silently
discards a genuine enquiry. Hide it with display:none in your stylesheet or the hidden
attribute, plus tabindex="-1" and autocomplete="off". Remove rules that reject
forms submitted within a few seconds, because agents type quickly.
Step 7
Let multi-step forms keep their answers
For forms split across several screens, show the step number and total, such as "Step 2 of 4", and a heading naming the step. Save answers as each step is completed, on the server or in session storage, so going back or refreshing does not wipe them. Give each step its own address or history entry so the browser back button works. End with a review screen listing every answer, with a change link beside each, before the final submit button.
Spam protection that does not punish agents
Forms need protection, but some common techniques block exactly the visitors you want. Weigh each one:
- Visible CAPTCHAs. Agents built by reputable providers will not solve them and will hand the task back to the person. That can be acceptable on a form that is attacked constantly, but it should not be the first line of defence on a simple enquiry form.
- Invisible scoring services, such as reCAPTCHA v3 or Cloudflare Turnstile in its non-interactive modes, judge behaviour in the background. Set a sensible threshold and send low-scoring submissions to a review folder instead of rejecting them outright, so you can see if genuine enquiries are being caught.
- Honeypots work well if the field is removed from the accessibility tree as well as from view. A honeypot that screen readers and agents can "see" catches people as well as bots.
- Time-to-submit checks assume that humans are slow. Agents are not, and neither are password managers that fill a form in one go.
- Server-side rate limits per IP address or per email address stop floods without troubling anyone who sends one enquiry.
- Content filtering of the message itself, for example flagging messages full of links, catches a lot of spam after submission without adding any barrier at all.
Form builders and platforms
WordPress form plugins
Contact Form 7, Gravity Forms, WPForms, Fluent Forms and Ninja Forms all produce labelled fields when used as intended, but settings can undo it. Look for options that hide labels and show placeholders instead, "conversational" layouts that show one question at a time, and bundled anti-spam settings with time checks. Gravity Forms and others offer an option to use a native select instead of an enhanced dropdown library; choose the native one where you can.
Shopify
The theme's built-in contact form is usually fine. Problems come from form apps that load inside an iframe from another domain, from product option apps that replace selects with swatches, and from pop-up sign-up forms that cover the page. Check each app's output with the Accessibility pane rather than trusting the app listing.
Embedded third-party forms
Booking systems, CRM forms and survey tools are often embedded in an iframe. Agents can usually work
inside an iframe in a browser, but the form's quality is then out of your hands, and fetch-based tools
will not see it at all. Where the provider allows it, use their direct link or an embed that renders
on your own page, and give the iframe a title that says what it contains.
Stopping regressions
- Test the form with the keyboard alone whenever the form, theme or builder plugin is updated.
- Add an automated accessibility check, such as axe in your test suite or a browser extension, which flags unlabelled fields and missing names.
- Send yourself a test enquiry every month and confirm it arrives, so silent spam filtering is caught quickly.
- Keep a list of field names that your CRM or email integration depends on, so a redesign does not rename them.
1. Why does the agent put information in the wrong field?
Usually because the fields have no proper names. If a form relies on placeholder text or nearby styled text instead of linked labels, the agent has to guess which box is which from the layout, and guesses can be wrong. Open the browser's Accessibility pane, click each field and check its computed name. Any field with an empty or vague name needs a visible label element joined to it with matching for and id values.
2. Are placeholders good enough as labels?
No. A placeholder disappears once someone starts typing, is often low contrast, and is not reliably treated as the field's name by browsers and assistive technology. That makes it a weak signal for agents too. Use a visible label above or beside each field and keep the placeholder, if you want one at all, for a short example of the expected format, such as a sample postcode or a date written in the style you expect.
3. Can agents use custom dropdowns and date pickers?
Sometimes, but not reliably. A dropdown built from styled div elements often has no role, no list of options in the accessibility tree and no keyboard support, so the agent cannot tell what choices exist or how to pick one. A native select and a native date input work everywhere. If your design needs a custom control, follow the WAI-ARIA Authoring Practices pattern for it and test it thoroughly with only a keyboard.
4. Will fixing my form for agents help accessibility too?
Very much so. Agents that drive a browser rely on the same accessibility tree that screen readers use, so linked labels, native controls, grouped questions and clear error messages help both. The fixes in this guide line up closely with WCAG 2.2 success criteria on labels, names, error identification and input purpose. Treat the work as one job that serves disabled users, agents and everyone filling in the form on a small phone.
5. Why are some genuine enquiries never arriving?
A common cause is anti-spam that rejects them silently. A honeypot field hidden only by moving it off screen can be filled in by agents or by some assistive technology, and a time check can reject forms completed quickly. Both make the form look successful while throwing the message away. Hide honeypots with display none or the hidden attribute, drop time checks, and log every rejected submission so you can review them.
6. Do agents cope with multi-step forms?
They can, as long as each step is clear and answers are kept. Problems arise when a step has no heading, when the back button resets the form, or when a refresh loses everything already entered. Show the step number and a heading, save answers as each step is completed, and end with a review page listing every answer. That gives the agent, and the person checking its work, a clear picture before submitting.
7. Should I use aria-label on every field?
Only where a visible label is not possible. A visible label element helps everyone, including people who can see the page, and it is what browser-based agents see on the screen too. aria-label is invisible, easy to leave out of date when the design changes, and sometimes ignored by translation tools. Use it sparingly, for example on a single search box beside a labelled search button, and keep its wording identical to anything visible nearby.
The AI Agent Compatibility audit tests your page for bot blocks, content hidden behind JavaScript, unlabelled forms and controls, navigation agents cannot follow and missing structured data, and links each finding to the guide that fixes it.
Open AI Agent Compatibility Fixes โ