Skip to content

Commit 2f6f624

Browse files
Merge pull request #3 from Laragear/feat/script-with-meta
[1.x] Adds script meta tag
2 parents a3825f8 + 07af1c1 commit 2f6f624

3 files changed

Lines changed: 111 additions & 40 deletions

File tree

README.md

Lines changed: 77 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -68,24 +68,98 @@ You can use the `<x-turnstile::script />` Blade Component to implement the Cloud
6868
</html>
6969
```
7070

71-
The script will render a `<script>` tag using `async` and `defer` by default. You can set any of these to `false`.
71+
The script will render a `<script>` tag using `async` and `defer` by default:
72+
73+
```html
74+
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" defer async></script>
75+
```
76+
77+
If you don't want to use `async` or `defer`, you can set any of these to `false`.
7278

7379
```blade
7480
<x-turnstile::script :async="false" :defer="false" />
7581
```
7682

83+
```html
84+
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js"></script>
85+
```
86+
7787
You may also set `explicit` to `true` to make widgets be rendered only explicitly by your frontend JavaScript.
7888

7989
```blade
8090
<x-turnstile::script :explicit="true" />
8191
```
8292

93+
```html
94+
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit" defer async></script>
95+
```
96+
8397
Finally, you can also set a custom callback name to be executed once the script is completely loaded in your frontend, especially if you're using explicit rendering, with the `onload` attribute.
8498

8599
```blade
86100
<x-turnstile::script :explicit="true" onload="renderAllWidgets" />
87101
```
88102

103+
```html
104+
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit&onload=renderAllWidgets" defer async></script>
105+
```
106+
107+
#### Site Key on JavaScript frontend
108+
109+
If you put the script on the `<head>` part of your HTML view, you may set the `meta` attribute to render a `<meta>` tag alongside the script. This tag will contain your Turnstile site key so your JavaScript frontend can retrieve use it to render the widget.
110+
111+
```blade
112+
<!DOCTYPE html>
113+
<html lang="en">
114+
<head>
115+
<!-- ... -->
116+
<title>My application</title>
117+
118+
<x-turnstile::script meta />
119+
</head>
120+
<body>
121+
...
122+
</body>
123+
</html>
124+
```
125+
126+
It will render the following HTML:
127+
128+
```html
129+
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" defer async></script>
130+
<meta name="turnstile-sitekey" content="1x00000000000000000000AA" />
131+
```
132+
133+
You will be able to retrieve the site key through Javascript by querying the meta tag with the `turnstile-sitekey` name.
134+
135+
```vue
136+
<script setup>
137+
import VueTurnstile from 'some-vue-turnstile library'
138+
139+
const siteKey = document.querySelector('meta[name="turnstile-sitekey"]').content;
140+
141+
const token = ref('')
142+
143+
// ...
144+
</script>
145+
146+
<template>
147+
<VueTurnstile :sitekey="siteKey" v-model="token" />
148+
149+
<!-- ... -->
150+
</template>
151+
```
152+
153+
Alternatively, you may set a custom name for the tag by setting a value to the `meta` attribute.
154+
155+
```blade
156+
<x-turnstile::script meta="my-custom-key" />
157+
```
158+
159+
```html
160+
<meta name="my-custom-key" content="1x00000000000000000000AA" />
161+
```
162+
89163
### Widget
90164

91165
> [!IMPORTANT]
@@ -127,42 +201,6 @@ You can pass HTML attributes and [data attributes](https://developers.cloudflare
127201
>
128202
> Classes are automatically appended, so you shouldn't worry about overwriting the `cf-turnstile` class used by the Widget to render.
129203
130-
### Retrieving the Site Key
131-
132-
If you're using a custom JavaScript frontend, you may require your Site Key available _somewhere_ so the frontend library can use it. You may do that by just simply using the `siteKey()` method of the `Turnstile` facade inside the `<meta>` header in your main HTML view.
133-
134-
```blade
135-
@php
136-
use Laragear\Turnstile\Facades\Turnstile;
137-
@endphp
138-
139-
<!DOCTYPE html>
140-
<html lang="en">
141-
<head>
142-
<meta charset="UTF-8">
143-
<title>My awesome app</title>
144-
<meta name="turnstile-sitekey" content="{{ Turnstile::sitekey() }}">
145-
</head>
146-
<body>
147-
// ...
148-
</body>
149-
</html>
150-
```
151-
152-
Then later you will be able to retrieve the site key through Javascript.
153-
154-
```vue
155-
<script setup>
156-
const siteKey = document.querySelector('meta[name="turnstile-sitekey"]').content;
157-
158-
// ...
159-
</script>
160-
161-
<template>
162-
<div class="cf-turnstile shadow-lg" :data-sitekey="siteKey"></div>
163-
</template>
164-
```
165-
166204
## Backend integration
167205

168206
When issuing a form, you have three alternatives to ensure the Turnstile challenge is valid and successful, from the easiest to the more flexible:
@@ -869,3 +907,5 @@ If you discover any security related issues, please [report it using the online
869907
This specific package version is licensed under the terms of the [MIT License](LICENSE.md), at time of publishing.
870908

871909
[Laravel](https://laravel.com) is a Trademark of [Taylor Otwell](https://github.com/TaylorOtwell/). Copyright © 2011-2025 Laravel LLC.
910+
911+
[Cloudflare](https://www.cloudflare.com) and Cloudflare Turnstile are trademarks of [Cloudflare, Inc](https://www.cloudflare.com/trademark/). Copyright © 2009-2025.

src/Views/Components/Script.php

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ public function __construct(
2525
public ?string $onload = null,
2626
public bool $async = true,
2727
public bool $defer = true,
28+
public string|bool $meta = false,
2829
)
2930
{
3031
//
@@ -44,10 +45,18 @@ public function render(): Closure|string
4445
return function (): string {
4546
$source = static::SOURCE . $this->query();
4647

47-
return <<<HTML
48+
$script = <<<HTML
4849
<script src="$source" {{ \$attributes }} {{ \implode(' ', \array_filter([\$defer ? 'defer' : '', \$async ? 'async' : '' ])) }}></script>
49-
HTML
50-
;
50+
HTML;
51+
52+
if ($this->meta) {
53+
$script .= "\n" . <<<HTML
54+
<meta name="{{ is_bool(\$meta) ? 'turnstile-sitekey' : \$meta }}" content="{$this->turnstile->getSiteKey()}" />
55+
HTML;
56+
57+
}
58+
59+
return $script;
5160
};
5261
}
5362

tests/Views/Components/ScriptTest.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,4 +71,26 @@ public function test_uses_attributes(): void
7171
false
7272
);
7373
}
74+
75+
public function test_adds_meta_tag(): void
76+
{
77+
$this->render('<x-turnstile::script meta />')
78+
->assertSee(<<<HTML
79+
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" defer async></script>
80+
<meta name="turnstile-sitekey" content="1x00000000000000000000AA" />
81+
HTML,
82+
false
83+
);
84+
}
85+
86+
public function test_adds_meta_tag_with_name(): void
87+
{
88+
$this->render('<x-turnstile::script meta="test-name" />')
89+
->assertSee(<<<HTML
90+
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" defer async></script>
91+
<meta name="test-name" content="1x00000000000000000000AA" />
92+
HTML,
93+
false
94+
);
95+
}
7496
}

0 commit comments

Comments
 (0)