Skip to main content
Any <form> on an ElasticFunnels page can store its entries in a collection. The builder does this for you when you drag a form onto the page. This page is for when you write the HTML yourself: in the code editor, with the ef CLI, or with an AI agent. A form needs two things:
  1. A collection with one field for each input you want to keep.
  2. A form whose action is /api/collection/<code>/store, where <code> is the collection’s code.

With the ef CLI or an AI agent

If you work with the ef CLI, the fastest route is to ask your agent. ef init (and ef claude) writes the ElasticFunnels guidance into your project’s CLAUDE.md, and ef codex writes the same into AGENTS.md. That guidance covers forms and collections, so in Claude Code you can say “add a form that collects phone numbers to the landing page” and it creates the collection and writes the markup. To do it yourself, create the collection first and note the code it prints:
Each --field is name:type[:required]. Types are text, email, number, checkbox, password, textarea, select and hidden.
Name each field exactly like the input’s name attribute, in lowercase (email, not Email). When you save the page, ElasticFunnels compares the inputs in your form with the collection’s field names. An input with no field of the same name gets a new field added, with a suffix on its key, and the input no longer matches it. If that new field is required, every submission fails with “is required”. Keep field names short too: keys are cut to 15 characters.
Then point the form at it:
Other commands you’ll use:

Without the CLI

  1. Go to Pages → Advanced → Collections and click Create Collection.
  2. Add one field per input, named exactly like the input’s name attribute (see the warning above).
  3. Save, and copy the collection’s code.
  4. Paste the form above into your page’s code, with your code in place of 4k2xqa.

Let ElasticFunnels create the collection

You can also write a plain form with no action:
When you save or push the page, ElasticFunnels creates a collection from the inputs and rewrites the form: it sets the action, adds data-collection attributes and inserts success and error message elements. ef push prints the new code and saves the rewritten HTML back into your local file, so open the file again before your next edit. Two limits:
  • It is skipped when the page contains template syntax anywhere ({{ }}, @if, @foreach, @set, @extends). Use the route above for those pages.
  • Any form with a non-empty action that is not /api/collection/.../store is left alone. Use that for search boxes or forms that post somewhere else.

Full example: a form that collects phone numbers

One phone field and a checkbox that starts unticked. Hidden fields keep the exact wording shown next to the box, the page address and the time the visitor submitted. Tested on a live demo page. Create the collection:
Paste the form, with your code in place of 0ws38w and your own wording and links:
The entry it stores:
Phone numbers are kept as typed, so ask for the country code in the label or placeholder. If you’d rather accept numbers without the checkbox ticked, drop :required from sms_opt_in and the required attribute from the checkbox.
An entry is stored data only. Saving it doesn’t add the number to any text message list and doesn’t send a text to anyone.

How the form behaves

ElasticFunnels’ page script sends every form whose action starts with /api/ and shows the result, without reloading the page.
  • Errors. Server errors (“phone is required”, “Your session has expired”) appear in the element with data-form-error-message. Without one, a red box appears above the submit button.
  • Success. The element with data-form-success-message shows “Thank you for submitting the form.” and the form is cleared. Saving the page resets the data-success-message attribute, so for your own wording use the on-form-success event as in the example.
  • Redirect. Add data-redirect-url="/thank-you" to the <form> to send the visitor to another page after a successful entry.
  • Checks. Required fields, email fields and number fields are checked on the server. Text fields are also screened for random-looking spam text. If the collection has reCAPTCHA v3 turned on, put <div data-recaptcha-v3="true" data-site-key="YOUR_SITE_KEY"></div> inside the form.
  • Session. The form only works on pages served by ElasticFunnels. It sends a security token from the page, so a copy of the form on another site is rejected.

Where entries show up

  • Collections. Go to Pages → Advanced → Collections and open the collection to see each entry with its fields.
  • CRM. Every collection has a matching CRM entity, and each entry is also a record there.
  • CLI. ef collections entries <code> lists the stored entries.
  • Export. Download entries as CSV, see Export form data.

How an entry links to a visitor

Each entry stores the visitor’s session id and IP address with the fields. The submission also counts as a form-submit event for that visit in your analytics. An entry doesn’t create or update a customer, and a phone number in it isn’t matched to an existing customer. If the form has an email field, the form-submit event also carries a hashed copy of that email. The entry itself stays a collection record.