Website / Webflow

Website

Webflow

Route native Webflow forms and open the calendar, while Webflow keeps every submission.

Keep your Webflow forms exactly as they are. Webflow still saves every submission, sends its notification emails and passes it on to apps like HubSpot, Zapier or Make. Alongside it, Cauliflower sends the lead to a router and opens the right rep's calendar on top of the form's success message, so qualified visitors book before they leave the page.

Setup takes about ten minutes: one snippet in your site settings, one attribute on each form, and a publish.

Already bound a form the usual way?

The widget's usual binding, cauliflower("form", …) or a data-cauliflower-router attribute, works on Webflow too: the widget recognizes forms Webflow sends itself, routes the lead alongside and leaves the submission to Webflow. It also finds the form when the selector or attribute is on the Form Block around it. The snippet on this page adds field mapping and sits in your site settings, so prefer it for new setups. A form bound both ways is routed once.

Before you start

  • A router that is Live, with the Website form entry point turned on in its trigger. The starter router, inbound, already is.
  • The router's slug, shown on Routers → your router → Install, along with your Cauliflower URL and workspace slug.
  • A paid Webflow Site plan or Workspace plan. Webflow only lets paid plans add custom code.
  • Your site's domains, including the staging domain ending in webflow.io if you test there.

Set it up

Allow your Webflow domains

In Cauliflower, open Settings → Workspace → Widget security & qualification → Allowed website origins and add every domain the form runs on, one per line:

Text
https://example.com
https://www.example.com
https://example.webflow.io

Add your own staging domain rather than *.webflow.io, which would let any Webflow site use your workspace. If the list is empty, every website is allowed. See Widget security.

Add the code to your site

In Webflow, open Site settings → Custom code and paste this into Footer code. Replace https://cal.example.com with your Cauliflower URL and acme with your workspace slug, then save.

HTML
<script>
  (function (w, d) {
    w.cauliflower = w.cauliflower || function () { (w.cauliflower.q = w.cauliflower.q || []).push(arguments) };
    var s = d.createElement("script"); s.async = true; s.src = "https://cal.example.com/embed.js"; d.head.appendChild(s);
  })(window, document);
  cauliflower("init", { workspace: "acme" });

  // Webflow forms marked with data-cauliflower-form="<router slug>". Webflow still saves the
  // submission; Cauliflower routes the lead at the same time and opens the calendar.
  (function () {
    // Your field names → Cauliflower's, when they differ. For example: { email: "E-post", company: "Företag" }
    var MAP = {};
    document.addEventListener("submit", function (event) {
      var marked = event.target.closest("[data-cauliflower-form]");
      // Skip forms the widget already routes, so a form bound both ways is routed once.
      if (!marked || event.cauliflowerRouted) return;
      var form = event.target;
      var data = new FormData(form);
      // Webflow doesn't send a form until its reCAPTCHA is checked, so don't route it either.
      if (form.querySelector(".g-recaptcha") && !data.get("g-recaptcha-response")) return;
      var lead = {};
      data.forEach(function (value, name) {
        if (typeof value !== "string" || /captcha|turnstile/i.test(name)) return;
        lead[name] = name in lead ? [].concat(lead[name], value) : value;
      });
      for (var key in MAP) if (MAP[key] in lead) lead[key] = lead[MAP[key]];
      cauliflower("route", { router: marked.getAttribute("data-cauliflower-form"), lead: lead });
    });
  })();
</script>

The same code, with your URL and workspace already filled in, is on Routers → your router → Install: the loader under 1. Add the loader and the rest on the Webflow tab. To load it on one page only, paste it into that page's Page settings → Custom code → Before </body> tag instead.

Mark the forms to route

In the Designer, select the form, open the Element settings panel (the gear icon) and under Custom attributes add:

NameValue
data-cauliflower-formThe router's slug, for example inbound

You can put the attribute on the Form element or on the Form Block around it. Only marked forms are routed, so newsletter signups and other forms keep working as before. Different forms can use different routers.

Turn off the form's redirect

With the form selected, check its settings in the Element settings panel and leave Redirect URL empty. A redirect sends the visitor to another page as soon as Webflow has saved the submission, which closes the calendar before they can book. Use a router path's Redirect step for leads who should go to another page, such as a thank-you page for disqualified leads. See Path steps.

Webflow shows the form's success message instead, and that's what visitors see when they close the calendar. Something like "Thanks! If the calendar didn't open, we'll be in touch shortly." works well.

Publish and test

Custom code only runs on the published site, not in the Designer, so publish to your staging domain first. Submit the form with a teammate's email address, since test submissions are real and send meeting invitations. Then check that:

  1. The calendar opens a moment after you submit.
  2. The submission appears in Webflow under Form submissions.
  3. The router's Logs tab in Cauliflower shows the lead and the path it matched.

When everything works, publish to your production domain.

What the code does

When a visitor submits a marked form, Webflow handles the submission as usual: it validates the fields, saves the entry and shows the success message. At the same moment, the snippet:

  1. Reads every named field from the form. Fields with the same name become a list, and reCAPTCHA and other spam-check tokens are left out.
  2. Skips the form when it has a reCAPTCHA that hasn't been checked, because Webflow won't send it either.
  3. Copies fields listed in MAP to Cauliflower's names.
  4. Calls route, which adds the page URL, the referrer and UTM parameters, sends the lead to the router and shows the outcome.

The visitor then sees the same outcome as with any widget form: the calendar for qualified leads, the path's message for disqualified or assigned leads, or a redirect. Unmarked forms and the rest of your site are untouched. If Cauliflower can't be reached, the Webflow submission still goes through as normal.

Field names

Cauliflower reads each field's Name from its settings in Webflow, not the label visitors see. Names are compared in lowercase with spaces and dashes turned into underscores, so Email, Work Email and Work-Email are all recognized. A typical form arrives like this:

Webflow field NameCauliflower field
NameFull name, split into first and last name
Email or Work-EmailEmail (required)
CompanyCompany
PhonePhone
Company-Sizecompany_size, a custom field you can route on
Messagemessage, stored with the lead

Every field Cauliflower recognizes is listed under Field mapping. An email is required: a form without a recognized email field isn't routed, and the browser console shows "A valid email is required to route a lead".

When your field names are in another language or otherwise differ, map them in the snippet. Keys are Cauliflower's names and values are your Webflow field Names:

JavaScript
var MAP = { email: "E-post", first_name: "Förnamn", company: "Företag", phone: "Telefon" };

You can also rename the fields in Webflow. Mapping is safer when other tools already use those names, such as a Zapier or Make scenario, because renaming a field changes what those tools receive.

To route on a field in the router builder, add it under the router's Form fields with the key Cauliflower uses, for example company_size. A Select field sends the chosen option's value, and a checked Checkbox sends on; unchecked boxes aren't sent at all. See Paths and conditions.

Booking buttons

The same script lets any button or link open a booking link in a modal, such as a "Book a demo" button in your navigation. Select the Button or Link Block, and under Element settings → Custom attributes add data-cauliflower-link with the booking link's slug as its value, for example product-demo. The widget handles the click, so the element's own link setting doesn't matter.

Embed the whole router instead

If you'd rather not keep a Webflow form, embed the router's hosted page: a form built from the router's fields, your team's photos and the calendar, all in one. Copy the code under Routers → your router → Install → Embed the hosted page into a Code Embed element. It doesn't need the footer code above. See Hosted router page.

Go-live checklist

  • The router is Live and its Website form entry point is on.
  • The footer code is saved, with your Cauliflower URL and workspace slug, and the site is published.
  • Each form that should route has data-cauliflower-form with the right router slug, and no other form does.
  • Those forms have no Redirect URL.
  • The email field is recognized, by its name or through MAP.
  • Allowed website origins lists every production domain, and the staging domain if you test there.
  • A test submission opens the calendar, shows up in Webflow's Form submissions and in the router's Logs.
  • A test with a personal email address, or anything else your paths disqualify, shows the message you expect.

Troubleshooting

Open the browser's developer console on your published site to see errors from Cauliflower. The most common problems:

What you seeCause and fix
Webflow shows its success message, but no calendar opens and nothing is in the router's LogsThe code isn't running or the form isn't marked. Check that the site was published after you saved the footer code, that the attribute is named exactly data-cauliflower-form, and that your Webflow plan allows custom code.
The form submits, but nothing appears under Webflow's Form submissionsThe form has an Action URL, so it posts there instead of to Webflow. Clear the form's action to let Webflow save it.
The spinner shows for several seconds before the calendar opensThe router looks the lead up in your CRM or Apollo before it decides. The router's Logs tab shows how long each routing took under its time. Turn off the lookups the router's paths don't use, under its Lead matching node. See Lead enrichment.
The calendar opens, then the page changesThe form has a Redirect URL. Clear it and use a router Redirect step where you need one.
"A valid email is required to route a lead"Cauliflower didn't recognize the email field. Rename the field or add it to MAP.
"This website is not allowed to use this workspace's widget"The domain isn't in Allowed website origins. Add it, including www. and the webflow.io staging domain.
"This router is paused" or "This router doesn't accept website form submissions"Set the router to Live and turn on its Website form entry point.
"Too many submissions. Please wait a minute."Public routing allows 30 submissions per minute from one IP address. Wait a minute between test bursts.
The calendar opens, but the lead goes down the wrong pathOpen the lead from the router's Logs tab. Its page shows the Submitted data that arrived and how each path's conditions were evaluated.
The calendar opens for you, but not for some visitorsA cookie consent tool may be blocking embed.js until visitors accept. The widget sets no cookies; it keeps the visit's UTM parameters in the browser's session storage. Decide with whoever owns your privacy policy how to categorize it.

To check a field's name on the published site, right-click the field, choose Inspect and look at its name attribute. If your site sends a Content Security Policy, allow your Cauliflower URL in script-src, connect-src and frame-src.