Embed guide

One script tag. Forms anywhere.

Embed any guided flow with a single line of HTML. Inline, button, modal, or slide-over. Auto-resizing, fully branded, works on every major website builder.

From intake to signed deal, all in one tool

Every submission lands in our kanban pipeline, ready to triage, assign, and advance through your stages. Collect payment at any step through your Stripe account. When you're ready to close, auto-generate an e-signature contract pre-filled from the flow's own answers. One subscription replaces Typeform + DocuSign + Zapier.

IntakePaymentContract
Quick start

Paste our snippets anywhere

Drop a single <script> tag onto your page. It loads our widget, renders the form, handles resizing, and submits answers back to your DocOtto dashboard. Same widget, four ways to surface it. Pick the one that fits where the form lives in your funnel.

Inline

Renders directly in the page

The flow appears where you place the script tag, taking up the available width and auto-resizing as the user navigates. Best for dedicated landing pages and "Get a quote" sections.

Split two-column layout·Use forDedicated intake pages, contact sections, embedded sign-up flows
HTML
<div id="docotto-flow"></div>
<script
  src="https://docotto.com/embed.js"
  data-flow="embed-demo"
  data-mode="inline"
  async></script>
Live demoDemo 1

Sample is inert

Click Paste HTML in Sample on the left to activate this demo.

Button

Branded button opens a modal on click

A styled button renders where you place the script tag. Clicking it opens the flow in a centered modal overlay. Best for CTAs that don't need to occupy permanent page real estate.

Magazine layout·Use for"Book a call" buttons, hero CTAs, sidebar conversions
HTML
<script
  src="https://docotto.com/embed.js"
  data-flow="embed-demo"
  data-mode="button"
  data-button-text="Get started"
  data-color="#1B64F2"
  async></script>
Live demoDemo 2

Sample is inert

Click Paste HTML in Sample on the left to activate this demo.

Modal

Same as button — alias for clarity

Identical behavior to button mode — kept as a separate value because some users find "modal" more intuitive in their snippet config. Pick whichever name fits your team's vocabulary.

Stepper layout·Use forWhen your team thinks in modals, not buttons
HTML
<script
  src="https://docotto.com/embed.js"
  data-flow="embed-demo"
  data-mode="modal"
  data-button-text="Open form"
  data-color="#0f172a"
  async></script>
Live demoDemo 3

Sample is inert

Click Paste HTML in Sample on the left to activate this demo.

Slide-over

Drawer slides in from the right edge

A button opens a right-edge drawer that slides over the page content. Less interruptive than a modal — visitors can still see the page they were on. Great for persistent capture without blocking content.

Conversational layout·Use forFloating "Contact us" CTAs, persistent help/quote drawers
HTML
<script
  src="https://docotto.com/embed.js"
  data-flow="embed-demo"
  data-mode="slide-over"
  data-button-text="Contact us"
  data-color="#1B64F2"
  async></script>
Live demoDemo 4

Sample is inert

Click Paste HTML in Sample on the left to activate this demo.

Customization

Configurable via data attributes

The widget reads its config from data-* attributes on the script tag — no JavaScript API to learn.

AttributeTypeDefaultDescription
data-flowRequiredstringThe slug of the published flow to embed. Found in the builder's Settings panel under "URL slug."
data-mode"inline" | "button" | "modal" | "slide-over"buttonWhich display mode to use. See the mode reference above for behavior.
data-button-textstring"Get started"Label for the trigger button. Ignored in inline mode.
data-colorstring (hex color)"#0f172a"Primary color for the trigger button background. Hex format only — anything else falls back to the default for safety.
Platform guides

Step-by-step for every major builder

Each platform exposes raw-HTML insertion in a slightly different place. The in-app Share panel auto-generates the exact snippet for each — these are the platforms supported today.

Squarespace

Personal plan and up

Insert via Code Block

Wix

All plans

Insert via Embed HTML element

Webflow

Up to 50K characters

Insert via Embed element

WordPress

Gutenberg or Classic

Insert via Custom HTML block

Showit

Hard refresh after publish

Insert via Custom HTML element

Notion

Public pages only

Insert via /embed command

Don't see your platform? If it accepts raw HTML, the snippet works. The in-app Share panel handles platform-specific quirks.

Security & compliance

Sandboxed by default

The embed runs in an isolated iframe — your site and the form never share JavaScript, cookies, or DOM access.

How is my data protected?+
The flow runs inside a sandboxed iframe from forms.docotto.com. The iframe is fully isolated from your website — your code can't read submission data, and our code can't read your visitors' cookies or page content. The sandbox attribute also prevents the iframe from navigating your top page or opening unsolicited popups. Submissions are sent over TLS directly from the iframe to DocOtto's API.
Content Security Policy (CSP) requirements+
If your site uses CSP headers, allow forms.docotto.com as an iframe source. Minimum required directive: frame-src https://forms.docotto.com; (or child-src on older browsers).
Third-party cookies+
The embed does not depend on third-party cookies. Email verification uses one-time tokens, drafts use sessionStorage in the iframe, and submissions identify the respondent via the answers themselves. Safari ITP and Firefox ETP have no impact on flow functionality.
postMessage protocol+
The iframe posts four events to the parent page: docotto:ready (mount), docotto:resize (height changes), docotto:page-change (step navigation), docotto:submitted (successful completion, includes submissionId + publicToken). The parent replies to docotto:ready with docotto:init carrying its URL and origin. embed.js handles all of this automatically; if you skip the script and use a raw iframe, you can listen for these events yourself. The submission event also dispatches a bubbling DOM event ("docotto:submitted") on the iframe element so you can hook in via document.addEventListener for analytics.
Troubleshooting

Common issues

The iframe shows a 404 or blank page+
Check that the flow slug in data-flow exactly matches the slug shown in the builder's Settings panel. Slugs are case-sensitive. Also confirm the flow is Published (status: active) — drafts can't be embedded.
The iframe stays at 800px even when content is smaller+
Auto-resize requires JavaScript on the host page. If your CSP blocks scripts or you're using a strict iframe sandbox, the postMessage resize event won't fire. Workaround: set a fixed height on the iframe via CSS, or use embed.js (which handles resize automatically).
Outcome redirects (Stripe Checkout, custom thank-you pages)+
When embedded, outcome redirects do not auto-navigate the iframe — instead, the thank-you screen renders with a "Continue →" button that opens the redirect URL in a new tab on click. This avoids both the jarring iframe-takeover and popup-blocker issues that come with auto-opening tabs from event handlers. Visitors stay on your page and can return to the new tab when they're ready.
Modal opens but is too small / cropped+
The modal sets max-height: 90vh and max-width: 900px. On mobile, this works automatically. On desktop with very tall flows, the iframe inside the modal scrolls internally — that's expected behavior.
Multiple embeds on the same page conflict+
Each script tag renders its own widget independently — no conflict. If two button-mode snippets render two buttons in the same spot, that's expected. Modal/slide-over modes share z-index, so the most-recently-opened wins if they overlap (rare).

Ready to embed your first flow?

Build a guided flow in the editor, click Share, and copy the snippet. Live on your site in under 5 minutes.

14-day free trial. Cancel anytime.