Code Examples

Code Examples

Real-world integration examples for popular frameworks and platforms.

HTML Form

Basic HTML Contact Form

The simplest way to get started

A basic HTML form that works anywhere - no framework required.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Contact Form</title>
  <style>
    .form-group { margin-bottom: 1rem; }
    label { display: block; margin-bottom: 0.5rem; }
    input, textarea {
      width: 100%;
      padding: 0.5rem;
      border: 1px solid #ccc;
      border-radius: 4px;
    }
    button {
      padding: 0.75rem 1.5rem;
      background: #FF6B9D;
      color: white;
      border: none;
      border-radius: 8px;
      cursor: pointer;
    }
  </style>
</head>
<body>
  <h1>Contact Us</h1>

  <form action="https://formigo.com/f/your-form" method="POST">
    <div class="form-group">
      <label for="name">Name *</label>
      <input type="text" id="name" name="name" required>
    </div>

    <div class="form-group">
      <label for="email">Email *</label>
      <input type="email" id="email" name="email" required>
    </div>

    <div class="form-group">
      <label for="message">Message *</label>
      <textarea id="message" name="message" rows="5" required></textarea>
    </div>

    <!-- Spam protection -->
    <input type="text" name="_formigo_hp" value=""
           style="display:none" tabindex="-1" autocomplete="off">
    <input type="hidden" name="_formigo_t" value="">

    <button type="submit">Send Message</button>
  </form>

  <script>
    document.querySelector('input[name="_formigo_t"]').value =
      Math.floor(Date.now() / 1000);
  </script>
</body>
</html>

React / Next.js

React Contact Form with Hooks

Modern React approach using hooks and fetch

A complete React component with state management, error handling, and success messages.

import { useState, useEffect } from "react";

export default function ContactForm() {
  const [formData, setFormData] = useState({
    name: "",
    email: "",
    message: "",
  });
  const [status, setStatus] = useState("");
  const [loading, setLoading] = useState(false);

  // Set timestamp when component mounts
  useEffect(() => {
    setFormData(prev => ({
      ...prev,
      _formigo_t: Math.floor(Date.now() / 1000)
    }));
  }, []);

  const handleChange = (e) => {
    setFormData({
      ...formData,
      [e.target.name]: e.target.value,
    });
  };

  const handleSubmit = async (e) => {
    e.preventDefault();
    setLoading(true);
    setStatus("");

    try {
      const response = await fetch("https://formigo.com/f/your-form", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          ...formData,
          _formigo_hp: "", // Honeypot
        }),
      });

      if (response.ok) {
        setStatus("success");
        setFormData({ name: "", email: "", message: "" });
      } else if (response.status === 429) {
        const data = await response.json();
        setStatus(`Rate limited. Try again in ${data.retry_after}s`);
      } else {
        setStatus("error");
      }
    } catch (error) {
      setStatus("error");
      console.error("Error:", error);
    } finally {
      setLoading(false);
    }
  };

  return (
    <div className="max-w-md mx-auto">
      <h2 className="text-2xl font-bold mb-4">Contact Us</h2>

      <form onSubmit={handleSubmit} className="space-y-4">
        <div>
          <label htmlFor="name" className="block mb-2">
            Name *
          </label>
          <input
            type="text"
            id="name"
            name="name"
            value={formData.name}
            onChange={handleChange}
            required
            className="w-full px-4 py-2 border rounded-lg"
          />
        </div>

        <div>
          <label htmlFor="email" className="block mb-2">
            Email *
          </label>
          <input
            type="email"
            id="email"
            name="email"
            value={formData.email}
            onChange={handleChange}
            required
            className="w-full px-4 py-2 border rounded-lg"
          />
        </div>

        <div>
          <label htmlFor="message" className="block mb-2">
            Message *
          </label>
          <textarea
            id="message"
            name="message"
            value={formData.message}
            onChange={handleChange}
            required
            rows={5}
            className="w-full px-4 py-2 border rounded-lg"
          />
        </div>

        <button
          type="submit"
          disabled={loading}
          className="w-full px-6 py-3 bg-pink-500 text-white rounded-lg
                     hover:bg-pink-600 disabled:opacity-50"
        >
          {loading ? "Sending..." : "Send Message"}
        </button>

        {status === "success" && (
          <p className="text-green-600">
            Thank you! Your message has been sent.
          </p>
        )}

        {status === "error" && (
          <p className="text-red-600">
            Something went wrong. Please try again.
          </p>
        )}

        {status && status.includes("Rate limited") && (
          <p className="text-yellow-600">{status}</p>
        )}
      </form>
    </div>
  );
}

Vue.js

Vue 3 Contact Form

Using Composition API

<template>
  <div class="max-w-md mx-auto">
    <h2 class="text-2xl font-bold mb-4">Contact Us</h2>

    <form @submit.prevent="handleSubmit" class="space-y-4">
      <div>
        <label for="name" class="block mb-2">Name *</label>
        <input
          type="text"
          id="name"
          v-model="formData.name"
          required
          class="w-full px-4 py-2 border rounded-lg"
        />
      </div>

      <div>
        <label for="email" class="block mb-2">Email *</label>
        <input
          type="email"
          id="email"
          v-model="formData.email"
          required
          class="w-full px-4 py-2 border rounded-lg"
        />
      </div>

      <div>
        <label for="message" class="block mb-2">Message *</label>
        <textarea
          id="message"
          v-model="formData.message"
          required
          rows="5"
          class="w-full px-4 py-2 border rounded-lg"
        />
      </div>

      <button
        type="submit"
        :disabled="loading"
        class="w-full px-6 py-3 bg-pink-500 text-white rounded-lg
               hover:bg-pink-600 disabled:opacity-50"
      >
        {{ loading ? "Sending..." : "Send Message" }}
      </button>

      <p v-if="status === 'success'" class="text-green-600">
        Thank you! Your message has been sent.
      </p>

      <p v-if="status === 'error'" class="text-red-600">
        Something went wrong. Please try again.
      </p>
    </form>
  </div>
</template>

<script setup>
import { ref, onMounted } from "vue";

const formData = ref({
  name: "",
  email: "",
  message: "",
  _formigo_t: 0,
});

const loading = ref(false);
const status = ref("");

// Set timestamp when component mounts
onMounted(() => {
  formData.value._formigo_t = Math.floor(Date.now() / 1000);
});

const handleSubmit = async () => {
  loading.value = true;
  status.value = "";

  try {
    const response = await fetch("https://formigo.com/f/your-form", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        ...formData.value,
        _formigo_hp: "", // Honeypot
      }),
    });

    if (response.ok) {
      status.value = "success";
      formData.value = {
        name: "",
        email: "",
        message: "",
        _formigo_t: Math.floor(Date.now() / 1000),
      };
    } else {
      status.value = "error";
    }
  } catch (error) {
    status.value = "error";
    console.error("Error:", error);
  } finally {
    loading.value = false;
  }
};
</script>

jQuery (AJAX)

jQuery AJAX Form

For legacy projects

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Contact Form</title>
  <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
  <style>
    .form-group { margin-bottom: 1rem; }
    label { display: block; margin-bottom: 0.5rem; }
    input, textarea {
      width: 100%;
      padding: 0.5rem;
      border: 1px solid #ccc;
    }
    .message { padding: 1rem; margin-top: 1rem; border-radius: 4px; }
    .success { background: #d4edda; color: #155724; }
    .error { background: #f8d7da; color: #721c24; }
  </style>
</head>
<body>
  <h1>Contact Us</h1>

  <form id="contact-form">
    <div class="form-group">
      <label for="name">Name *</label>
      <input type="text" id="name" name="name" required>
    </div>

    <div class="form-group">
      <label for="email">Email *</label>
      <input type="email" id="email" name="email" required>
    </div>

    <div class="form-group">
      <label for="message">Message *</label>
      <textarea id="message" name="message" rows="5" required></textarea>
    </div>

    <button type="submit">Send Message</button>
  </form>

  <div id="status-message"></div>

  <script>
    $(document).ready(function() {
      // Set timestamp
      const timestamp = Math.floor(Date.now() / 1000);

      $("#contact-form").on("submit", function(e) {
        e.preventDefault();

        const formData = {
          name: $("#name").val(),
          email: $("#email").val(),
          message: $("#message").val(),
          _formigo_hp: "", // Honeypot
          _formigo_t: timestamp
        };

        $.ajax({
          url: "https://formigo.com/f/your-form",
          method: "POST",
          contentType: "application/json",
          data: JSON.stringify(formData),
          beforeSend: function() {
            $("button[type=submit]").prop("disabled", true)
                                     .text("Sending...");
            $("#status-message").empty();
          },
          success: function() {
            $("#status-message").html(
              '<div class="message success">Thank you! Your message has been sent.</div>'
            );
            $("#contact-form")[0].reset();
          },
          error: function(xhr) {
            let message = "Something went wrong. Please try again.";
            if (xhr.status === 429) {
              const data = xhr.responseJSON;
              message = `Rate limited. Try again in ${data.retry_after} seconds.`;
            }
            $("#status-message").html(
              `<div class="message error">${message}</div>`
            );
          },
          complete: function() {
            $("button[type=submit]").prop("disabled", false)
                                     .text("Send Message");
          }
        });
      });
    });
  </script>
</body>
</html>

WordPress

WordPress Integration

No plugins required

Add a contact form to any WordPress page or post. Works with Gutenberg and Classic Editor.

Step 1: Add to Your Theme

Create a file contact-form.php in your theme directory:

<!-- wp:html -->
<div class="formigo-contact-form">
  <form id="formigo-form" action="https://formigo.com/f/your-form" method="POST">
    <div class="form-group">
      <label for="name">Name *</label>
      <input type="text" id="name" name="name" required>
    </div>

    <div class="form-group">
      <label for="email">Email *</label>
      <input type="email" id="email" name="email" required>
    </div>

    <div class="form-group">
      <label for="message">Message *</label>
      <textarea id="message" name="message" rows="5" required></textarea>
    </div>

    <!-- Spam protection -->
    <input type="text" name="_formigo_hp" value=""
           style="display:none" tabindex="-1" autocomplete="off">
    <input type="hidden" name="_formigo_t" id="formigo-timestamp">

    <button type="submit">Send Message</button>
  </form>

  <div id="formigo-status"></div>
</div>

<style>
  .formigo-contact-form { max-width: 600px; margin: 2rem 0; }
  .form-group { margin-bottom: 1.5rem; }
  .form-group label { display: block; margin-bottom: 0.5rem; font-weight: 600; }
  .form-group input,
  .form-group textarea {
    width: 100%;
    padding: 0.75rem;
    border: 2px solid #ddd;
    border-radius: 8px;
  }
  button {
    padding: 0.75rem 2rem;
    background: #FF6B9D;
    color: white;
    border: none;
    border-radius: 8px;
    font-weight: 600;
    cursor: pointer;
  }
  #formigo-status { margin-top: 1rem; padding: 1rem; border-radius: 8px; }
  .success { background: #d4edda; color: #155724; }
  .error { background: #f8d7da; color: #721c24; }
</style>

<script>
  document.addEventListener("DOMContentLoaded", function() {
    // Set timestamp
    document.getElementById("formigo-timestamp").value =
      Math.floor(Date.now() / 1000);

    // Handle form submission
    document.getElementById("formigo-form").addEventListener("submit", async function(e) {
      e.preventDefault();

      const form = e.target;
      const status = document.getElementById("formigo-status");
      const submitBtn = form.querySelector("button[type=submit]");

      // Disable button
      submitBtn.disabled = true;
      submitBtn.textContent = "Sending...";
      status.innerHTML = "";

      try {
        const formData = new FormData(form);
        const data = Object.fromEntries(formData);

        const response = await fetch(form.action, {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify(data)
        });

        if (response.ok) {
          status.className = "success";
          status.innerHTML = "Thank you! Your message has been sent.";
          form.reset();
          document.getElementById("formigo-timestamp").value =
            Math.floor(Date.now() / 1000);
        } else {
          throw new Error("Submission failed");
        }
      } catch (error) {
        status.className = "error";
        status.innerHTML = "Something went wrong. Please try again.";
      } finally {
        submitBtn.disabled = false;
        submitBtn.textContent = "Send Message";
      }
    });
  });
</script>
<!-- /wp:html -->

Step 2: Use in Gutenberg

  1. Add a "Custom HTML" block to your page
  2. Paste the code above
  3. Replace your-form with your actual form slug
  4. Publish and test!

Vanilla JavaScript

Vanilla JavaScript (Modern)

No dependencies, pure ES6+

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Contact Form</title>
  <style>
    .form-group { margin-bottom: 1rem; }
    label { display: block; margin-bottom: 0.5rem; font-weight: 600; }
    input, textarea {
      width: 100%;
      padding: 0.75rem;
      border: 2px solid #ddd;
      border-radius: 8px;
    }
    button {
      padding: 0.75rem 2rem;
      background: #6BCF7F;
      color: white;
      border: none;
      border-radius: 8px;
      font-weight: 600;
      cursor: pointer;
    }
    .message { padding: 1rem; margin-top: 1rem; border-radius: 8px; }
    .success { background: #d4edda; color: #155724; }
    .error { background: #f8d7da; color: #721c24; }
  </style>
</head>
<body>
  <h1>Contact Us</h1>

  <form id="contact-form">
    <div class="form-group">
      <label for="name">Name *</label>
      <input type="text" id="name" name="name" required>
    </div>

    <div class="form-group">
      <label for="email">Email *</label>
      <input type="email" id="email" name="email" required>
    </div>

    <div class="form-group">
      <label for="message">Message *</label>
      <textarea id="message" name="message" rows="5" required></textarea>
    </div>

    <input type="hidden" id="timestamp" name="_formigo_t">

    <button type="submit">Send Message</button>
  </form>

  <div id="status"></div>

  <script>
    // Set timestamp when page loads
    document.getElementById("timestamp").value = Math.floor(Date.now() / 1000);

    // Handle form submission
    document.getElementById("contact-form").addEventListener("submit", async (e) => {
      e.preventDefault();

      const form = e.target;
      const status = document.getElementById("status");
      const submitBtn = form.querySelector("button[type=submit]");

      // Get form data
      const formData = new FormData(form);
      const data = Object.fromEntries(formData);
      data._formigo_hp = ""; // Add honeypot

      // Disable button
      submitBtn.disabled = true;
      submitBtn.textContent = "Sending...";
      status.innerHTML = "";

      try {
        const response = await fetch("https://formigo.com/f/your-form", {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
          },
          body: JSON.stringify(data)
        });

        if (response.ok) {
          status.className = "message success";
          status.textContent = "Thank you! Your message has been sent.";
          form.reset();
          // Reset timestamp
          document.getElementById("timestamp").value =
            Math.floor(Date.now() / 1000);
        } else if (response.status === 429) {
          const result = await response.json();
          status.className = "message error";
          status.textContent = `Rate limited. Try again in ${result.retry_after} seconds.`;
        } else {
          throw new Error("Submission failed");
        }
      } catch (error) {
        status.className = "message error";
        status.textContent = "Something went wrong. Please try again.";
        console.error("Error:", error);
      } finally {
        submitBtn.disabled = false;
        submitBtn.textContent = "Send Message";
      }
    });
  </script>
</body>
</html>

Need help with integration?

Whether you need a custom integration or a full web application built around Formigo, our team at WorkersLab can help.

Built by WorkersLab LLC - Custom web applications that don't break