Prerequisites

  • A Next.js application (version 13 or higher recommended)
  • Your SixtyFour AI API credentials:
    • SIXTYFOUR_INBOUND_API_KEY
    • SIXTYFOUR_ORG_ID

Step 1: Set Up Environment Variables

First, add your SixtyFour AI credentials to your .env.local file:

SIXTYFOUR_INBOUND_API_KEY=your_api_key_here
SIXTYFOUR_ORG_ID=your_organization_id_here
NEXT_PUBLIC_API_ENDPOINT=https://api.inbound.sixtyfour.ai/enrich-lead

Once you have an active subscription, you will see your API Key in the api-keys tab like this:

Your org-id is visible on the sidebar when you hover over your profile picture.

Note: While we’re using NEXT_PUBLIC_ prefix for simplicity in this example, in production you should handle the API key server-side only.

Step 2: Create the API Route

Create a new API route in your Next.js application at app/api/interestForm/route.ts:

import { NextResponse } from 'next/server';

export async function POST(request: Request) {
  try {
    const formData = await request.json();

    // Generate unique IDs for tracking
    const submission_id = Math.random().toString(36).substring(2, 8);
    const respondent_id = Math.random().toString(36).substring(2, 8);

    // These coould be any fields of your choice
    // We recommend collecting atleast the name + company email + company name for best results
    const payload = {
      lead_data: {
        submission_id,
        respondent_id,
        submitted_at: new Date().toISOString(),
        name: formData.name,
        email: formData.email,
        phone_number: null,
        inquiry: null,
        upload_link: null,
        role: null,
        role_other: null,
        heard_about_us: "Website Form",
        heard_about_us_other: null,
        terms_agreed: null
      },
      // Make sure to pass this
      customer_id: process.env.SIXTYFOUR_ORG_ID
    };

    const response = await fetch(process.env.NEXT_PUBLIC_API_ENDPOINT!, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'x-api-key': process.env.SIXTYFOUR_INBOUND_API_KEY!
      },
      body: JSON.stringify(payload)
    });

    if (!response.ok) {
      const errorData = await response.json().catch(() => ({}));
      const statusCode = response.status;
      throw new Error(`Failed to submit lead: API responded with status ${statusCode}. ${JSON.stringify(errorData)}`);
    }

    return NextResponse.json({ success: true });
  } catch (error) {
    console.error('Error submitting lead:', error);
    return NextResponse.json(
      { error: 'Failed to submit lead' },
      { status: 500 }
    );
  }
}

Step 3: Create the Frontend Form Component

Create a new component for your lead capture form. Here’s an example using React and Shadcn UI:

'use client'

import { useState, useEffect } from 'react'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
import { Card } from '@/components/ui/card'
import { CheckCircle } from 'lucide-react'

export default function LeadCaptureForm() {
    const [isSubmitting, setIsSubmitting] = useState(false)
    const [isSubmitted, setIsSubmitted] = useState(false)
    const [formDisabled, setFormDisabled] = useState(false)

    // Check if form was already submitted in this session
    useEffect(() => {
        const hasSubmitted = sessionStorage.getItem('formSubmitted') === 'true'
        if (hasSubmitted) {
            setFormDisabled(true)
            setIsSubmitted(true)
        }
    }, [])

    const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
        e.preventDefault();
        setIsSubmitting(true);
        const form = e.currentTarget;
        const formData = {
            name: (form.elements.namedItem('name') as HTMLInputElement).value,
            email: (form.elements.namedItem('email') as HTMLInputElement).value,
            company: (form.elements.namedItem('company') as HTMLInputElement).value,
        };

        try {
            const response = await fetch('/api/interestForm', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify(formData),
            });

            if (!response.ok) {
                throw new Error('Submission failed');
            }

            // Clear form and update state
            form.reset();
            setIsSubmitted(true);
            setFormDisabled(true);
            sessionStorage.setItem('formSubmitted', 'true');
        } catch (error) {
            console.error('Error:', error);
        } finally {
            setIsSubmitting(false);
        }
    };

    return (
        <Card className="mx-auto max-w-lg p-8 shadow-md">
            <form onSubmit={handleSubmit} className="space-y-6">
                <div className="space-y-3">
                    <Label htmlFor="name">Full name</Label>
                    <Input type="text" id="name" required disabled={formDisabled} />
                </div>
                <div className="space-y-3">
                    <Label htmlFor="email">Work Email</Label>
                    <Input type="email" id="email" required disabled={formDisabled} />
                </div>
                <div className="space-y-3">
                    <Label htmlFor="company">Company</Label>
                    <Input type="text" id="company" required disabled={formDisabled} />
                </div>

                <Button 
                    type="submit" 
                    className="w-full bg-gradient-to-r from-[#5FA5F9] to-[#2463EB] hover:opacity-90 hover:shadow-lg"
                    disabled={isSubmitting || formDisabled}
                >
                    {isSubmitting ? (
                        <span className="flex items-center justify-center">
                            <svg className="animate-spin -ml-1 mr-2 h-4 w-4 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
                                <circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
                                <path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
                            </svg>
                            Submitting...
                        </span>
                    ) : isSubmitted ? (
                        <span className="flex items-center justify-center">
                            <CheckCircle className="mr-2 h-4 w-4" />
                            Submitted!
                        </span>
                    ) : (
                        "Talk to Sales"
                    )}
                </Button>
            </form>
        </Card>
    );
}

Step 4: Add the Form to Your Page

Import and use the LeadCaptureForm component in your page:

import LeadCaptureForm from '@/components/LeadCaptureForm'

export default function ContactPage() {
    return (
        <section className="py-16">
            <div className="mx-auto max-w-3xl px-6">
                <h2 className="text-center text-4xl font-semibold">
                    Ready to discover prospects your competitors can't see?
                </h2>
                <p className="mt-4 text-center">
                    If traditional lead sources aren't delivering the quality or quantity of prospects you need, we'd be glad to explore how our approach might help.
                </p>
                <div className="mt-12">
                    <LeadCaptureForm />
                </div>
            </div>
        </section>
    );
}

How It Works

  1. When a user submits the form, the data is sent to your Next.js API route
  2. The API route adds tracking information and forwards the data to SixtyFour AI
  3. SixtyFour AI processes the lead and:
    • If qualified, sends an enriched profile to your email within ~60 seconds
    • All leads (qualified or not) appear on your SixtyFour dashboard
  4. The form prevents duplicate submissions using session storage

Best Practices

  1. Security: In production, consider moving the API key to server-side only
  2. Error Handling: Implement proper error messages for users
  3. Validation: Add client-side validation before submission
  4. Loading States: Show appropriate loading states during submission
  5. Success States: Provide clear feedback when submission is successful

Troubleshooting

If you encounter issues:

  1. Check your environment variables are correctly set
  2. Verify the API endpoint is correct
  3. Ensure your API key has the necessary permissions
  4. Check the browser console and server logs for errors
  5. Contact support at saarth@sixtyfour.ai for assistance