Freeform Freeform for Craft

Templating

Caching Forms Improved in 5.0+

Forms and pages can be cached in a variety of ways. Here are 2 different solutions, depending on your caching approach.

User Guide:

Quick troubleshooting the most commonly reported issues with your form's appearance, behavior, or submission of the form on the front end.

Twig Template Caching

When using simple Craft Caching, you'll need to make sure that you are refreshing the CSRF token and the Freeform form hash. Here's how that may look inside your template:

{# Initialize the form #}
{% set form = freeform.form("myFormHandle") %}

{# Cached form comes here #}
{% cache %}
    {{ form.render }}
{% endcache %}

{# Script for updating the form's Hash and CSRF token loads after #}
<script>
    // Find the corresponding Form
    var form = document.querySelector('form');

    // Locate and update the Hash input
    var formHashInput = form.querySelector('input[name=formHash]');
    formHashInput.setAttribute('value', '{{ form.hash }}');

    // Locate and update the CSRF input
    var csrfInput = form.querySelector('input[name={{ craft.app.config.general.csrfTokenName|e('js') }}]');
    csrfInput.value = '{{ craft.app.request.csrfToken|e('js') }}';
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

If using PHP Sessions or Database Tables for Freeform Session Context, be sure to include {% do form.registerContext %}:



 




{# Initialize the form #}
{% set form = freeform.form("myFormHandle") %}
{% do form.registerContext %}

{# Cached form comes here #}
...
1
2
3
4
5
6

Static Page Caching / CDN / Blitz

Services like CloudFlare allow you to cache components of web pages like JS, CSS and images. But you can also cache entire web pages; the complete HTML of a page. They then distribute these cached copies of pages across their global network of data centers. This makes websites screaming fast. The Blitz Craft plugin is another way for static page caching.

There's one problem with full page caching though. Forms stop working after a while since their CSRF tokens expire. CSRF tokens are a way of cutting down on unwanted form submissions and assure that a given form actually belongs to a given website.

You can overcome this problem of expired CSRF tokens in Craft CMS with some simple javascript and a little Twig template code.

{% set form = freeform.form(craft.app.request.get('form')) %}
{{ {
    hash: form.hash,
    payload: form.payload,
    csrf: {
        name: craft.app.config.general.csrfTokenName,
        value: craft.app.request.csrfToken,
    }
}|json_encode|raw }}
1
2
3
4
5
6
7
8
9

If using PHP Sessions or Database Tables for Freeform Session Context, be sure to include {% do form.registerContext %}:


 








{% set form = freeform.form(craft.app.request.get('form')) %}
{% do form.registerContext %}
{{ {
    hash: form.hash,
    csrf: {
        name: craft.app.config.general.csrfTokenName,
        value: craft.app.request.csrfToken,
    }
}|json_encode|raw }}
1
2
3
4
5
6
7
8
9
{# Initialize the form #}
{% set form = freeform.form("myFormHandle") %}
{{ form.render }}

{# Load the jQuery library #}
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>

{# The script for updating the form's hash, payload and CSRF token loads after #}
<script>
    $(function () {
        // Find the corresponding Form
        var form = document.querySelector('form');

        $.ajax({
            // Specify the form handle in the GET parameters
            // ! Make sure to change the `myFormHandle` to your specific form handle.
            url: '/dynamic?form=myFormHandle',
            type: 'get',
            dataType: 'json',
            success: function (response) {
                // Update the Form Hash
                form.querySelector('input[name=formHash]').value = response.hash;

                // Update the Payload if encrypted payloads are enabled
                form.querySelector('input[name=freeform_payload]').value = response.payload;

                // Locate and update the CSRF input
                var csrf = response.csrf;
                form.querySelector('input[name=' + csrf.name + ']').value = csrf.value;
            },
        });
    });
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
Finished!
User Guide:

Using a form more than once in the same template? Be sure to specify the id parameter for the Form query in your template with unique values.