The Solspace team is expanding! If you love Craft CMS and you’re looking for an exciting full-time remote position working on software development for the Freeform and Calendar plugins for Craft and more, we’d love to hear from you!

Check Out Job Listing!

Cacheable Forms

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.

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.

  1. Create a Twig template with the following line of code:
    {{ craft.app.request.csrfToken }}
  2. Make sure routing to that template works correctly. For example, we often dedicate a directory named something like dynamic on our websites and place files in that directory that we know should never be cached by the CDN. The above template might be in a directory called dynamic with a filename of index.twig.
  3. Set up a rule in CloudFlare or your preferred CDN that makes sure any URLs starting with dynamic are not cached. You can then aggressively cache all of your other site URLs.
  4. Add the following JS snippet to your main .js file or to the bottom of all your web pages. Note that this snippet assumes you're already running jQuery. It uses AJAX to fetch the contents of http://yourwebsite.com/dynamic, which just returns a fresh CSRF token. This is then replaced in the CSRF token field of all forms on the page.
      if ($("input[name='{{ craft.app.config.general.csrfTokenName }}']").length > 0) {
        $(() => {
            url: "/dynamic",
            success: (response) => {
              $("input[name='{{ craft.app.config.general.csrfTokenName }}']").val(response);

That's it!

Last Updated: 1/14/2020, 3:35:55 PM