# Popup Form Embed



<Warning>
  **WAIT...** Make sure that you have added the [**Surface Tag**](/platform/traffic/surface-tag) to your site before proceeding.
</Warning>

## Edit Head Tag [#edit-head-tag]

Add this code to your site's `head` tag to enable the popup form.

```html
<!-- Start Surface Form Embed -->

<script>
  (function () {
    const surface_src = "REPLACE ME WITH FORM URL"
    const surface_embed_type = "popup"
    const target_element_class = "surface-form-button"
    const c = new SurfaceEmbed(surface_src, surface_embed_type, target_element_class)
  })();
</script>

<!-- End of Surface Form Embed -->
```

Replace &#x2A;*`REPLACE ME WITH FORM URL`** with your form URL. Click the share
button in the Surface app to find it.

## Choose Trigger Buttons [#choose-trigger-buttons]

Add the class `surface-form-button` to any element that should open the form.

```html
<button class="... surface-form-button"> </button>
```

## Control Popup Size [#control-popup-size]

Set `popupSize` to control how large the popup is:

```html
<!-- Start Surface Form Embed -->

<script>
  (function () {
    const surface_src = "REPLACE ME WITH FORM URL";
    const surface_embed_type = "popup";
    const target_element_class = "surface-form-button";
    const c = new SurfaceEmbed(surface_src, surface_embed_type, target_element_class);

    c.popupSize = "medium"; // This value can be "small", "medium", or "large"
  })();
</script>

<!-- End of Surface Form Embed -->
```

## Direct Link [#direct-link]

Append `showSurfaceForm=true` to the url of your website.

For example:

```
https://YOUR_WEBSITE.com/?showSurfaceForm=true
```

<Info>
  Replace `YOUR_WEBSITE.com` with your actual website URL.
</Info>

The popup opens on page load, with no trigger button to click.

## Optimize Speed [#optimize-speed]

Add the following `<link>` tags inside the `<head>` of your site:

```html
<!-- Speed up connections to forms.withsurface.com by performing early DNS resolution and TCP handshake -->
<link rel="dns-prefetch" href="https://forms.withsurface.com">
<link rel="preconnect" href="https://forms.withsurface.com" crossorigin>

<!--  Fetch the form in advance, so it's ready when a user opens it. -->
<link rel="prefetch" href="REPLACE ME WITH FORM URL" as="document">
```

<Info>
  Replace `REPLACE ME WITH FORM URL` with a Surface Form URL.
</Info>

<Info>
  If the form uses a custom domain, replace `forms.withsurface.com` in the connection hints with your verified domain. See [Use the Surface Tag with a Custom Domain](/platform/traffic/custom-domains).
</Info>

### Explanation [#explanation]

1. dns-prefetch → Resolves the domain early to skip DNS lookup delays.
2. preconnect → Prepares the TCP + TLS handshake so the browser is ready to request assets immediately.
3. prefetch → Fetches the form in advance, so it's ready when a user opens it.

## Where to Paste It [#where-to-paste-it]

The script is the same on every platform. What changes is where it goes, and
how the trigger element gets the `surface-form-button` class.

<Tabs>
  <Tab title="Webflow">
    Webflow [dashboard](https://webflow.com/dashboard) → **Project Settings** →
    **Custom Code**, and paste it into the **Footer Code** section. Publish the
    site for it to take effect.

    Then give the trigger element the class: select the button in Designer, open
    the **Style** panel, and add `surface-form-button` to the Style Selector.
  </Tab>

  <Tab title="Framer">
    Framer → project **Settings** → **Custom Code** → **End of `<body>` tag**.

    Framer has no class field, so the trigger needs a code override. In the
    element's **Code Overrides**, create a file called `SurfaceFormButton` and
    add:

    ```tsx
    export function withClass(Component): ComponentType {
      return (props) => {
        props.className += " surface-form-button" // keep the leading space
        return <Component {...props} />
      }
    }
    ```

    Then select `SurfaceFormButton` → `withClass` on the element.

    <Tip>
      Custom code is a paid Framer feature.
    </Tip>
  </Tab>

  <Tab title="WordPress">
    Use a header/footer plugin. [WPCode](https://wordpress.org/plugins/insert-headers-and-footers/)
    is the usual choice. **Code Snippets → Header & Footer**, paste into the
    **Footer** box, save.

    Add `surface-form-button` to the trigger element's CSS classes in the block
    editor's **Advanced** panel.
  </Tab>

  <Tab title="Next.js">
    In `app/layout.tsx` (App Router) or `pages/_document.tsx` (Pages Router),
    using `next/script` with `strategy="afterInteractive"`:

    ```tsx
    import Script from "next/script";

    <Script
      id="surface-form-script"
      strategy="afterInteractive"
      dangerouslySetInnerHTML={{ __html: `
        (function () {
          const surface_src = "REPLACE ME WITH FORM URL";
          const surface_embed_type = "popup";
          const target_element_class = "surface-form-button";
          new SurfaceEmbed(surface_src, surface_embed_type, target_element_class);
        })();
      `}}
    />
    ```

    Then `<button className="surface-form-button">Open form</button>`.
  </Tab>

  <Tab title="React">
    In `public/index.html`, at the end of `<body>`.

    Then `<button className="surface-form-button">Open form</button>` anywhere in
    your tree. The embed script binds by class, so it works with elements React
    renders later.
  </Tab>

  <Tab title="Unbounce">
    In the page editor's bottom toolbar → **JavaScript** → **Add New JavaScript*&#x2A;,
    with placement &#x2A;*"Before the body Tag"**.

    Unbounce loads scripts unpredictably, so guard the constructor and run it on
    first interaction:

    ```html
    <script>
      let surfaceInitialized = false;
      function initializeSurfaceForm() {
        if (surfaceInitialized || typeof SurfaceEmbed === "undefined") return;
        surfaceInitialized = true;
        new SurfaceEmbed("REPLACE ME WITH FORM URL", "popup", "surface-form-button");
      }
      document.addEventListener("click", initializeSurfaceForm, { once: true });
      document.addEventListener("scroll", initializeSurfaceForm, { once: true });
    </script>
    ```
  </Tab>

  <Tab title="HTML">
    Anywhere before `</body>`, on every page that has a trigger element. Give
    that element `class="surface-form-button"`.
  </Tab>
</Tabs>
