# Widget Form Embed



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

## Edit Surface Form Embedding Script [#edit-surface-form-embedding-script]

Edit the Surface Form embedding script to display the form as a widget:

```html
<!-- Start Surface Form Embed -->
<script>
  (function() {
    const surface_src = "surface_form_url";
    const surface_embed_type = "widget"; // switch to "widget" to display the form as a widget
    const target_element_class = "surface-form-button";
    const c = new SurfaceEmbed(
        surface_src,
        surface_embed_type,
        target_element_class,
        {
            widgetStyles: {
                position: "right",
                bottomMargin: "40px",
                sideMargin: "30px",
                size: "64px",
                backgroundColor: "#1a56db",
                hoverScale: "1.05",
                boxShadow: "0 6px 12px rgba(0,0,0,0.25)"
            }, // customize the widget appearance
        }
    );

    c.popupSize = "small";
  })();
</script>
<!-- End of Surface Form Embed -->
```

## Customize Widget Appearance [#customize-widget-appearance]

Adjust the `widgetStyles` options on the `SurfaceEmbed` instance:

```javascript
widgetStyles: {

    position: "right", // position of the widget (right, left)

    bottomMargin: "40px", // margin from the bottom of the page (in px)
    
    sideMargin: "30px", // margin from the side of the page (in px)
    
    size: "64px", // size of the widget (in px)
    
    backgroundColor: "#1a56db", // background color of the widget (in hex)
    
    hoverScale: "1.05", // scale of the widget when hovered (in decimal)
    
    boxShadow: "0 6px 12px rgba(0,0,0,0.25)" // shadow of the widget (in hex)

}
```

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

Clicking the widget opens a popup. Set `popupSize` on the `SurfaceEmbed`
instance to `small`, `medium` or `large`.

```javascript
c.popupSize = "small";
```

## Use It with Popup Embedding [#use-it-with-popup-embedding]

The widget only inherits the popup embedding type, so you can still add the
`surface-form-button` class to any HTML element to trigger the popup.

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

The widget renders its own button, so no trigger class is needed. The class
instructions in the tabs below only apply if you also want a second, in-page
trigger.

<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>
