Skip to main content

Environments

We recommend creating a separate domain in the ShieldLabs dashboard for each environment.
EnvironmentDomainPublic Key
Developmentdev.example.comSLPUB_dev_...
Stagingstaging.example.comSLPUB_staging_...
Productionexample.comSLPUB_prod_...
Each domain gets its own public key, secret key, and webhook URL — so you can test without polluting production data.

Development: testing webhooks locally

Use ngrok or a similar tunnel to expose your local server:
ngrok http 3000
# → https://abc123.ngrok.io
Register the tunnel URL as your webhook:
curl -X POST "https://api.shieldlabs.ai/dev.example.com:YOUR_DEV_SECRET/callback" \
  -H "Content-Type: text/plain" \
  -d "https://abc123.ngrok.io/shieldlabs/webhook"

Environment variables

# .env.development
SHIELD_PUBLIC_KEY=d932476e-9f95-4ad9-820e-6f2118b1d27a
SHIELD_SECRET=89jb7aadzp6uuph5yo3pttw4

# .env.production
SHIELD_PUBLIC_KEY=a1b2c3d4-...
SHIELD_SECRET=xk9p2mzqwerty...
The SHIELD_PUBLIC_KEY is used in your frontend build. The SHIELD_SECRET must stay server-side only.

Next.js example

// lib/shield.js
export const SHIELD_PUBLIC_KEY = process.env.NEXT_PUBLIC_SHIELD_PUBLIC_KEY;
export const SHIELD_SECRET     = process.env.SHIELD_SECRET; // server-side only
// components/ShieldTracker.jsx
'use client';
import { useEffect } from 'react';
import { SHIELD_PUBLIC_KEY } from '@/lib/shield';

export function ShieldTracker({ userHashedId }) {
  useEffect(() => {
    let cancelled = false;
    (async () => {
      const mod = await import(
        `https://cdn.shieldlabs.ai/snippet.js?publicKey=${SHIELD_PUBLIC_KEY}`
      );
      if (!cancelled) {
        userHashedId
          ? mod.checkAuthenticatedUser(userHashedId)
          : mod.checkAnonymous();
      }
    })();
    return () => { cancelled = true; };
  }, [userHashedId]);
  return null;
}