request_id join key, and the same Risk Score (0-100) with its signals. Nothing about the integration changes between environments except the credentials and the host you load.
Two things change per environment
The domain and its key set
Register a separate domain for each environment (for example
dev.example.com and example.com). Each domain gets its own public key, secret key, webhook endpoints, and request balance.The snippet host
Production loads the snippet from
cdn.shieldlabs.ai. Development loads it from dev.cdn.shieldlabs.ai. Same module, same exports, same call pattern.Snippet hosts
The only host that differs in your page code is the CDN that serves the module.
Both serve the same ES module with the same
checkAnonymous, checkAuthenticatedUser, and forceCheck* exports that Install the snippet covers for the full client setup.
Use a separate domain and key set per environment
Register each environment as its own domain in app.shieldlabs.ai. Every domain you add gets an independent public key, secret key, webhook endpoints, and request balance.
Keeping them separate buys you:
- Clean data. Development traffic never lands in your production dashboard, so your visitor counts, traffic sources, and patterns reflect real users only.
- Isolated webhooks. Each domain registers its own webhook endpoints, so test deliveries hit your local handler and never your production endpoint.
- Independent balances. Test runs draw down the development domain’s request balance, not your paid production balance. Billing is per request.
- Blast-radius control. A leaked development secret cannot call the Server API for your production domain. Keys are scoped to a single domain. Webhook
whsec_…secrets are scoped per endpoint.
Wire the host and keys through config
Load the host and public key from environment config instead of hardcoding them, so the same build runs in both environments. Keep the Private API Key (for History API reads) and the secret key (for the Management API) server-side only, and store each webhookwhsec_… for signature verification. None of them must reach the browser.
ShieldLabsTracker.jsx
Your strict Content-Security-Policy must allow whichever snippet host that environment uses. A development build pointed at
dev.cdn.shieldlabs.ai needs that origin in script-src, not cdn.shieldlabs.ai. Keep the jsDelivr dependency host cdn.jsdelivr.net in script-src in both environments, and the connect-src endpoints (rest.shieldlabs.ai, webrtc.shieldlabs.ai, stun:ice.shieldlabs.ai:3478) stay the same in both. A very strict connect-src may skip the local-network check; the main snapshot and the Risk Score are unaffected.Receiving webhooks in development
Your development webhook needs a publicly reachable URL. Run a tunnel to your local server and register it as an endpoint on the development domain’s Webhooks tab:https://abc123.ngrok.app/webhooks/shieldlabs as an endpoint in the dashboard, copy that endpoint’s whsec_… secret into SHIELDLABS_WEBHOOK_SECRET, and verify X-Shield-Signature exactly as you will in production. The Webhooks guide carries the verification logic, the single webhook per scored identification (the server waits up to ~60s for follow-up checks, then sends the final score once), and the at-most-once delivery caveat.
Test with real traffic before production
Risk Scores reflect the actual connection and browser environment of whoever loads the page, so the most useful test is real traffic on a real development domain, not synthetic requests.1
Deploy the snippet on a development domain
Register
dev.example.com, drop the dev.cdn.shieldlabs.ai snippet onto a staging or preview deployment, and let real visits flow through it.2
3
Tune your thresholds against the bands
Decide what your code does at each band (Clean 0-9, Low 10-29, Medium 30-59, High 60-100) and verify the behavior on this real traffic, the way acting on the Risk Score lays out.
4
Promote to production
Swap the host to
cdn.shieldlabs.ai and the keys to the production domain’s key set through config. Nothing else in your code changes.A legitimate visitor can score high (a corporate proxy, a VPN, a privacy browser). Testing with real traffic on a development domain is the best way to see that distribution before you wire scores into a decision your application acts on. Decide on Score plus
signals plus context, and tune thresholds gradually.Promotion checklist
Snippet host
Snippet host
Switch the import URL from
dev.cdn.shieldlabs.ai to cdn.shieldlabs.ai, or flip the SHIELDLABS_SNIPPET_HOST config value.Public key
Public key
Use the production domain’s public key in the snippet URL.
Webhook endpoints
Webhook endpoints
Register production webhook endpoints in the dashboard Webhooks tab, not your development tunnel.
Secret key
Secret key
Load the production Secret Key on your server for Server API auth. It must never reach the browser.
Webhook signing secrets
Webhook signing secrets
Copy each production endpoint’s
whsec_… into your server environment for webhook verification.CSP
CSP
Confirm your production Content-Security-Policy allows
cdn.shieldlabs.ai in script-src.Next steps
Public and Secret Keys
Where each key lives and why the secret never ships to the browser.
Domains
Register a domain per environment and manage its webhook endpoints.
Webhooks
Verify
X-Shield-Signature and handle the single scored webhook per identification.Acting on the Risk Score
Turn the bands into allow, challenge, review, or block in your own code.