Quote request forms.
A quote request is often the first step towards paid work, so losing one to a spam folder costs real money. FormRoute delivers each request from your own domain and shows you whether it was sent.Who it's for.
- Trades and service businesses: builders, cleaners, installers, studios.
- B2B suppliers taking requests for prices or samples.
- Agencies and consultants with a "start a project" form.
Fields to set up.
Add them in FormRoute with these names, so the form and its settings match.| Field name | Label | Required | Max length | Note |
|---|---|---|---|---|
name | Name | Yes | 120 | |
email | Yes | 254 | ||
phone | Phone | No | 40 | Optional; many customers prefer a call. |
company | Company | No | 160 | Useful for B2B quotes. |
service | Service | Yes | 120 | A select with your services keeps answers consistent. |
details | Details | Yes | 5000 | Size, quantities, location, deadline. |
The form.
Your own markup, plus the script that sends it.<form id="contact-form">
<label>Name <input name="name" required maxlength="120"></label>
<label>Email <input name="email" type="email" required maxlength="254"></label>
<label>Phone <input name="phone" type="tel" maxlength="40"></label>
<label>Company <input name="company" maxlength="160"></label>
<label>Service
<select name="service" required>
<option value="">Choose a service</option>
<option>Installation</option>
<option>Maintenance</option>
<option>Something else</option>
</select>
</label>
<label>Details <textarea name="details" required maxlength="5000"></textarea></label>
<!-- Honeypot: hidden from people, must stay empty -->
<div aria-hidden="true" style="position:absolute;left:-10000px">
<label>Leave this empty <input name="hp" tabindex="-1" autocomplete="off"></label>
</div>
<button type="submit">Request a quote</button>
<p id="contact-status" role="status"></p>
</form><script>
const ENDPOINT = "https://form-route.com/api/v1/send";
const SITE_KEY = "fr_your_site_key"; // from your FormRoute account
const form = document.querySelector("#contact-form");
const status = document.querySelector("#contact-status");
const shownAt = Date.now();
form.addEventListener("submit", async (event) => {
event.preventDefault();
const data = new FormData(form);
const button = form.querySelector("button[type=submit]");
button.disabled = true;
status.textContent = "Sending…";
try {
const response = await fetch(ENDPOINT, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
siteKey: SITE_KEY,
t: Date.now() - shownAt, // ms since the form was shown
hp: data.get("hp") ?? "", // honeypot, empty for people
name: data.get("name"),
email: data.get("email"),
phone: data.get("phone"),
company: data.get("company"),
service: data.get("service"),
details: data.get("details"),
}),
});
if (response.ok) {
form.reset();
status.textContent = "Thanks, your message was sent.";
} else {
status.textContent = "Sorry, that didn't go through. Please try again.";
}
} catch {
status.textContent = "Sorry, that didn't go through. Please try again.";
} finally {
button.disabled = false;
}
});
</script>Replace fr_your_site_key with the site key from your account. Using a framework or site builder? The platform guides show where the code goes.
Good to know.
Ask for what you need to price. A good quote form asks the questions you would otherwise ask by email, and nothing more.
Make optional fields optional. Mark only the fields you truly need as required in FormRoute; the rest may be left empty.
Watch the results. Your account lists every request, including refused ones, so a real customer stopped by a mistake in your setup is easy to spot.
Not for: File attachments such as plans or photos: FormRoute carries text fields only, up to 20 KB per request.