Dashboard

Embedding in React & Next.js

Add FavForm to your React or Next.js application with our SDK or iframe.

Quick start (Script tag)

The simplest approach — load the SDK and use the web components:

TSX
// app/contact/page.tsx (Next.js App Router)
import Script from 'next/script'

export default function ContactPage() {
  return (
    <div>
      <h1>Contact Us</h1>
      
      {/* FavForm embed */}
      <fav-form data-embedId="your-form-id" />
      
      {/* Load SDK */}
      <Script 
        src="https://favform.com/embed/v1.js" 
        strategy="lazyOnload" 
      />
    </div>
  )
}

TypeScript declarations

Add type declarations for the custom elements:

TypeScript
// types/favform.d.ts
declare namespace JSX {
  interface IntrinsicElements {
    'fav-form': React.DetailedHTMLProps<
      React.HTMLAttributes<HTMLElement> & {
        'data-embedId'?: string
      },
      HTMLElement
    >
  }
}

Reusable component

Create a reusable FavForm component:

TSX
// components/FavForm.tsx
'use client'

import { useEffect } from 'react'

interface FavFormProps {
  embedId: string
  className?: string
}

export function FavForm({ embedId, className }: FavFormProps) {
  useEffect(() => {
    // Load SDK if not already loaded
    if (typeof window !== 'undefined' && !document.querySelector('script[src*="favform.com"]')) {
      const script = document.createElement('script')
      script.src = 'https://favform.com/embed/v1.js'
      script.async = true
      document.body.appendChild(script)
    }
  }, [])

  return (
    <div className={className}>
      <fav-form data-embedId={embedId} />
    </div>
  )
}

// Usage:
// <FavForm embedId="your-form-id" />

Using iframe

For simpler integration without custom elements:

TSX
// components/FavFormIframe.tsx
interface FavFormIframeProps {
  formId: string
  height?: number
  className?: string
}

export function FavFormIframe({ 
  formId, 
  height = 600, 
  className 
}: FavFormIframeProps) {
  return (
    <iframe
      src={`https://favform.com/f/${formId}`}
      width="100%"
      height={height}
      frameBorder="0"
      className={className}
      style={{ border: 'none' }}
      title="FavForm"
    />
  )
}

Next.js App Router

For Next.js 13+ with the App Router:

TSX
// app/layout.tsx
import Script from 'next/script'

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en">
      <body>
        {children}
        
        {/* Load FavForm SDK globally */}
        <Script 
          src="https://favform.com/embed/v1.js" 
          strategy="lazyOnload"
        />
      </body>
    </html>
  )
}
Loading the SDK in the root layout makes it available on all pages without re-loading.

Site-wide widget

Add a feedback widget to your entire app:

TSX
// app/layout.tsx
import Script from 'next/script'

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en">
      <body>
        {children}
        
        {/* Feedback widget */}
        <fav-form data-embedId="your-widget-id" />
        
        <Script 
          src="https://favform.com/embed/v1.js" 
          strategy="lazyOnload"
        />
      </body>
    </html>
  )
}

Dynamic form IDs

Load different forms based on route or state:

TSX
// app/forms/[slug]/page.tsx
import { FavForm } from '@/components/FavForm'

const embedIds: Record<string, string> = {
  contact: 'form-id-1',
  feedback: 'form-id-2',
  support: 'form-id-3',
}

export default function FormPage({ 
  params 
}: { 
  params: { slug: string } 
}) {
  const embedId = embedIds[params.slug]
  
  if (!embedId) {
    return <div>Form not found</div>
  }
  
  return <FavForm embedId={embedId} />
}

Polls and widgets

TSX
// Poll component
<fav-form data-embedId="your-poll-id" />

// Widget component  
<fav-form data-embedId="your-widget-id" />

Troubleshooting

Hydration mismatch

Custom elements may cause hydration warnings. Use 'use client' and load the SDK in useEffect.

TypeScript errors

Add the type declarations shown above to your project's types folder.

Form not rendering in SSR

Custom elements only work client-side. The form will render after hydration. Use the iframe method for SSR-friendly embedding.

Script loading multiple times

Check for the script before adding it, or load it once in your root layout.