Next.js - SpamBlock Pixel and Forms Integration

Learn how to integrate SpamBlock Pixel and Forms solution with Next.js forms. Complete Next.js component example with App Router patterns and optimal script loading.

Overview

This example shows how to integrate both the SpamBlock Pixel and SpamBlock Forms solution in a Next.js application using the Fetch API. The Pixel intercepts form submissions and scores them at the edge, while the Forms solution provides a hosted endpoint for receiving submissions.

Note: While the SpamBlock Pixel works with any backend endpoint, this example specifically demonstrates using both the Pixel and SpamBlock Forms together. The SpamBlock Forms endpoint (https://api.spamblock.io/f/{form_id}) provides a complete hosted form solution. Learn more about Forms or use your own backend endpoint with the Pixel.

"use client";

import { useEffect, useRef, useState } from "react";
import Script from "next/script";

export default function ContactForm() {
  const formRef = useRef(null);
  const [isSubmitting, setIsSubmitting] = useState(false);
  const [message, setMessage] = useState("");

  useEffect(() => {
    const form = formRef.current;
    if (!form) return;

    // Listen for allowed submissions from SpamBlock
    const handleAllowed = async (event) => {
      event.preventDefault();
      setIsSubmitting(true);
      setMessage("");

      const formData = new FormData(event.target);

      try {
        const response = await fetch(
          "https://api.spamblock.io/f/{form_id}",
          {
            method: "POST",
            body: formData,
          }
        );

        if (response.ok) {
          setMessage("Submission successful!");
          form.reset();
        } else {
          setMessage("There was an error submitting the form.");
        }
      } catch (error) {
        setMessage("Network error. Please try again.");
        console.error("Error:", error);
      } finally {
        setIsSubmitting(false);
      }
    };

    form.addEventListener("spamblock:allowed", handleAllowed);

    return () => {
      form.removeEventListener("spamblock:allowed", handleAllowed);
    };
  }, []);

  return (
    <>
      <Script
        src="https://pixel.spamblock.io/latest.js"
        strategy="afterInteractive"
      />
      <form ref={formRef}>
        <label htmlFor="name">Name</label>
        <input id="name" name="name" type="text" required />

        <label htmlFor="email">Email Address</label>
        <input id="email" name="email" type="email" required />

        <label htmlFor="message">Message</label>
        <textarea id="message" name="message" required></textarea>

        <button type="submit" disabled={isSubmitting}>
          {isSubmitting ? "Sending..." : "Send"}
        </button>

        {message && <p>{message}</p>}
      </form>
    </>
  );
}

What This Example Shows

  • How to integrate SpamBlock Pixel with Next.js
  • Using Next.js Script component for optimal script loading
  • Client-side form handling with React hooks
  • Proper cleanup of event listeners
  • Next.js App Router patterns ("use client" directive)

When to Use It

Use this approach when:

  • You're building a Next.js application (App Router)
  • You want to use Next.js optimized script loading
  • You need client-side form handling
  • You're using React Server Components

How it Works

  1. User submits form
  2. SpamBlock Pixel intercepts submission
  3. Submission scored at the edge
  4. If spam: submission blocked, event not fired
  5. If allowed: spamblock:allowed event fired
  6. Next.js component handles the allowed submission

Common Mistakes

  1. Missing "use client" - Client components that use hooks need this directive
  2. Not using Next.js Script - Use next/script instead of regular <script> tags for optimization
  3. Wrong script strategy - Use afterInteractive for scripts that need to run after page becomes interactive
  4. Not cleaning up event listeners - Always remove event listeners in the useEffect cleanup function
  5. Missing ref - Use useRef to access the form DOM element
  6. Server vs Client - Remember that form handling must be in a client component

Learn More