INTEGRITY Dokumentace

Vložení widgetu

Jak přidat widget Turnstile na webovou stránku pomocí implicitního nebo explicitního vykreslení.

Turnstile nabízí dva způsoby, jak widget přidat na stránku. Implicitní vykreslování automaticky prohledá vaše HTML a najde kontejnery widgetů, jakmile se stránka načte. Explicitní vykreslování vám dává programovou kontrolu nad tím, kdy widget v JavaScriptu vytvoříte. Implicitní vykreslování použijte u statických stránek, kde formuláře existují už při načtení. Explicitní vykreslování použijte u dynamického obsahu a jednostránkových aplikací (SPA), kde formuláře vznikají až po prvotním načtení stránky.

Funkce Implicitní vykreslování Explicitní vykreslování
Snadnost nastavení Jednoduchý, minimální kód Vyžaduje další JavaScript
Kontrola nad načasováním Vykreslí se automaticky při načtení stránky Plná kontrola nad načasováním vykreslení
Případy použití Statický obsah Dynamický nebo interaktivní obsah
Přizpůsobení Omezeno na atributy HTML Rozsáhlé možnosti přes JavaScript API

Předpoklady

Než začnete, budete potřebovat:

Postup

  1. Načtení stránky: skript Turnstile se načte a vyhledá příslušné prvky, případně čeká na programové volání.
  2. Vykreslení widgetu: widgety se vytvoří a začnou spouštět výzvy.
  3. Generování tokenu: po dokončení výzvy se vygeneruje token.
  4. Integrace do formuláře: token se předává přes callbacky nebo skrytá pole formuláře.
  5. Ověření na serveru: váš server token převezme a ověří jej přes Siteverify API.

Implicitní vykreslování

Implicitní vykreslování automaticky prohledá vaše HTML a najde prvky s cf-turnstile a vykreslí widgety bez dalšího JavaScriptového kódu. Toto nastavení je ideální pro statické stránky, kde má být widget načtený hned se stránkou.

Případy použití

Cloudflare doporučuje použít implicitní vykreslování v těchto případech:

Implementace

1. Přidejte skript Turnstile

Vložení skriptu Turnstile: Přidejte JavaScriptové API Turnstile do souboru HTML uvnitř prvku <head> nebo těsně před uzavírací </body> .

<script
	src="https://challenges.cloudflare.com/turnstile/v0/api.js"
	async
	defer
></script>

2. (Volitelné) Optimalizujte výkon pomocí resource hints

Přidejte resource hints, které naváží spojení se servery Cloudflare s předstihem a zrychlí načítání. Umístěte tento <link> ve svém HTML <head> před skript Turnstile.

<link rel="preconnect" href="https://challenges.cloudflare.com" />

3. Přidejte prvky widgetu

Na místa, kde se mají výzvy na webu zobrazit, vložte kontejnery widgetu.

<div class="cf-turnstile" data-sitekey="<YOUR-SITE-KEY>"></div>

4. Nastavte pomocí datových atributů

Přizpůsobení widgetů pomocí datových atributů. Vložte div element tam, kam chcete widget umístit.

<div
	class="cf-turnstile"
	data-sitekey="<YOUR-SITE-KEY>"
	data-theme="light"
	data-size="normal"
	data-callback="onSuccess"
></div>

Po vyřešení výzvy se do success callbacku předá token. Ten je nutné ověřit proti našemu Endpoint Siteverify.

Kompletní příklady implicitního vykreslování podle scénářů

Základní přihlašovací formulář

Turnstile se často používá k ochraně formulářů na webech, například přihlašovacích nebo kontaktních. Widget vložíte přímo do svého <form> .

Příklad
<!DOCTYPE html>
<html>
<head>
    <title>Login Form</title>
    <script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>
</head>
<body>
    <form action="/login" method="POST">
        <input type="text" name="username" placeholder="Username" autocomplete="username" required />
        <input type="password" name="password" placeholder="Password" autocomplete="current-password" required />

        <!-- Turnstile widget with basic configuration -->
        <div class="cf-turnstile" data-sitekey="<YOUR-SITE-KEY>"></div>
        <button type="submit">Log in</button>
    </form>

</body>
</html>

Neviditelný input s názvem cf-turnstile-response se přidá a odešle se na server spolu s ostatními poli.

Kompletní příklad v HTML
<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8" />
		<title>Implicit Rendering with Cloudflare Turnstile</title>
		<script
			src="https://challenges.cloudflare.com/turnstile/v0/api.js"
			async
			defer
		></script>
	</head>
	<body>
		<h1>Contact Us</h1>
		<form action="/submit" method="POST">
			<label for="name">Name:</label><br />
			<input type="text" id="name" name="name" required /><br />
			<label for="email">Email:</label><br />
			<input type="email" id="email" name="email" required /><br />
			<!-- Turnstile Widget -->
			<div class="cf-turnstile" data-sitekey="<YOUR-SITE-KEY>"></div>
			<br />
			<button type="submit">Submit</button>
		</form>
	</body>
</html>

Pokročilý formulář s callbacky

Příklad
<form action="/contact" method="POST" id="contact-form">
	<input type="email" name="email" placeholder="Email" required />
	<textarea name="message" placeholder="Message" required></textarea>
	<!-- Widget with callbacks and custom configuration -->
	<div
		class="cf-turnstile"
		data-sitekey="<YOUR-SITE-KEY>"
		data-theme="auto"
		data-size="flexible"
		data-callback="onTurnstileSuccess"
		data-error-callback="onTurnstileError"
		data-expired-callback="onTurnstileExpired"
	></div>
	<button type="submit" id="submit-btn" disabled>Send Message</button>
</form>

<script>
	function onTurnstileSuccess(token) {
		console.log("Turnstile success:", token);
		document.getElementById("submit-btn").disabled = false;
	}
	function onTurnstileError(errorCode) {
		console.error("Turnstile error:", errorCode);
		document.getElementById("submit-btn").disabled = true;
	}
	function onTurnstileExpired() {
		console.warn("Turnstile token expired");
		document.getElementById("submit-btn").disabled = true;
	}
</script>

Více widgetů s odlišnou konfigurací

Příklad
<!-- Compact widget for newsletter signup -->
<form action="/newsletter" method="POST">
	<input type="email" name="email" placeholder="Email" />
	<div
		class="cf-turnstile"
		data-sitekey="<YOUR-SITE-KEY>"
		data-size="compact"
		data-action="newsletter"
	></div>
	<button type="submit">Subscribe</button>
</form>

<!-- Normal widget for contact form -->
<form action="/contact" method="POST">
	<input type="text" name="name" placeholder="Name" />
	<input type="email" name="email" placeholder="Email" />
	<textarea name="message" placeholder="Message"></textarea>
	<div
		class="cf-turnstile"
		data-sitekey="<YOUR-SITE-KEY>"
		data-action="contact"
		data-theme="dark"
	></div>
	<button type="submit">Send</button>
</form>

Automatická integrace s formulářem

Když widget Turnstile vložíte do <form> elementu neviditelné vstupní pole s názvem cf-turnstile-response se vytvoří automaticky. Obsahuje ověřovací token a odesílá se společně s ostatními daty formuláře.

<form action="/submit" method="POST">
	<input type="text" name="data" />
	<div class="cf-turnstile" data-sitekey="<YOUR-SITE-KEY>"></div>
	<!-- Hidden field automatically added: -->
	<!-- <input type="hidden" name="cf-turnstile-response" value="TOKEN_VALUE" /> -->
	<button type="submit">Submit</button>
</form>

Explicitní vykreslování

Explicitní vykreslování vám dává programovou kontrolu nad tím, kdy a kde se widget zobrazí a jak se widgety vytvářejí pomocí funkcí JavaScriptu. Tento postup se hodí pro dynamický obsah, jednostránkové aplikace (SPA) nebo podmíněné vykreslování podle akcí uživatele.

Případy použití

Cloudflare doporučuje použít explicitní vykreslování v těchto případech:

Implementace

1. Přidejte skript na web s explicitním vykreslováním

<script
	src="https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit"
	defer
></script>

2. Vytvořte kontejnerové prvky

Vytvořte kontejnery bez cf-turnstile třídu.

<div id="turnstile-container"></div>

3. Vykreslete widgety programově

Zavolejte turnstile.render() až budete připraveni widget vytvořit.

const widgetId = turnstile.render("#turnstile-container", {
	sitekey: "<YOUR-SITE-KEY>",
	callback: function (token) {
		console.log("Success:", token);
	},
});

Volitelná volání

Po explicitním vykreslení widgetu Turnstile s ním podle potřeb vaší aplikace obvykle dále pracujete. Jak spravovat stav widgetu, popisují následující části.

Resetování widgetu

Pokud danému widgetu vypršel časový limit nebo platnost, resetujete ho touto funkcí:

turnstile.reset(widgetId);

Získání response tokenu

Aktuální token odpovědi můžete kdykoli získat:

const responseToken = turnstile.getResponse(widgetId);

Odstranění widgetu

Jakmile už widget není potřeba, můžete ho ze stránky odstranit pomocí:

turnstile.remove(widgetId);

Nezavolá se žádný callback a odstraní se všechny související prvky DOM.

Kompletní příklady explicitního vykreslování podle scénářů

Základní explicitní implementace

Příklad
<!DOCTYPE html>
<html>
	<head>
		<title>Explicit Rendering</title>
		<script
			src="https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit"
			defer
		></script>
	</head>
	<body>
		<form id="login-form">
			<input
				type="text"
				name="username"
				placeholder="Username"
				autocomplete="username"
			/>
			<input
				type="password"
				name="password"
				placeholder="Password"
				autocomplete="current-password"
			/>
			<div id="turnstile-widget"></div>
			<button type="submit">Login</button>
		</form>

		<script>
			window.onload = function () {
				turnstile.render("#turnstile-widget", {
					sitekey: "<YOUR-SITE-KEY>",
					callback: function (token) {
						console.log("Turnstile token:", token);
						// Handle successful verification
					},
					"error-callback": function (errorCode) {
						console.error("Turnstile error:", errorCode);
					},
				});
			};
		</script>
	</body>
</html>

Použití callbacku onload

Příklad
<script
	src="https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit&onload=onTurnstileLoad"
	defer
></script>
<div id="widget-container"></div>
<script>
	function onTurnstileLoad() {
		turnstile.render("#widget-container", {
			sitekey: "<YOUR-SITE-KEY>",
			theme: "light",
			callback: function (token) {
				console.log("Challenge completed:", token);
			},
		});
	}
</script>

Pokročilá implementace v SPA

Příklad
<div id="dynamic-form-container"></div>

<script src="https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit"></script>

<script>
	class TurnstileManager {
		constructor() {
			this.widgets = new Map();
		}
		createWidget(containerId, config) {
			// Wait for Turnstile to be ready
			turnstile.ready(() => {
				const widgetId = turnstile.render(containerId, {
					sitekey: config.sitekey,
					theme: config.theme || "auto",
					size: config.size || "normal",
					callback: (token) => {
						console.log(`Widget ${widgetId} completed:`, token);
						if (config.onSuccess) config.onSuccess(token, widgetId);
					},
					"error-callback": (error) => {
						console.error(`Widget ${widgetId} error:`, error);
						if (config.onError) config.onError(error, widgetId);
					},
				});

				this.widgets.set(containerId, widgetId);
				return widgetId;
			});
		}
		removeWidget(containerId) {
			const widgetId = this.widgets.get(containerId);
			if (widgetId) {
				turnstile.remove(widgetId);
				this.widgets.delete(containerId);
			}
		}
		resetWidget(containerId) {
			const widgetId = this.widgets.get(containerId);
			if (widgetId) {
				turnstile.reset(widgetId);
			}
		}
	}

	// Usage
	const manager = new TurnstileManager();

	// Create a widget when user clicks a button
	document.getElementById("show-form-btn").addEventListener("click", () => {
		document.getElementById("dynamic-form-container").innerHTML = `
        <form>
            <input type="email" placeholder="Email" />
            <div id="turnstile-widget"></div>
            <button type="submit">Submit</button>
        </form>
    `;
		manager.createWidget("#turnstile-widget", {
			sitekey: "<YOUR-SITE-KEY>",
			theme: "dark",
			onSuccess: (token) => {
				// Handle successful verification
				console.log("Form ready for submission");
			},
		});
	});
</script>

Správa životního cyklu widgetu

Explicitní vykreslování dává plnou kontrolu nad životním cyklem widgetu.

// Render a widget
const widgetId = turnstile.render("#container", {
	sitekey: "<YOUR-SITE-KEY>",
	callback: handleSuccess,
});

// Get the current token
const token = turnstile.getResponse(widgetId);

// Check if widget is expired
const isExpired = turnstile.isExpired(widgetId);

// Reset the widget (clears current state)
turnstile.reset(widgetId);

// Remove the widget completely
turnstile.remove(widgetId);

Režim spouštění

Pomocí režimů spuštění určete, kdy se výzvy spouštějí.

// Render widget but don't run challenge yet
const widgetId = turnstile.render("#container", {
	sitekey: "<YOUR-SITE-KEY>",
	execution: "execute", // Don't auto-execute
});

// Later, run the challenge when needed
turnstile.execute("#container");

Optimalizace výkonu a uživatelského prožitku

Cloudflare doporučuje spustit skript Turnstile co nejdříve po vstupu návštěvníka na stránku, aby ověření stihlo doběhnout a interakce byla připravená ve chvíli, kdy návštěvník na stránce něco udělá.


Možnosti konfigurace

Implicitní i explicitní způsob vykreslení podporuje stejné možnosti konfigurace. Nejčastěji používané najdete v tabulce níže.

Možnost Popis Hodnoty
sitekey Sitekey vašeho widgetu Povinný řetězec
theme Vizuální motiv auto, light, dark
size Velikost widgetu normal, flexible, compact
callback Callback při úspěchu Funkce
error-callback Callback při chybě Funkce
execution Kdy spustit výzvu render, execute
appearance Kdy je widget viditelný always, execute, interaction-only

Úplný seznam možností konfigurace najdete v Konfigurace widgetů.


Testování

Pomocí testovacího sitekey si widget Turnstile na své stránce vyzkoušíte, aniž by se spustil skutečný Cloudflare Challenge.

Viz Testování s dalšími informacemi.


Omezení

Turnstile funguje pouze na stránkách, které používají http:// nebo https:// schémata URI. Ostatní protokoly, například file://, nejsou pro vložení widgetu podporovány.


Bezpečnostní požadavky