Skip to content
All guides

Connect your Jekyll form.

Simplest

Ask your agent

  1. 1

    Open your Jekyll project in your coding agent and paste: “Use Ellieforms: ellieforms.com/agent”.

  2. 2

    Sign in from the link your agent shows. Check that the short code matches.

  3. 3

    Your agent connects your HTML form, loads the Ellieforms script and builds loading, success and error feedback in your site's design.

  4. 4

    Your agent sends a setup test and checks delivery. Look for the [TEST] email, then publish and test again on the live site.

Your agent keeps your design. On the Free plan, a small “Sent with Ellieforms” link appears under your form.

For developers

Set it up yourself

The same connection by hand, in about ten minutes. The result is identical to what an agent builds.

1. Create the form in Ellieforms

  1. Sign in at app.ellieforms.com with Google or your email.
  2. Open Forms → Add website. Type the site's web address, so messages from it are trusted straight away.
  3. Press + Form, name it (“Contact form”), then open Code.
  4. Copy your form ID (it starts with frm_) and your badge link. In the code below, replace frm_YOUR_FORM_ID and YOUR_BADGE_LINK with them.

2. Add the code to your Jekyll project

  1. Save the form as an include, then add {% include contact-form.html %} where it should appear.
  2. Add the script tag once in _layouts/default.html, before </body>.
_includes/contact-form.html
<form data-ellieforms="frm_YOUR_FORM_ID" action="https://in.ellieforms.com/f/frm_YOUR_FORM_ID" method="POST" accept-charset="UTF-8">
<label>Name <input name="name" autocomplete="name" required></label>
<label>Email <input type="email" name="email" autocomplete="email" required></label>
<label>Message <textarea name="message" required></textarea></label>
<!-- Bot trap: keep it hidden and empty -->
<input type="text" name="_fh_hp" tabindex="-1" autocomplete="off" aria-hidden="true" style="position:absolute;left:-9999px">
<button type="submit">Send</button>
</form>
<p class="form-success" role="status" hidden>Thanks! We got your message.</p>
<p class="form-error" role="alert" hidden>Sorry, that didn't send. Please try again.</p>
<p class="form-badge"><a href="YOUR_BADGE_LINK">Sent with Ellieforms</a></p>
<script>
// Ellieforms shows nothing to visitors. This code shows the result.
document.addEventListener("ellieforms:sent", (event) => {
event.target.hidden = true;
document.querySelector(".form-success").hidden = false;
});
document.addEventListener("ellieforms:error", () => {
document.querySelector(".form-error").hidden = false;
});
</script>
_layouts/default.html
    <!-- … -->
<script src="https://in.ellieforms.com/v1/f.js" defer></script>
</body>

The published site stays static. No server runs alongside it.

3. Test, then go live

  1. Publish your site, open the page and send one message through the form.
  2. It appears in your Ellieforms inbox, and Ellieforms learns the form's fields from it.
  3. In Forms, press Go live. That locks in the fields, so Ellieforms notices if the form changes later.

Free sends one daily summary of real messages; Pro and Team alert you instantly.

Advanced

Everything the code above relies on, for adapting it to your own setup.

What goes on the form

Attribute or fieldRequiredWhy
data-ellieforms="frm_YOUR_FORM_ID"YesTells the script which form this is.
action="https://in.ellieforms.com/f/frm_YOUR_FORM_ID", method="POST"YesThe fallback: if JavaScript fails, the browser still posts the message there.
accept-charset="UTF-8"RecommendedKeeps every language intact in the fallback post.
name on every fieldYesFields without a name are not sent. Repeated names (checkboxes) arrive joined with commas.
Hidden _fh_hp fieldYesA bot trap. People never see it; bots fill it in. Keep it off-screen exactly as shown.
data-ellieforms-mode="call"Only with your own handlerThe script stops handling submit, and your code calls ellieforms.send(form).

The script

Load https://in.ellieforms.com/v1/f.js exactly as shown, once per page, with defer. Don't bundle it, copy it, or add an integrity attribute: fixes reach every site from one place, and v1 never changes in a breaking way. It sets no cookies and makes no third-party requests. On load it solves an invisible bot check for each form, so sending is instant when the visitor clicks.

You useWhat you get
ellieforms:sent eventFired on the form after a successful send; it bubbles. event.detail is { ok: true, status, id }.
ellieforms:error eventFired when sending failed. detail is { ok: false, status }, with network: true when the visitor is offline. In automatic mode the script then falls back to the plain post, so the message still arrives.
await window.ellieforms.send(form)Call mode. Sends the HTMLFormElement you pass (never a component or data object), retries twice, fires the same events and returns true or false.

Forms added later (client-side navigation, htmx swaps, modals) work without extra code: the script listens on the whole page.

Show a sending state

In automatic mode the script takes over the submit. To disable the button while sending, switch to call mode and send from your own handler:

contact.html
<form id="contact" data-ellieforms="frm_YOUR_FORM_ID" data-ellieforms-mode="call"
action="https://in.ellieforms.com/f/frm_YOUR_FORM_ID" method="POST" accept-charset="UTF-8">
<!-- the same fields, trap and button as above -->
</form>

<script>
const form = document.getElementById("contact");
form.addEventListener("submit", async (event) => {
event.preventDefault();
if (!window.ellieforms) return form.submit(); // script blocked: the plain post still delivers
const button = form.querySelector("button");
button.disabled = true;
document.querySelector(".form-error").hidden = true;
const ok = await window.ellieforms.send(form);
button.disabled = false;
form.hidden = ok;
document.querySelector(ok ? ".form-success" : ".form-error").hidden = false;
});
</script>

Limits and changes

  • Up to 100 fields, 10,000 characters per field and 32 KB per message. File uploads are not sent.
  • The visitor's email address (usually a field named email) becomes the Reply-To of your alert, so you can answer straight from your inbox.
  • Changed the form's fields after going live? Messages still arrive, with a note asking you to confirm the new version. To relearn on purpose: Forms → Relearn fields, send one message, then Go live.
  • Visitors without JavaScript return to your home page after sending, or to your own thank-you page: Forms → Settings.
  • Want Cloudflare Turnstile as well? Add your own keys under Forms → Advanced and put the Turnstile widget inside the form; the script sends its answer along.

Webhooks and the API

Send messages to Zapier, Make, n8n or your own server, or script the setup: see the developer docs.