Easily integrate Turnstile to validate your forms.
Turnstile is Cloudflare's free, privacy-first, smart CAPTCHA replacement. It automatically chooses from a rotating suite of non-intrusive browser challenges based on telemetry and client behavior exhibited during a session.
The plugin support Sprig requests out of the box.
If you want to know more about Turnstile, read the announcement blog post or the official documentation.
This plugin requires Craft CMS 4.3.5 or later, and PHP 8.0.2 or later.
You can install this plugin from the Plugin Store or with Composer.
Go to the Plugin Store in your project’s Control Panel and search for “Turnstile”. Then press “Install”.
Open your terminal and run the following commands:
# go to the project directory
cd /path/to/my-project.test
# tell Composer to load the plugin
composer require billmn/craft-turnstile
# tell Craft to install the plugin
./craft plugin/install turnstile
Insert site and secret keys in the plugin settings page, .env
variables are supported.
You can create a turnstile.php
file in the config folder of your project to override the settings specified in control panel:
<?php
return [
'siteKey' => '',
'secretKey' => '',
];
In your template add the following code inside the form
tag to render the widget:
{{ craft.turnstile.widget() }}
The widget
method accept optional parameters in which you can provide HTML attributes to configure Turnstile.
A list of supported configurations is available on Turnstile's docs.
Here an example that provide the element ID attribute and set widget's theme and size:
{{ craft.turnstile.widget({
id: 'contact-form',
'data-size': 'compact',
'data-theme': 'dark',
}) }}
{# or if you prefer #}
{{ craft.turnstile.widget({
id: 'contact-form',
data: {
size: 'compact',
theme: 'dark',
}
}) }}
If you don't specify the ID, a random one will be created.
To validate the Turnstile response, you can use one of this methods:
Turnstile::getInstance()->validator->verify(); // returns `true` if passes
Turnstile::getInstance()->validator->passes();
Turnstile::getInstance()->validator->fails();
This is an example on how to flag the message as spam using Contact Form. Add the following code in your project module:
use billmn\turnstile\Turnstile;
use craft\contactform\events\SendEvent;
use craft\contactform\Mailer;
use yii\base\Event;
Event::on(
Mailer::class,
Mailer::EVENT_BEFORE_SEND,
function(SendEvent $e) {
$e->isSpam = Turnstile::getInstance()->validator->fails();
}
);
If you use the response-field-name
configuration, you can validate the submission by specifying the field name:
{{ craft.turnstile.widget({
'data-response-field-name': 'custom-field',
}) }}
Turnstile::getInstance()->validator->fails('custom-field');
You can also verify Turnstile if you are using Craft's built-in controller action save-user
(by using {{ actionInput('users/save-user') }}
or <input type="hidden" name="action" value="users/save-user">
). This behavior is turned off by default, but can be enabled on the plugin settings page or by setting validateUserRegistrations
to true
in the optional config file.
You can customize the behavior of the widget using the config
array.
Option | Default | Description |
---|---|---|
registerJs |
true |
Automatically register scripts |
scriptAttr |
{} |
Script tag HTML attributes |
Like this:
{{ craft.turnstile.widget({
config: {
scriptAttr: {
nonce: 'nonce'
}
}
}) }}
Method | Description |
---|---|
widget |
Render the widget |
siteKey |
Returns Turnstile's site key |
scriptUrl |
Returns Turnstile's script url |
initScript |
Returns initialization script |
For example:
{{ craft.turnstile.widget({
config: {
registerJs: false,
}
}) }}
<script src="{{ craft.turnstile.scriptUrl }}"></script>
<script>
{{ craft.turnstile.initScript|raw }}
</script>