Contact forms.

The contact form is the one every business site has, and the one bots find first. FormRoute keeps it simple: your form, three fields, and every genuine message in your inbox from your own domain.

Who it's for.

  • Small businesses and freelancers with a contact page.
  • Agencies maintaining contact forms on client websites.
  • Static sites with no server to send mail from.

Fields to set up.

Add them in FormRoute with these names, so the form and its settings match.
Field nameLabelRequiredMax lengthNote
nameNameYes120Shown first in the email.
emailEmailYes254So you can reply. Use type="email" so browsers check the format.
messageMessageYes5000A length limit stops pasted walls of spam.

The form.

Your own markup, plus the script that sends it.
Form
<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>Message <textarea name="message" 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">Send</button>
  <p id="contact-status" role="status"></p>
</form>
Script (after the 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"),
          message: data.get("message"),
        }),
      });

      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.

Keep it short. Name, email and message are enough for most businesses. Every extra field is one more reason not to send.

Set the same limits twice. Use maxlength in the HTML for visitors, and the same maximum length in FormRoute for everyone else.

Choose a sender you read. Replying to a submission email goes to the sender address on your domain, so pick one that reaches you.

Not for: Newsletters or mailing lists: FormRoute sends each submission to you, it does not collect subscribers.

Give your form a route.

Create an account, subscribe through Stripe and send your first test submission.