1. Embed the Surface Form

  1. Using iFrame

    <iframe
        id="surface-iframe"
        src="<your_form_link>"
        frameborder="0"
        allowfullscreen>
    </iframe>
  2. Using Script (Recommended)

    • Go to your Next.js project and create a new file surfaceForm-script.tsx and add the following code:
    /* eslint-disable @typescript-eslint/no-explicit-any */
     "use client";
     import Script from "next/script";
     import { useEffect, useState } from "react";
    
     declare global {
     interface Window {
         SurfaceEmbed: any;
         showSurfaceForm: any;
     }
     }
    
     export type SurfaceEmbedType = {
     formUrl: string;
     popupSize?: "small" | "medium" | "large";
     children?: React.ReactNode;
     };
    
     export function SurfaceFormScript() {
     return (
         <Script
         src="https://cdn.jsdelivr.net/gh/trysurface/scripts@latest/surface_tag.min.js"
         type="application/javascript"
         strategy="afterInteractive"
         onLoad={() => {
             // @ts-expect-error - SurfaceEmbed is available on the global window object
             window.SurfaceEmbed = SurfaceEmbed;
         }}
         />
     );
     }
    
     export default function ShowSurfaceForm({
     formUrl,
     popupSize
     }: SurfaceEmbedType) {
     const [isFormInitialized, setIsFormInitialized] = useState(false);
     useEffect(() => {
         if (!isFormInitialized) {
         
         const SurfaceConstructor = new window.SurfaceEmbed(
             formUrl,
             "popup",
             "surface-form-button"
         );
         if (popupSize) {
             SurfaceConstructor.popupSize = popupSize;
         }
         SurfaceConstructor.embedSurfaceForm();
         window.showSurfaceForm = () => {
             SurfaceConstructor.showSurfaceForm();
         }
         setIsFormInitialized(true);
         }
     }, [formUrl, isFormInitialized, popupSize]);
     return null;
     }

    This script extends a function window?.showSurfaceForm() which can be used to open the form programmatically.

    • For App Router Now let’s add the SurfaceFormScript() component to the app/layout.tsx file:
    export default function RootLayout({
    children,
    }: Readonly<{
    children: React.ReactNode;
    }>) {
    return (
        <html lang="en">
    
        <SurfaceFormScript /> {/* Import the SurfaceFormScript component and add here */}
    
        <body>
    
             <ShowSurfaceForm
                 formUrl="your_form_url"
                 popupSize="medium" {/* small, medium or large */}
             />
    
            {children}
    
        </body>
        </html>
    );
    }
    • For Page Router Now let’s add the ShowSurfaceForm component to the pages/_app.tsx file:
    import Script from 'next/script'
    import { SurfaceFormScript } from '../surfaceForm-script'
     
     export default function MyApp({ Component, pageProps }) {
         return (
             <>
                 <Component {...pageProps} />
                 <SurfaceFormScript /> {/* Import the SurfaceFormScript component and add here */}
             </>
         )
     }
    • Give a className to the button or div where you want to show the form:
    <div className="surface-form-target"></div>
    • In the same file where you want to show the form, import <ShowSurfaceForm /> component and add the following code:
    export default function Home() {
        return (
            <div>
                <button className="surface-form-button or surface-form-target">Open Form</button>
            </div>
        );
    }
    Or
    • If you want to open the form programmatically, you can use the following code:
    export default function Home() {
        return (
            <div>
                <button onClick(() => window?.showSurfaceForm())>Open Form</button>
            </div>
        );
    }

2. All done!

You have successfully integrated Surface Forms with your Next.js application. You can now embed forms in your Next.js application.