> ## Documentation Index
> Fetch the complete documentation index at: https://docs.formbox.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Embed

> Learn how to embed a Formbox form inline, as a full-page form, or inside a popup on your website.

The Formbox embed script lets you render a form inline on a page, open it in a popup, or mount it as a full-page experience, all without rebuilding any form UI yourself.

## Install the script

Add the script once on any page where you want to embed a form:

```html theme={null}
<script async src="https://app.formbox.app/scripts/embed.js"></script>
```

Once loaded, the script initializes any iframes with `data-formbox-src`, wires up popup triggers marked with `data-formbox-open`, handles iframe height syncing for inline embeds, and exposes `window.Formbox` for programmatic control.

## Inline embed

Place an iframe with `data-formbox-src` wherever you want the form to appear. The script will set the `src` for you and inject the metadata it needs.

```html theme={null}
<script async src="https://app.formbox.app/scripts/embed.js"></script>

<iframe
  data-formbox-src="https://app.formbox.app/embed/your-form-id?dynamicHeight=1"
  loading="lazy"
  width="100%"
  title="Contact form"
></iframe>
```

Adding `dynamicHeight=1` tells the embedded form to report its content height back to the parent page. The script listens for those messages and resizes the iframe automatically, so it grows naturally with multi-page forms, validation messages, or conditional content. This is the recommended setup for any inline embed placed inside flowing page content.

You can render the same form more than once on a single page — each iframe gets a unique instance ID internally, so height events and lifecycle messages never collide. Just make sure every iframe has a meaningful `title` for accessibility.

Inline embeds can also use the same presentation-style data attributes as popup embeds, so you do not have to switch to query parameters just to hide the title or apply color overrides.

```html theme={null}
<iframe
  data-formbox-src="https://app.formbox.app/embed/your-form-id"
  data-formbox-hide-title="1"
  data-formbox-align-left="1"
  data-formbox-background-color="#ffffff"
  data-formbox-text-color="#111827"
  data-formbox-button-background-color="#111827"
  data-formbox-button-text-color="#ffffff"
  loading="lazy"
  width="100%"
  title="Contact form"
></iframe>
```

## Full-page embed

If the form should take over an entire page, wrap the iframe in a minimal HTML shell that fills the viewport:

```html theme={null}
<!DOCTYPE html>
<html>
  <head>
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"
    />
    <title>Contact form</title>
    <script async src="https://app.formbox.app/scripts/embed.js"></script>
    <style>
      html,
      body {
        margin: 0;
        height: 100%;
        overflow: hidden;
      }

      iframe {
        position: absolute;
        inset: 0;
        width: 100%;
        height: 100%;
        border: 0;
      }
    </style>
  </head>
  <body>
    <iframe
      data-formbox-src="https://app.formbox.app/embed/your-form-id?dynamicHeight=1"
      title="Contact form"
    ></iframe>
  </body>
</html>
```

This gives the form its own dedicated page rather than embedding it inside surrounding content.

## Popup embed

Popups can be opened declaratively with data attributes on any clickable element, or programmatically with JavaScript if you need callbacks or more control.

### Using data attributes

The simplest approach — no extra JavaScript required. Set `data-formbox-open` to your form ID and the script handles the rest:

```html theme={null}
<script async src="https://app.formbox.app/scripts/embed.js"></script>

<button
  type="button"
  data-formbox-open="your-form-id"
  data-formbox-layout="modal"
  data-formbox-width="560"
>
  Open form
</button>
```

The value of `data-formbox-open` accepts a form ID, a full embed URL like `https://app.formbox.app/embed/your-form-id`, or a relative path like `/embed/your-form-id`.

You can configure the popup further with additional data attributes on the same element:

| Attribute                             | Description                                                      |
| ------------------------------------- | ---------------------------------------------------------------- |
| `data-formbox-layout`                 | `modal` or `popup`                                               |
| `data-formbox-width`                  | Width in pixels or a valid CSS size string                       |
| `data-formbox-title`                  | Accessible dialog title (defaults to "Formbox popup form")       |
| `data-formbox-hide-title`             | Hide the form title inside the popup                             |
| `data-formbox-align-left`             | Left-align the form content                                      |
| `data-formbox-transparent-background` | Make the form background transparent                             |
| `data-formbox-overlay-opacity`        | Number from `0` to `1`                                           |
| `data-formbox-close-on-overlay`       | Set to `0`, `false`, or `no` to prevent closing on overlay click |

### Using JavaScript

Use `Formbox.openPopup()` when you want programmatic control or lifecycle callbacks:

```html theme={null}
<script async src="https://app.formbox.app/scripts/embed.js"></script>

<button id="open-formbox-popup" type="button">Open popup</button>

<script>
  document.getElementById("open-formbox-popup")?.addEventListener("click", () => {
    Formbox.openPopup("your-form-id", {
      width: 560,
      onOpen: ({ instanceId, formId }) => {
        console.log("opened", instanceId, formId);
      },
      onClose: ({ instanceId, formId }) => {
        console.log("closed", instanceId, formId);
      },
      onPageView: (page, { formId, totalPages }) => {
        console.log("page", page, "of", totalPages);
      },
      onError: ({ reason, message }) => {
        console.log(reason, message);
      },
      onSubmit: (payload, detail) => {
        console.log("submitted", payload, detail);
      },
    });
  });
</script>
```

The popup supports keyboard close with `Escape`, optional overlay-click-to-close, scroll locking while open, and automatic height syncing with internal scrolling when content exceeds the viewport.

To close a popup programmatically, call `Formbox.closePopup()`.

## Styling and appearance

By default, the embed inherits the form's saved appearance from the Formbox dashboard — background color, text color, accent color, and button colors all carry over automatically.

If you need to override those styles for a specific embed, you can pass color values through data attributes, the JavaScript API, or query parameters. All three approaches support the same set of overrides:

| Override          | Data attribute                         | JS option               | Query parameter         |
| ----------------- | -------------------------------------- | ----------------------- | ----------------------- |
| Accent color      | `data-formbox-accent-color`            | `accentColor`           | `accentColor`           |
| Background color  | `data-formbox-background-color`        | `backgroundColor`       | `backgroundColor`       |
| Text color        | `data-formbox-text-color`              | `textColor`             | `textColor`             |
| Button background | `data-formbox-button-background-color` | `buttonBackgroundColor` | `buttonBackgroundColor` |
| Button text       | `data-formbox-button-text-color`       | `buttonTextColor`       | `buttonTextColor`       |

Here's what a fully customized popup trigger looks like using data attributes:

```html theme={null}
<button
  type="button"
  data-formbox-open="your-form-id"
  data-formbox-layout="modal"
  data-formbox-accent-color="#7c3aed"
  data-formbox-background-color="#faf5ff"
  data-formbox-text-color="#4c1d95"
  data-formbox-button-background-color="#4c1d95"
  data-formbox-button-text-color="#faf5ff"
>
  Open customized form
</button>
```

You only need to pass overrides when you want an embed-specific look. Otherwise the form's saved styling is used.

### Query parameters

For inline embeds or manually constructed URLs, you can also pass layout options as query parameters:

```text theme={null}
https://app.formbox.app/embed/your-form-id?dynamicHeight=1&hideTitle=1&alignLeft=1&accentColor=%23111827
```

Additional layout parameters include `hideTitle=1`, `alignLeft=1`, and `transparentBackground=1`.

## Dynamically inserted embeds

The script watches the DOM for newly inserted iframes that contain `data-formbox-src`, so in most cases you don't need to do anything special after injecting new markup.

If you want to explicitly trigger initialization after a manual DOM update:

```js theme={null}
window.Formbox?.loadEmbeds();
```

## Events

The embed script dispatches lifecycle events on `document` that you can listen for:

```js theme={null}
document.addEventListener("formbox:submit", (event) => {
  console.log(event.detail.payload);
});

document.addEventListener("formbox:popup-open", (event) => {
  console.log(event.detail);
});

document.addEventListener("formbox:error", (event) => {
  console.log(event.detail.reason);
});
```

The available events are `formbox:loaded`, `formbox:resized`, `formbox:page-view`, `formbox:submit`, `formbox:popup-open`, `formbox:popup-close`, and `formbox:error`. Each event's `detail` object includes the relevant `formId` and `instanceId`, plus event-specific data like `height`, `page`, `totalPages`, `payload`, or an error `reason`.

If an embed fails to initialize, Formbox dispatches `formbox:error` and shows a basic fallback error state instead of leaving the embed stuck indefinitely.

## JavaScript API

The script exposes `window.Formbox` with a handful of methods:

**`Formbox.loadEmbeds()`** — Scans the page for uninitialized `data-formbox-src` iframes and sets them up. Useful after dynamically inserting embed markup.

**`Formbox.openPopup(formId, options)`** — Opens a popup for the given form ID. Returns the popup instance ID. The options object supports:

| Option                  | Description                                                                           |
| ----------------------- | ------------------------------------------------------------------------------------- |
| `width`                 | Popup width in pixels or a CSS size string                                            |
| `overlayOpacity`        | Backdrop opacity from `0` to `1`                                                      |
| `closeOnOverlayClick`   | Whether clicking the overlay closes the popup (default `true`)                        |
| `hideTitle`             | Hide the form title inside the popup                                                  |
| `alignLeft`             | Left-align the form content                                                           |
| `transparentBackground` | Make the form background transparent                                                  |
| `accentColor`           | Override the form's accent color                                                      |
| `backgroundColor`       | Override the form's background color                                                  |
| `textColor`             | Override the form's text color                                                        |
| `buttonBackgroundColor` | Override the form's button background color                                           |
| `buttonTextColor`       | Override the form's button text color                                                 |
| `onOpen`                | Called when the popup opens. Receives `{ instanceId, formId }`                        |
| `onClose`               | Called when the popup closes. Receives `{ instanceId, formId }`                       |
| `onPageView`            | Called on page changes. Receives `(page, { formId, instanceId, totalPages })`         |
| `onError`               | Called when the popup embed fails. Receives `{ formId, instanceId, reason, message }` |
| `onSubmit`              | Called on form submission. Receives `(payload, { formId, instanceId })`               |

**`Formbox.closePopup()`** — Closes the active popup, or pass a specific instance ID or form ID to close a particular one.

## Tips

Always use `data-formbox-src` instead of setting `src` directly — this lets the script inject the routing metadata it needs. For inline embeds inside flowing content, include `dynamicHeight=1` so the iframe resizes with the form.

For popups, use data attributes when you want a simple no-JavaScript integration, and the JavaScript API when you need lifecycle callbacks. The popup and inline modes share the same hosted embed URL and runtime, so everything from page-view tracking to submit events works the same way regardless of how the form is displayed.
