Skip to content
All writing
EmbeddingWeb

Put a booking form on Webflow, Framer or WordPress without an iframe

How to add a booking calendar to a Webflow, Framer or WordPress site so it renders in your own page and takes on your fonts, with the steps for each one.

Vedant Kulkarni9 November 20266 min read

To add a booking calendar to Webflow, Framer or WordPress without an iframe, paste a script that mounts the booking form into an element on your own page: a Code Embed element in Webflow, a Custom HTML block in WordPress, and a small code component in Framer. Mounted that way, the form becomes part of the page, so it takes your fonts, colours and corner radius instead of arriving in the scheduler's own styling.

The iframe version is easier to paste and harder to live with: a fixed height that is always slightly wrong, a second scrollbar in the middle of the page, and type that does not match anything around it. Three ways to embed a booking form explains why at the level of the browser. This post is the practical half: what to paste, where it goes, and what each builder will and will not let you do.

What you paste

Setupp's embed is two lines: an element to mount into, and a script that names your workspace and the meeting type. The dashboard's Embed page generates both with your own values filled in.

<div id="setupp"></div>
<script src="https://usesetupp.com/embed/setupp.js"
        data-setupp-workspace="your-workspace"
        data-setupp-event="intro-call"
        data-setupp-mount="#setupp" async></script>

The script reads the page around the mount, works out a typeface, a text colour, a background, an accent and a radius, and renders the booking flow as ordinary elements inside the <div>. If the meeting type asks qualifying questions, the embed asks them first and shows times only to people who clear your rules, exactly as the hosted page does.

The embed is on the Pro plan and up. On Free, the same snippet loads, declines to render, and logs the reason to the browser console, while your hosted booking page carries on working.

Webflow

  1. In the Designer, open the Add panel and drag a Code Embed element to the place the form should appear.
  2. Paste both lines into it and save. The <div> and the script can share one element.
  3. Open Preview or publish the site. The Designer shows a placeholder for any embed that contains a <script> tag, so the form never appears on the canvas itself.

Webflow's Code Embed element needs a paid Site plan or a Core, Growth, Agency or Freelancer Workspace, and holds up to 50,000 characters, which the snippet is nowhere near. If the form comes out in a typeface you did not expect, look at the element it sits in rather than the page: the embed takes the font of its mount, so a Code Embed inside a block with a different text style inherits that style.

WordPress

  1. Edit the page and add a Custom HTML block where the form should go.
  2. Paste both lines and update the page.
  3. Open the published page to check it.

WordPress only keeps a <script> tag for users allowed to post unfiltered HTML. On a single site that means Administrators and Editors. On a multisite network it means Super Admins only, so if the script vanishes when a site admin saves the page, that is the reason.

On WordPress.com, the Custom HTML block accepts script tags only on a paid plan with hosting features switched on, which WordPress.com activates when you install a plugin. On the free plan the script is stripped when the page is saved, and the form never loads.

Page builders that run on WordPress have their own HTML or code modules, and the same two lines go there. If a performance plugin delays or combines your JavaScript, exclude setupp.js from it: a delayed loader means a visitor scrolling past an empty space.

Framer

Framer is the one builder where the obvious route is the wrong one. Its Embed component is built for iframes and third-party embed scripts, and widget makers such as Elfsight point Framer users to a code component instead when they want their widget in the page rather than in a frame. A code component is a small React component that Framer renders into the page, which is what lets the form inherit.

  1. In your Framer project, open Assets, add a new Code file and create it as a component.
  2. Replace its contents with the component below, putting your own workspace and meeting type in place of the examples.
  3. Drag the component onto the page, then publish and check the live site.
import { useEffect, useRef } from "react"

const LOADER = "https://usesetupp.com/embed/setupp.js"

export default function SetuppBooking() {
    const ref = useRef<HTMLDivElement>(null)

    useEffect(() => {
        const el = ref.current
        if (!el) return
        el.id = "setupp-" + Math.random().toString(36).slice(2)

        const script = document.createElement("script")
        script.src = LOADER
        script.async = true
        script.setAttribute("data-setupp-workspace", "your-workspace")
        script.setAttribute("data-setupp-event", "intro-call")
        script.setAttribute("data-setupp-mount", "#" + el.id)
        document.body.appendChild(script)

        return () => {
            script.remove()
            el.textContent = ""
        }
    }, [])

    return <div ref={ref} style={{ width: "100%" }} />
}

The component gives its own <div> an id, adds the script with your values and that id on it, and clears the form when the page changes. If the form comes out in a default typeface, the component's container has no font of its own to pass on. Add a data-setupp-font attribute the same way, set to your own font stack.

Three things that go wrong on any builder

  • The form is in the wrong typeface. The embed reads the font of the element it is mounted in and downloads no fonts of its own, so the font has to be loaded on that page already. Mount it inside a section that uses your body text style, or set data-setupp-font to your font stack.
  • The colours come from the wrong surface. The embed walks up from the mount until it finds a painted background colour. A gradient or an image cannot be sampled, so on sections that use one, set data-setupp-theme and data-setupp-accent yourself.
  • Nothing appears. Open the browser console, which usually says why. The common causes are a workspace on the Free plan, which the embed reports there itself, or a Content-Security-Policy that blocks the script, its requests to usesetupp.com, or the inline style element it adds.

One embed shows one meeting type. For several on one page, give each its own <div> and its own script tag, with each tag's data-setupp-mount naming its own <div>. Or link to your hosted booking page, which lists them all.

The same booking form on three different builders. The page around it changes, and the form takes on whatever it finds there.

Iframe or in the page: which to choose

An iframe is the right choice when isolation is the point: a card payment field, or content from a party you do not trust. A booking form on your own marketing site is the opposite case. You want it to look like your page, size itself like your page and scroll with your page, and only a script that mounts into the page can do all three.

The trade is that a script in your page is a guest in your document, and a guest should behave. Setupp's embed prefixes its classes and custom properties with stp-, writes its colour tokens on its own element inside the mount and never on your page, and reports a setup problem in the browser console rather than showing it to your visitors.

Where Setupp fits

The native embed is on Pro and up, from $19 a month for the workspace, and it renders the same flow as the hosted page: your questions first if the meeting type is gated, real availability for every host, and one invitation for everybody on the booking. The native embed page shows one form inside three very different sites, pricing lists what each plan includes, and the Calendly comparison covers the move if your current booking widget is an iframe.

If the reason you are putting a booking form on your site is to stop the wrong people booking, pair it with how to stop unqualified leads booking sales calls.

Stop taking calls you would have declined.

Connect a calendar, add the questions you already ask on every call, and set your minimum. It takes about twenty minutes, and it saves the half hours you spend finding out a call was never going to work.

Free for one host, for as long as you like. You don’t need a card or a sales call to start.

What you get on day one
  1. 01Multi-recipient invitesfrom Pro
  2. 02Qualification before the calendarfrom Pro
  3. 03A score on every booking
  4. 04An embed that inherits your brandfrom Pro