Webflow form to email from your own domain

Webflow's own form block sends submissions to Webflow. To send them through FormRoute, and from your own domain, build the form inside a Code Embed element so that its script can post to FormRoute.

You need a FormRoute account with a verified domain and a form whose fields are name, email and message, or change the names below to match yours. Getting started covers the setup.

1. Check your plan

Webflow allows the Code Embed element when the site has a paid Site plan or belongs to a paid Workspace plan (Core, Growth, Agency or Freelancer).

2. Add a Code Embed element

Drag a Code Embed element where the form should be, paste the form and script below, and replace fr_your_site_key with the site key from your FormRoute account.

Style it with a <style> block inside the embed, or give the elements the class names you already use on the site.

Code Embed
<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>
  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>

3. Publish

Custom code runs on the published site, not inside the Designer. Publish to your staging address or your domain to try it.

4. List your website in FormRoute

In your FormRoute account, open your form and add every address the form is served from to Allowed websites, for example https://www.example.com and, while you test, your https://your-site.webflow.io staging address. Each entry is a scheme and host, with a port only if your site uses one.

A browser submission from an address that isn't listed is refused, and your account shows it as Rejected: website not allowed. For local development, use the exact address your dev server prints.

5. Send a test

Open the page, fill in the form and send it. The submission appears on your FormRoute home page within seconds, as Sent or with the reason it was refused, and the email arrives from your own domain.

Fill the form in at a human pace: a submission sent within 1.2 seconds of the form appearing is treated as automated.

Good to know

  • Remove the webflow.io address from Allowed websites once the site is live on your domain.

More guides

HTML · Next.js · React · Vue · Astro · WordPress · Framer · Hugo, Jekyll and Eleventy