Build forms for your October CMS site without code — with file uploads, reCAPTCHA and a log of every submission.
Demo URL: https://october-demo.renatio.com/backend/backend/auth/signin
Login: formbuilder
Password: formbuilder
Contact forms, quote requests, job applications or surveys: put the form together from ready field types, place it on a page, and every submission lands in your inbox and in the backend.
- Build and manage forms in the October CMS backend, reorder fields with drag and drop
- 21 field types out of the box, editable HTML markup for each of them and custom field types
- Custom form template with the
form_field()helper for any layout - Native AJAX file uploads with attachments in the submission and in the mail
- Google reCAPTCHA v2 and v3, Spam Protection Plugin support
- Reply-to and autoresponder with their own mail templates
- Form submissions log with e-mail preview, filters, CSV/JSON export and automatic pruning
- Import and export of forms and field types
- Granular backend permissions for forms, field types and submissions
- Events to override the form, the fields, the submitted data and the message
- RainLab Translate with Multisite, RainLab Location and RainLab Pages (form as a snippet) support
- Multilingual: English, Polish, German, French, Spanish, Brazilian Portuguese, Italian, Russian, Dutch and Czech translations included — more available on request
This plugin requires October CMS 4.x and PHP 8.2 or newer.
If you are running October CMS 3.x, use the 4.x version of this plugin.
Something that is free has little or no perceived value. Users do not commit to free products and only use them until something else that looks nice and is free comes along. When I invest my time in the development of a new plugin I commit to supporting and maintaining it. I ask my customers to do the same. I do not make money from this plugin by advertisements, upgrades or additional services like hosting or setup.
Did you know that 30% of your purchase or donation goes to help fund the October Project?
My plugins take many hours to develop (40-120+) and even more hours to document and maintain. My paid plugins have to pay for both this time, and the time I am spending on free plugins and less successful paid plugins. This means that it will take even a successful plugin years to become profitable. Please consider buying an extended license if you want me to continue to maintain these plugins for the very small fee I ask in return or hire me for adding functionality that you feel is missing but valuable.
If you like this plugin, give this plugin a like or make a donation with PayPal.
Please check my other plugins.
Please use GitHub Issues Page to report any issues with the plugin.
Reviews should not be used for getting support or reporting bugs, if you need support please use the Plugin support link.
Icon made by Darius Dan from www.flaticon.com.
After installation the plugin registers the Form Builder backend menu with four items: Forms, Field types, Form submissions and Settings. Two example forms are installed: a simple contact form and a default form that demonstrates every field type.
Place the renderForm component on a CMS page, inspect it and choose the form.
The form is submitted through the AJAX Framework, so the layout must load it next to the page styles:
<head>
{% styles %}
</head>
<body>
...
{% framework extras %}
{% scripts %}
</body>
/themes/demo/pages/contact.htm
url = "/contact"
layout = "default"
[renderForm contactForm]
formCode = "contact-form"
==
{% component 'contactForm' %}
/themes/demo/pages/contact.htm
url = "/contact"
layout = "default"
[renderForm contactForm]
formCode = "contact-form"
==
{% ajaxPartial "contact" %}
/themes/demo/partials/contact.htm
{% component 'contactForm' %}
Important note: The form handler works only inside
{% ajaxPartial %}, not inside a plain{% partial %}.
Install the Spam Protection Plugin to protect every Form Builder form with a honeypot, content rules, a single-use form token and a per-visitor rate limit. It works out of the box.
A submission identical to one accepted within the last minute is answered with the success message but is neither logged nor mailed again, so a double click or a page refresh after sending does not produce duplicates.
The plugin generates the form template while the Custom Template field is empty. To replace that markup, write your
own template there and render each field with the form_field() function, which takes the field name.
Example that will display two fields in one row:
<div class="row">
<div class="col-6">{{ form_field('first_name') }}</div>
<div class="col-6">{{ form_field('last_name') }}</div>
</div>
Turn on Floating labels in the form's Options tab to render Bootstrap floating labels. The theme must use Bootstrap 5.
The default markup of every field type uses Bootstrap 5 form classes. On a theme with another CSS framework, or none, change the HTML markup of each field type under Form Builder → Field types. The recommended approach is to duplicate the field type and modify the copy.
Create a field type under Form Builder → Field types with the New field type button. For example, an Email
field type is the markup of Text with the input type changed to email. Once saved, it can be used in any form.
In markup section you can use Twig and following variables:
| Property | Type | Description |
|---|---|---|
| label | String | Label for the field. |
| field_id | String | Unique field ID useful when pairing labels with inputs. |
| required | Bool | Whether the validation rules include required or accepted. |
| label_class | String | Label CSS classes. |
| name | String | HTML name attribute. Also used in mail template. |
| default | String | Default value for the field. |
| comment | String | Help block for the field. |
| class | String | HTML class. |
| wrapper_class | String | HTML wrapper class. |
| placeholder | String | Placeholder for the field. |
| options | Array | Options for dropdown, radio list, checkbox list. |
| custom_attributes | String | Custom HTML attributes. For example id="my-field". |
The default field types link labels, help text and validation errors to the field, mark fields with a required or
accepted rule as required, and group checkbox and radio lists in a fieldset. Add autocomplete through Custom
attributes on fields that collect personal data, for example autocomplete="email".
| Field type | Renders |
|---|---|
| Text | a single-line text input |
| Textarea | a multi-line text box |
| E-mail, Phone number, URL, Numeric | an email, tel, url or number input |
| Date, Time, Datetime | a date, time or datetime-local input |
| Color Picker | a color input |
| Dropdown | a dropdown with the given options |
| Checkbox | a single checkbox |
| Checkbox List | a list of checkboxes |
| Radio List | a list of radio options, where only one can be selected |
| Hidden | a hidden input |
| Section | a heading and subheading for grouping fields |
| Submit | the submit button |
| reCaptcha, File upload, Country select, State select | see below |
Renders Google reCAPTCHA, either v2 (checkbox) or v3 (invisible and score-based, no user interaction).
Create the keys on the reCAPTCHA site — v2 and v3 keys are not interchangeable — and enter them under Settings → Form Builder → Google reCAPTCHA:
- Version — reCAPTCHA v2 (Checkbox) or reCAPTCHA v3 (Invisible).
- Site Key and Secret Key — must match the selected version.
- Score Threshold (v3 only) — minimum score from 0.0 (likely bot) to 1.0 (likely human) needed to pass. Default is 0.5.
- Language — language of the widget.
- Theme — light or dark v2 checkbox widget.
Important note: This field must have g-recaptcha-response as field name and required|recaptcha in validation section to work properly.
Renders a file input.
To limit the file picker, add an accept custom attribute, for example accept=".pdf,.doc" for PDF and Word files or
accept="image/*" for images.
Add the rules in the field's validation section:
required— a file must be chosen,max:512— at most 512 KB,mimes:pdf— PDF files only,image— images only.
See the available validation rules for more.
To accept more than one file, check Allow multiple files in the Upload Options tab. Then check Nested array
based form input next to each rule so it applies to every uploaded file, except the required rule.
Uploaded files are attached to the mail by default. Uncheck the option to send the mail without them.
Tells the backend how to show the uploaded files in a form submission. Choose image when only images are allowed.
Renders a dropdown with country options.
Important note: You must install Location Plugin to use this field.
Renders a dropdown with state options. This field depends on country select.
Important note: You must install Location Plugin to use this field.
Every submitted field is available in the mail template under its name. For a field named name:
{{ name }}
The value is already processed by Form Builder: dropdowns and radio lists return the label of the selected option,
checkbox lists the selected labels separated by commas, a checkbox Yes or No, and country and state selects the
name. The value exactly as the browser sent it is available with the _raw suffix:
{{ name_raw }}
Every submission is stored under Form Builder → Form submissions with the submitted values, the uploaded files, the sender IP address and a preview of the sent e-mail. The autoresponder is stored as a separate submission, marked with the Autoresponder column and filter. Turn logging off per form in the Options tab; a form without a mail template always logs, because the submission would otherwise be lost.
Submissions are pruned by a daily scheduled job after Prune period in days from Settings → Form Builder.
It only runs if October's scheduler is running (php artisan schedule:run every minute). Leave the period empty to
keep submissions forever.
Submissions can be exported to CSV or JSON from the toolbar.
Plugin settings are available at Settings → Form Builder.
- reCAPTCHA version, Site key, Secret key, Score threshold, Language, Theme — see the reCaptcha field type above. The pre-filled demo keys work with v2 only.
- Prune period in days — how long submissions are kept. Default:
30.
| Permission | Grants |
|---|---|
| Manage Forms | the Forms list; create, update, delete and import/export have their own permission each |
| Manage field types | the Field types list; create, update, delete and import/export have their own permission each. Update also covers restoring the default markup |
| Manage form submissions | the Form submissions list; preview, delete, truncate and export have their own permission each |
| Manage Settings | the plugin settings page |
Every backend action checks its permission on the server, so a user without it gets a 403 even when the button is reached by hand.
| Event | Fired when | Payload |
|---|---|---|
formBuilder.overrideForm |
before the form markup is rendered | &$form — replace or change the model |
formBuilder.overrideField |
before each field is rendered | &$field, $form |
formBuilder.formSubmitted |
the submission passed validation | &$form |
formBuilder.extendFormData |
before the mail data is built; return the array to replace it | $data |
formBuilder.beforeSendMessage |
before the mail is sent; return false to cancel it |
$form, $data |
Listen in your plugin's boot() method:
Event::listen('formBuilder.overrideForm', function ($form) {
$form->css_class = 'form-horizontal';
});
Event::listen('formBuilder.overrideField', function ($field, $form) {
if ($field->name === 'currency') {
$field->default = 'USD';
}
});
Event::listen('formBuilder.extendFormData', function ($data) {
$data['foo'] = 'bar';
return $data;
});
Event::listen('formBuilder.beforeSendMessage', function ($form, $data) {
$form->from_email = '[email protected]';
$form->from_name = 'John Doe';
});