One of our forms, which had first level protection using a hidden field, occasionally got bursts of spam submissions. Added Cloudflare turnstile as an additional layer of protection.
In the <head> section of the web page which had the form,
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" defer></script>
Inside the form,
<div class="cf-turnstile" data-sitekey="0x4OUR-SITE-KEY0-"></div>
and in the done function, handling the "failed captcha" situation -
$.ajax({
method: "POST",
url: url,
data: user
}).done(function (msg) {
// When the request is successful
if(msg=="Success") {
$('span').html('<strong>Thank you for submitting your details. We will get back to you shortly, in a week or so.</strong>');
$("form").trigger("reset");
}
if(msg=="Failed captcha.") {
$('span').html('<strong>Please resubmit after the captcha loads, checking the box to confirm you are human if necessary.</strong>');
}
}).fail(function (err, textstatus, error) {
$('span').text(textstatus);
});
Then, we need to add some back-end code. Since we're using Google Apps Scripts, this looked like:
function doPost(e) {
var scriptProperties = PropertiesService.getScriptProperties();
var myKey = scriptProperties.getProperty('SECRET_KEY');
.....
const siteresponse = e.parameter['cf-turnstile-response'];
.....
var verifyurl = 'https://challenges.cloudflare.com/turnstile/v0/siteverify';
var formData = {
'secret': myKey,
'response': siteresponse
};
var options = {
'method' : 'post',
'payload' : formData
};
var responsetositeverify = UrlFetchApp.fetch(verifyurl, options);
var verifydata = JSON.parse(responsetositeverify.getContentText());
if (!verifydata.success) {
// do the rest of the processing only if verification returns success.
return ContentService.createTextOutput().append('Failed captcha.');
}