Content IntegrationsNew in 5.18.2+
Embed forms in editors, link fields, menus, and content blocks. These integrations require Craft 5 and do not support Craft 4. Freeform's Craft field type requires Lite or Pro. Other plugins may have their own edition requirements.
Content Integrations settings
Open Freeform → Settings → Content Integrations to enable or disable the CKEditor, Vizy, Navigation, Craft Link, Hyper, and Linkit integrations. Supported integrations are enabled by default. Turning one off hides its form insertion controls without affecting saved selections or frontend rendering.
Use Integration Icon to choose a Craft icon for the toolbar controls and form pickers, or keep the Freeform logo.
Supported plugins and content types
| Integration | Supported versions | Form selection | Rendering |
|---|---|---|---|
| Craft Link | Built into Craft 5.3+ | Freeform Form link type | craft.freeform.formFromLink() |
| Hyper | 2.x and 3.x | Freeform Form link type | formFromLink() or link.form |
| Linkit | 5.x | Freeform Form link type | formFromLink() or link.form |
| CKEditor | 5.9+ | Freeform Form toolbar button | craft.freeform.renderContent(entry.body) |
| Vizy | 4.x | Freeform Form node | entry.body.render() |
| Vizy content blocks | 3.x and 4.x | Freeform Craft field in a block type | freeform-integrations/vizy partial |
| Navigation | 3.x and 4.x | Freeform Form node type | formFromLink() in a custom menu template |
| Matrix | Built into Craft 5 | Freeform Craft field in a nested entry type | freeform-integrations/_form partial |
| Neo | 5.x | Freeform Craft field in a block type | freeform-integrations/_form partial |
| Content Block | Built into Craft 5.8+ | Freeform Craft field in its field layout | freeform-integrations/_form partial |
The freeform-integrations template partials are included with Freeform. You do
not need to copy them into your project. They create a separate form instance
for each embed and render nothing for empty, archived, or deleted selections.
Forms use their own formatting templates, so load the required CSS in your site
layout.
Matrix, Neo, and Content Block fields
These containers use the Freeform Form Craft field and do not need a toggle on the Content Integrations settings page.
Set up the field
Create a Freeform Form field, for example selectedForm. Use Available
Forms to choose which forms authors can select.
Add the field to the appropriate layout:
- Matrix: a nested entry type allowed by the Matrix field.
- Neo: a Neo block type.
- Content Block: the Content Block field's own field layout.
Add the container field to your entry layout. Authors can then select a form inside it.
Render the selection
For a Matrix or Neo field named pageBlocks with a form entry or block type:
{% for block in entry.pageBlocks.all() %}
{% if block.type.handle == 'form' %}
{% include 'freeform-integrations/_form' with {
selectedForm: block.selectedForm,
instanceId: 'block-' ~ entry.id ~ '-' ~ block.id,
renderProperties: {},
} only %}
{% endif %}
{% endfor %}
For a Content Block field named formBlock:
{% include 'freeform-integrations/_form' with {
selectedForm: entry.formBlock.selectedForm,
instanceId: 'content-block-' ~ entry.id,
renderProperties: {},
} only %}
Give each occurrence a unique instanceId if you render the same block more than
once on a page. Use renderProperties for Freeform render options, such as a
formatting template override.
Native editor controls
Both editors show a non-interactive form preview. Your site renders the actual form using the examples below.
CKEditor 5.9+
Add Freeform Form (freeformForm) to the CKEditor field's toolbar. Authors
can use the button to insert a form or change the form in a selected block.
Render the field with Freeform's helper:
{{ craft.freeform.renderContent(entry.body) }}
To override the formatting template for embedded forms:
{{ craft.freeform.renderContent(entry.body, {
formattingTemplate: 'bootstrap-5/index.twig'
}) }}
Use this helper instead of {{ entry.body }}, which leaves form placeholders
empty. Keep the Freeform toolbar control enabled when editing fields containing
these blocks.
Vizy 4
Enable the Freeform Form node in the field's Editor Config and add its control to the toolbar. Authors can insert a form or select an existing node to change its form. No custom block type or Craft field is needed.
Render the field normally:
{{ entry.body.render() }}
Existing nested entries and content blocks remain supported. They are not converted to native editor blocks automatically.
Optional CKEditor nested-entry recipe
To use CKEditor's nested entries instead of the toolbar integration:
Create a Freeform Form Craft field with the handle freeformForm. Choose
which forms authors can select in its settings.
Create an entry type named Freeform Form, with the handle freeformForm, and
add the field to its layout. If authors do not need a title, disable the title
field and set the title format to Form.
Allow that entry type in your CKEditor field and add the + toolbar menu.
Create templates/_partials/entry/freeformForm.twig:
{% include 'freeform-integrations/ckeditor' %}
In an entry, use + → Freeform Form, select a form, and save. Render the
CKEditor field normally with {{ entry.body }}.
If your entry type has a different handle, use it as the partial's filename. For a different field handle or render options:
{% include 'freeform-integrations/ckeditor' with {
freeformFieldHandle: 'contactForm',
renderProperties: {formattingTemplate: 'bootstrap-5/index.twig'},
} %}
Vizy content blocks (3.x and 4.x)
To embed forms in Vizy content blocks:
Create a Freeform Form Craft field with the handle freeformForm.
Create a Freeform Form Vizy block type and add the field to its layout. In Vizy 3, create the block type in your Vizy field. In Vizy 4, create it under Settings → Vizy → Block Types, then allow it in the field's Block Configuration.
Set the block type's Template to freeform-integrations/vizy.
Insert the block, choose a form, and save the entry. Render the Vizy field with
{{ entry.body.render() }}.
For a different field handle or render options, assign your own wrapper template to the block type:
{% include 'freeform-integrations/vizy' with {
freeformFieldHandle: 'contactForm',
renderProperties: {formattingTemplate: 'bootstrap-5/index.twig'},
} %}
Navigation (3.x and 4.x)
Allow Freeform Form nodes in your menu, then add one and choose a form.
Enter a title. In Navigation 4, you can leave it blank to use the form name.
Forms do not have a public URL. Use formFromLink() in a custom navigation
template to decide how they appear in your menu:
{% set nodes = craft.navigation.nodes('mainMenu').all() %}
<ul>
{% nav node in nodes %}
<li>
{% set form = craft.freeform.formFromLink(node) %}
{% if form %}
{% include 'freeform-integrations/navigation' %}
{% elseif node.url %}
{{ node.link }}
{% else %}
<span>{{ node.title }}</span>
{% endif %}
{% ifchildren %}<ul>{% children %}</ul>{% endifchildren %}
</li>
{% endnav %}
</ul>
The included partial displays the form in a <details> disclosure. You can
instead use your own markup to show it inline or in a modal. Navigation's
automatic menu renderer does not handle form display.
Form Links
Set up a link field
Under Settings → Fields, create or edit a Link, Hyper, or Linkit field.
Enable Freeform Form in the field's link types:
- Craft Link: select it under Allowed Link Types.
- Hyper: enable it in the field's link types. In Hyper 3, edit the field's Custom settings or its shared Link Type Config.
- Linkit: enable it in the link type settings.
Use Available Forms in the Freeform Form type's settings to offer all forms or limit the choices.
Save the field and add it to your element's field layout.
Edit the entry or other element, choose Freeform Form as the link type, select a form, and save.
Render the selected form
For Craft Link and Linkit, pass the complete field value to
formFromLink():
{% set form = craft.freeform.formFromLink(entry.myLinkField) %}
{% if form %}
{{ form.render() }}
{% endif %}
For Craft Link, its value property is a URL, not a form ID. Pass the field value
directly to the helper. To link to a page containing a form, choose an Entry
link to that page instead.
Hyper fields
Hyper returns a collection, even for a single-link field. Pass one link to the
helper. Twig's first filter works with both Hyper 2 and Hyper 3:
{% set link = entry.myHyperField|first %}
{% set form = craft.freeform.formFromLink(link) %}
{% if form %}
{{ form.render() }}
{% endif %}
Hyper and Linkit also expose the selected form as link.form.
Render options and unavailable forms
You can pass render options to the helper:
{% set form = craft.freeform.formFromLink(link, {id: 'footer-contact-form'}) %}
The helper returns null for empty selections, unrelated link types, and deleted
or archived forms. Always check the result before rendering.
Pickers show the current site's forms and exclude archived forms. The permission setting can also limit choices to forms the author can manage. Saved selections that are no longer available appear as Unavailable form. Choose another form or clear the selection before saving.
Selections are stored in the field's content, not as Craft element relations. They do not appear in Usage in Elements, which tracks the standalone Freeform Form field.