<botshield-verify> Web Component
The <botshield-verify> element renders a verification widget on the merchant’s page. When clicked, it opens the BotShield passkey verification flow. On success, the widget transitions to a verified state and fires a callback with a signed token.
Installation
Add a single script tag to your page. No npm install, no build step.
<script src="https://cdn.botshield.ai/sdk.js"></script>
The script registers the <botshield-verify> custom element globally. It uses a closed Shadow DOM so it never conflicts with your page styles.
Usage
<botshield-verify
site-key="pk_live_YOUR_SITE_KEY"
theme="auto"
onsuccess="handleVerified"
onfailure="handleFailed"
></botshield-verify>
<script>
function handleVerified({ token }) {
// Enable the checkout button
document.querySelector('#checkout-btn').disabled = false;
// Send token to your backend
submitTokenToServer(token);
}
function handleFailed({ reason }) {
console.error('Verification failed:', reason);
}
</script>
Attributes
| Attribute | Type | Default | Description |
|---|
site-key | string | required | Your public site key (pk_live_... or pk_test_...) |
theme | light | dark | auto | auto | Visual theme. auto follows the user’s prefers-color-scheme. |
challenge-url | string | https://cdn.botshield.ai/challenge | Override the challenge page URL (for self-hosted deployments) |
onsuccess | string | - | Name of a global function called with { token } on success |
onfailure | string | - | Name of a global function called with { reason } on failure |
onexpired | string | - | Name of a global function called when the token expires |
onready | string | - | Name of a global function called when the widget loads |
Events
In addition to callback attributes, the element dispatches standard Custom Events. Use addEventListener if you prefer:
const el = document.querySelector('botshield-verify');
el.addEventListener('botshield:success', (e) => {
const { token } = e.detail;
submitTokenToServer(token);
});
el.addEventListener('botshield:failure', (e) => {
console.error('Failed:', e.detail.reason);
});
| Event | e.detail | Description |
|---|
botshield:ready | {} | Widget has loaded and is ready for interaction |
botshield:success | { token } | User completed verification. token is a signed JWT. |
botshield:failure | { reason } | Verification failed. reason explains why. |
botshield:expired | {} | The verification token has expired. Widget resets to idle. |
Visual States
The widget transitions through four states:
| State | Appearance | Behavior |
|---|
| idle | Shield icon, “Verify human presence”, “Required” badge | Click to start verification |
| verifying | Spinner, “Verifying…” | Verification in progress (new tab open) |
| verified | Green checkmark, “Human presence verified”, green border | Complete. Token available via callback. |
| failed | Red X, “Verification failed”, red border | Click to reset and retry. |
Themes
White background (#f9f9f9), gray border (#bebfc1), dark text.
Dark background (#0b0b0c), subtle border (#2a2a2a), light text. Blue gradient BotShield logo.
Follows the user’s system preference via prefers-color-scheme.
JavaScript API
The element exposes methods for programmatic control:
const el = document.querySelector('botshield-verify');
// Trigger verification programmatically
el.verify();
// Get the token after verification
const token = el.getToken(); // string | null
// Reset to idle state
el.reset();
Server-Side Token Validation
After receiving the token via onsuccess, validate it on your server:
// POST the token from your frontend to your backend
const response = await fetch('https://api.botshield.ai/v1/verify', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer sk_live_YOUR_SECRET_KEY',
},
body: JSON.stringify({
token: botshieldToken,
}),
});
const result = await response.json();
if (result.valid) {
// Human verified -- proceed with checkout
}
Never skip server-side validation. The client-side token alone is not sufficient — always verify with your secret key on the backend.
When placed inside a <form>, the widget automatically injects a hidden input with the verification token:
<form action="/checkout" method="POST">
<botshield-verify
site-key="pk_live_YOUR_SITE_KEY"
onsuccess="enableSubmit"
></botshield-verify>
<!-- This hidden input is auto-created on verification success -->
<!-- <input type="hidden" name="botshield_token" value="eyJhbGc..."> -->
<button type="submit" id="checkout-btn" disabled>
Proceed to Checkout
</button>
</form>
<script>
function enableSubmit() {
document.getElementById('checkout-btn').disabled = false;
}
</script>
Shopify (Cart Page)
<!-- In your Shopify theme's cart template -->
<script src="https://cdn.botshield.ai/sdk.js"></script>
<botshield-verify
site-key="pk_live_YOUR_KEY"
theme="auto"
onsuccess="enableCheckout"
></botshield-verify>
<script>
function enableCheckout({ token }) {
// Store token for checkout submission
sessionStorage.setItem('botshield_token', token);
document.querySelector('[name=checkout]').disabled = false;
}
</script>
WooCommerce
<!-- Before the Place Order button -->
<script src="https://cdn.botshield.ai/sdk.js"></script>
<botshield-verify
site-key="pk_live_YOUR_KEY"
theme="light"
onsuccess="onVerified"
></botshield-verify>
<script>
function onVerified({ token }) {
// Inject token into the checkout form
const input = document.createElement('input');
input.type = 'hidden';
input.name = 'botshield_token';
input.value = token;
document.querySelector('form.checkout').appendChild(input);
document.getElementById('place_order').disabled = false;
}
</script>
Next Steps