Proteggere i tuoi moduli con Cloudflare Turnstile
Cloudflare Turnstile è un’alternativa moderna e orientata alla privacy ai CAPTCHA. Offre il rilevamento dei bot senza attriti, senza challenge per l’utente, migliorando sia l’accessibilità sia la sicurezza del modulo.
Formspree supporta Turnstile out of the box: basta configurare le tue chiavi e abilitare il CAPTCHA nelle impostazioni del modulo.
Passaggio 1: Creare un sito Turnstile
Inizia visitando la dashboard di Cloudflare Turnstile.
Fai clic su Add widget per creare un nuovo sito Turnstile, poi:

- Inserisci un nome per il tuo sito.
- Aggiungi il tuo dominio (es.
example.com) sotto Allowed Domains. Usa localhost per scopi di sviluppo. - Scegli la modalità widget

Salva la configurazione. Una volta creato, vedrai le tue nuove chiavi del Widget

Copia questa Site Key e Secret Key: le userai nel tuo modulo HTML e nella configurazione di Formspree.
Passaggio 2: Configurare il CAPTCHA in Formspree
Vai alla pagina delle impostazioni del tuo modulo nella Formspree Dashboard.
Nella sezione CAPTCHA, assicurati che la protezione CAPTCHA sia abilitata.
Fai clic su Adjust settings, seleziona Cloudflare Turnstile e incolla la tua Secret Key nel campo fornito.

Salva le modifiche.
Passaggio 3: Aggiungere Turnstile all’HTML del tuo modulo
Ora è il momento di aggiungere Turnstile al tuo modulo. Includi lo script Turnstile e la tua Site Key nel tuo codice HTML.
Ecco un esempio di base:
<html>
<head>
<title>Turnstile Demo</title>
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>
</head>
<body>
<form action="https://formspree.io/f/{your-form-id}" method="POST">
<input type="email" name="email" placeholder="Email" required />
<div class="cf-turnstile" data-sitekey="{your-site-key}"></div>
<br />
<input type="submit" value="Submit" />
</form>
</body>
</html>
Quando un utente invia il modulo, il widget Turnstile genera automaticamente un token (cf-turnstile-response) che viene verificato da Formspree usando la tua Secret Key.
Usando AJAX (Opzionale)
Se invii il tuo modulo tramite AJAX, puoi includere manualmente il token Turnstile nella tua richiesta.
Di seguito un esempio usando Vanilla JS:
<!DOCTYPE html>
<html>
<head>
<title>Turnstile AJAX Demo</title>
<!-- Turnstile script -->
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>
</head>
<body>
<form id="form" method="POST" action="https://formspree.io/f/<form-hashid>">
<input type="email" name="email" placeholder="email@example.com" required />
<!-- Turnstile widget (automatically adds hidden cf-turnstile-response input) -->
<div class="cf-turnstile" data-sitekey="{site-key}"></div>
<br />
<button type="submit">Submit</button>
</form>
<script>
const form = document.getElementById("form");
form.addEventListener("submit", function (event) {
event.preventDefault();
// Grab all form fields, including the hidden cf-turnstile-response
const data = new FormData(form);
fetch(form.action, {
method: form.method,
body: data,
headers: {
"Accept": "application/json"
}
})
.then(function (response) {
return response.json();
})
.then(function (data) {
console.log("Formspree response:", data);
})
.catch(function (error) {
console.error("Error:", error);
});
});
</script>
</body>
</html>
Oppure usando l’API Turnstile
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<script
src="https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit"
defer
></script>
</head>
<body>
<form id="contact-form">
<input type="email" name="email" placeholder="Email" required />
<div id="turnstile-container"></div>
<button type="submit">Send</button>
</form>
<script>
let widgetId = null;
// Render widget when the page finishes loading
window.onload = function () {
if (!window.turnstile) {
console.error("Turnstile did not load.");
return;
}
widgetId = window.turnstile.render("#turnstile-container", {
sitekey: "{your-site-key}",
callback: function (token) {
console.log("Turnstile success:", token);
}
});
};
// AJAX submit
document.getElementById("contact-form").addEventListener("submit", function (event) {
event.preventDefault();
const form = this;
const formData = new FormData(form);
// Ensure we send the token under the standard field name
// If Turnstile already added a hidden input, this overwrites it.
formData.set("cf-turnstile-response", token);
fetch("/submit", {
method: "POST",
body: formData
})
.then((res) => {
if (!res.ok) {
throw new Error("Server error: " + res.status);
}
return res.text();
})
.then((text) => {
alert("Server replied: " + text);
// Reset for next submission
window.turnstile.reset(widgetId);
form.reset();
})
.catch((err) => {
console.error(err);
alert("Request failed: " + err.message);
});
});
</script>
</body>
</html>