EasyContactForms
Sign in
dependency-free PHP · self-hostable

A form backend you actually own.

One script tag drops a themed, validated, spam-protected form onto any page — no build step, no framework. Behind it: dependency-free PHP over MySQL you can self-host, so the submissions live in your database, not someone else's.

  • No npm, no build
  • Unguessable IDs by default
  • Script tag or React
Paste this
<div data-easycontact="f3a9c1b7e2d4"></div>
<script src="https://api.easycontactforms.com/widget/embed.js" defer></script>
renders
The wedge

Rent a form service, or own the backend.

Most form tools are hosted-only: you pay per submission, your data sits on their servers, and the embed is a black box. This is the other option.

Saved money

No per-submission tax

Self-host on a server you already pay for and the recurring form-SaaS bill goes to zero. For an agency running many client sites, the saving compounds per site.

Saved time

Drop-in, not stand-up

A working, validated, spam-protected form in the time it takes to paste two lines — versus writing a POST handler, storage, validation and an admin view yourself.

Saved nerves

Your data, your rules

Submissions land in your database. Nothing leaves your infrastructure, so your GDPR and data-residency story is simply “it’s on our server.”

One tag, any page

Static site, Jamstack, or plain HTML — it just mounts.

No bundler, no npm install. Configure everything through data-attributes; the widget reads them and renders itself.

Full-page contact section
<div data-easycontact="f3a9c1b7e2d4"
     data-easycontact-theme="dark"
     data-easycontact-layout="page"
     data-easycontact-heading="Get in touch"></div>
Inside a React app
import { ContactForm } from './ContactForm';

<ContactForm token="f3a9c1b7e2d4" theme="auto" />

A backend whose whole job is to never drop a message.

Stored the instant it's submitted, addressable only by an unguessable ID, and surfaced in a dashboard that flags it amber until it's answered. The hard parts are done; you own the result.

Done right, so you don’t have to

The security-sensitive parts, handled.

The details that are easy to get wrong when you roll your own — and expensive when you do.

Unguessable identifiers

Every external ID is a random UUIDv4 or hex token. Sequential auto-increment keys never leave the server, so nobody can walk to a neighbouring record.

Uniform 404 authorization

Missing row or not yours? Identical 404. A 403 would confirm the ID exists — exactly what an attacker is fishing for. Scoping is enforced server-side.

Honeypot spam protection

A hidden field silently drops bots at submit time. No CAPTCHA, no third-party risk-scoring, no friction for real visitors.

Idempotent migrations

The migration runner records what it applied and is safe to run twice. It converts a pre-forms database in place without changing existing tokens.

Graceful fallback fields

If a form’s config can’t be fetched, the widget renders classic name/email/message fields the backend still accepts — never a blank page.

Multi-form data model

Projects own forms; forms own ordered field definitions; submissions snapshot field labels and types, so editing a form never rewrites history.

0runtime dependencies — no Composer, no framework, no build
2 linesto embed on any page you control
UUIDv4on every identifier that leaves the server
1 cmdidempotent migration to upgrade an existing install
Questions

What developers ask first.

Both. The backend is dependency-free PHP 8 over MySQL/MariaDB — clone the repo, point it at a database, serve the directory. There is a hosted API at api.easycontactforms.com if you would rather not run anything, but nothing forces you to: self-host and every submission stays in your own database.

Own the form backend. Ship in two lines.

Grab a token, paste the snippet, and self-host whenever you’re ready — the data’s yours either way.