Get Started using the Keverd Next.js SDK
Overview
In this 5-minute quickstart, you’ll add Keverd to a Next.js app and get:
- Persistent device IDs that survive incognito, VPNs, and browser clears
- Real-time risk scores for every user action
- Automatic fraud detection with minimal setup
No backend setup required for the frontend integration. Keverd works out-of-the-box with your existing Next.js app.
Prerequisites
- Node.js 18+ and npm
- Your Favorite Code Editor
- A Next.js app (new or existing, App Router or Pages Router)
- 5 minutes of your time
This quickstart covers the frontend setup only. You’ll need a backend server to receive and process device identification events for full fraud detection. Check out one of the backend quickstarts after completing this.
Step 1: Get Your API Key
- Sign up for a free Keverd account at dashboard.keverd.com/request-access
- Navigate to Settings → API Keys
- Copy your Public API Key (starts with
pk_live_)
Step 2: Install the SDK
npm install @keverdjs/react
We use the @keverdjs/react package for Next.js. It is fully compatible with both App Router and Pages Router.
Step 3: Wrap Your App with KeverdProvider
Choose your router below. The provider prepares Keverd but does not trigger API calls yet.
App Router
Create a client component wrapper:
// app/components/KeverdWrapper.jsx
'use client';
import { KeverdProvider } from '@keverdjs/react';
export function KeverdWrapper({ children }) {
return (
<KeverdProvider apiKey="pk_live_your_api_key_here">
{children}
</KeverdProvider>
);
}
Then use it in your root layout:
// app/layout.jsx
import { KeverdWrapper } from './components/KeverdWrapper';
export default function RootLayout({ children }) {
return (
<html lang="en">
<body>
<KeverdWrapper>
{children}
</KeverdWrapper>
</body>
</html>
);
}
Pages Router
// pages/_app.jsx
import { KeverdProvider } from '@keverdjs/react';
export default function MyApp({ Component, pageProps }) {
return (
<KeverdProvider apiKey="pk_live_your_api_key_here">
<Component {...pageProps} />
</KeverdProvider>
);
}
Step 4: Initialize Fingerprinting
Keverd only starts collecting device data and making API calls when a component calls useKeverd(). This is intentional — it gives you control over when fingerprinting happens (e.g., on login, checkout, or page load).
useKeverd() must be called inside a Client Component ('use client' in App Router). It cannot be used in Server Components.
Basic usage — trigger on component mount:
// app/checkout/page.jsx (App Router)
'use client';
import { useKeverd } from '@keverdjs/react';
export default function CheckoutPage() {
const { deviceId, riskScore, isLoading, error } = useKeverd();
if (isLoading) return <div>Loading device profile...</div>;
if (error) return <div>Failed to identify device. Please refresh.</div>;
return (
<div>
<p>Device ID: {deviceId}</p>
<p>Risk Score: {riskScore}/100</p>
<p>Risk Level: {riskScore > 70 ? '⚠️ High' : '✅ Normal'}</p>
</div>
);
}
// pages/checkout.jsx (Pages Router)
import { useKeverd } from '@keverdjs/react';
export default function CheckoutPage() {
const { deviceId, riskScore, isLoading, error } = useKeverd();
if (isLoading) return <div>Loading device profile...</div>;
if (error) return <div>Failed to identify device. Please refresh.</div>;
return (
<div>
<p>Device ID: {deviceId}</p>
<p>Risk Score: {riskScore}/100</p>
<p>Risk Level: {riskScore > 70 ? '⚠️ High' : '✅ Normal'}</p>
</div>
);
}
How It Works
| Step | What Happens | Who Triggers It |
|---|
| 1. Provider mounts | SDK loads, validates API key | KeverdProvider |
| 2. Fingerprinting starts | Device signals collected, API call made | First useKeverd() call |
| 3. Data available | deviceId, riskScore returned to component | Hook re-renders with data |
Key point: If no component calls useKeverd(), Keverd stays idle. No API calls are made. No device data is collected.
Complete Example
App Router
// app/components/KeverdWrapper.jsx
'use client';
import { KeverdProvider } from '@keverdjs/react';
export function KeverdWrapper({ children }) {
return (
<KeverdProvider apiKey="pk_live_your_api_key_here">
{children}
</KeverdProvider>
);
}
// app/layout.jsx
import { KeverdWrapper } from './components/KeverdWrapper';
export default function RootLayout({ children }) {
return (
<html lang="en">
<body>
<KeverdWrapper>
{children}
</KeverdWrapper>
</body>
</html>
);
}
// app/checkout/page.jsx
'use client';
import { useKeverd } from '@keverdjs/react';
export default function Checkout() {
const { deviceId, riskScore, isLoading } = useKeverd();
if (isLoading) return <div>Verifying device...</div>;
return (
<div>
<h1>Checkout</h1>
<p>Processing payment from device: {deviceId}</p>
{riskScore > 70 && (
<p style={{color: 'red'}}>
⚠️ High risk detected. Additional verification required.
</p>
)}
</div>
);
}
Pages Router
// pages/_app.jsx
import { KeverdProvider } from '@keverdjs/react';
export default function MyApp({ Component, pageProps }) {
return (
<KeverdProvider apiKey="pk_live_your_api_key_here">
<Component {...pageProps} />
</KeverdProvider>
);
}
// pages/checkout.jsx
import { useKeverd } from '@keverdjs/react';
export default function Checkout() {
const { deviceId, riskScore, isLoading } = useKeverd();
if (isLoading) return <div>Verifying device...</div>;
return (
<div>
<h1>Checkout</h1>
<p>Processing payment from device: {deviceId}</p>
{riskScore > 70 && (
<p style={{color: 'red'}}>
⚠️ High risk detected. Additional verification required.
</p>
)}
</div>
);
}
What About My Backend?
Once useKeverd() has resolved, Keverd automatically injects headers into your HTTP requests:
// Every fetch/axios request gets these headers:
headers: {
'X-Keverd-Device-ID': 'dev_2x7f9k3m4n5p8q2r',
'X-Keverd-Risk-Score': '23',
'X-Keverd-Session-ID': 'sess_abc123'
}
Backend reads the headers. No backend code changes needed beyond reading them.
Using in API Routes
// app/api/payment/route.js (App Router)
export async function POST(request) {
const headers = request.headers;
const deviceId = headers.get('X-Keverd-Device-ID');
const riskScore = headers.get('X-Keverd-Risk-Score');
if (riskScore > 70) {
return Response.json({ error: 'High risk transaction blocked' }, { status: 403 });
}
// Process payment...
}
// pages/api/payment.js (Pages Router)
export default function handler(req, res) {
const deviceId = req.headers['x-keverd-device-id'];
const riskScore = req.headers['x-keverd-risk-score'];
if (riskScore > 70) {
return res.status(403).json({ error: 'High risk transaction blocked' });
}
// Process payment...
}
Testing It Works
1. Verify the Hook Triggers the Call
Open DevTools Network tab, then mount a client component with useKeverd(). You should see a request to Keverd’s API.
2. Check the Console
// After useKeverd() resolves:
console.log(window.__KEVERD_DEVICE_ID__);
// Should show: "dev_2x7f9k3m4n5p8q2r"
3. Test Incognito Persistence
// In normal window
await keverd.getDeviceId(); // "dev_2x7f9k3m4n5p8q2r"
// Open incognito, run same code
await keverd.getDeviceId(); // "dev_2x7f9k3m4n5p8q2r" (SAME ID)
4. View Your Dashboard
Visit dashboard.keverd.com to see devices, risk scores, and blocked attempts.
Common Questions
Q: Can I trigger fingerprinting without rendering UI?
Yes. Create an invisible client component that calls useKeverd() on mount, or call the imperative API directly (see JavaScript Quickstart).
Q: What if I call useKeverd() in multiple components?
The SDK deduplicates — only one API call is made, and all components share the result.
Q: Does KeverdProvider itself make any API calls?
No. It only sets up context. The first useKeverd() call triggers all fingerprinting logic.
Q: Can I use useKeverd() in a Server Component?
No. Device fingerprinting requires browser APIs (canvas, WebGL, etc.) that only exist on the client. Always use 'use client' in App Router.
Q: Will this affect my Core Web Vitals?
The SDK is loaded asynchronously and fingerprinting is deferred until useKeverd() is called. It does not block the initial page render.
Key additions for Next.js:
1. **App Router vs Pages Router** — separate code examples for both
2. **`'use client'` directive** — explicitly marked on all `useKeverd()` examples since it only works client-side
3. **API Routes section** — showing how to read Keverd headers in both `app/api/` and `pages/api/` patterns
4. **Server Component warning** — clear note that `useKeverd()` cannot run in Server Components
5. **Core Web Vitals note** — addresses a common Next.js concern about bundle size and render blocking