Eleventy contact form

Eleventy builds the page and the browser posts it, so nothing runs at submit time and no plugin is involved. The form is an include, and the two values it needs come from a global data file.

Global data and the include

A data file keeps the two values out of the template, so a second form later is a second entry rather than a second copy of the markup.

// Eleventy 3 is ESM. On 2.x, write this as `module.exports = { ... }`.
export default {
  formId: process.env.EZFORM_FORM_ID,
  honeypot: process.env.EZFORM_HONEYPOT_FIELD,
}
<form action="https://api.ezform.io/f/{{ ezform.formId }}" 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="{{ ezform.honeypot }}">Company website</label>
    <input
      id="{{ ezform.honeypot }}"
      name="{{ ezform.honeypot }}"
      type="text"
      tabindex="-1"
      autocomplete="off">
  </div>

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

Drop it into a Nunjucks template with {% include "ezform-form.njk" %}.

Including it from Markdown

Eleventy renders Markdown files through Liquid unless you tell it otherwise, so a Nunjucks include written in a .md file does not run and does not complain. Either write the include in Liquid’s syntax, or change the default for Markdown and keep one syntax across the site:

export default function (eleventyConfig) {
  return {
    markdownTemplateEngine: 'njk',
  }
}

A missing form with an otherwise correct-looking page is almost always this.

Allow your origins

Scheme and host, no path, one entry each:

  • http://localhost:8080 for eleventy --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.
  • Any preview host your deploy setup gives you.

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.

Nothing here ships JavaScript, so the form still works with it turned off.

Where to go next