Jekyll contact form

Jekyll builds the page and the browser posts it, so there is no plugin to install and nothing to run on the server. The form is an include, and the two values it needs live in _config.yml.

The include

<form action="https://api.ezform.io/f/{{ site.ezform.form_id }}" method="POST">
  <label for="email">Email</label>
  <input id="email" name="email" type="email" required>

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

  <div style="position:absolute;left:-9999px" aria-hidden="true">
    <label for="{{ site.ezform.honeypot }}">Company website</label>
    <input
      id="{{ site.ezform.honeypot }}"
      name="{{ site.ezform.honeypot }}"
      type="text"
      tabindex="-1"
      autocomplete="off">
  </div>

  <button type="submit">Send</button>
</form>
ezform:
  form_id: YOUR_FORM_ID
  honeypot: YOUR_HONEYPOT_FIELD

Using it in a page

---
layout: page
title: Contact
---

Tell us what you need and we will get back to you.

{% include ezform-form.html %}

The front matter at the top is not decoration. A file without it is copied to the output untouched, Liquid and all, so the include tag ends up in the page as literal text and no form is rendered. If the form is missing and the page otherwise looks right, that is the first thing to check.

Allow your origins

Scheme and host, no path, one entry each:

  • http://localhost:4000 for jekyll serve, if you test against the real endpoint rather than filling the console in by hand.
  • Your production host. The apex and www. are two different origins.

On GitHub Pages the origin is the host alone, so a project site published at https://you.github.io/project is served from the origin https://you.github.io. Allowlist that, with no path, and it covers every project site on the same account. A custom domain is its own origin and needs its own entry.

A submission from an origin that is not listed is discarded and never stored, which is what keeps someone who read your form ID out of your inbox. It is also the first thing to check when a form appears to do nothing: see Responses and failure.

What happens when someone submits

The browser posts the form and navigates. Configure a redirect path on the form in the console and ezform answers 303 to that page, so a refresh cannot repost the submission. Without one, ezform renders its own short confirmation page.

The site ships no JavaScript for any of this, so the form still works with JavaScript turned off.

Where to go next