> ## Documentation Index
> Fetch the complete documentation index at: https://docs.fingerprintiq.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Next.js Integration

Integrate FingerprintIQ with Next.js App Router.

## Installation

```bash npm
npm install @fingerprintiq/js
```

```bash yarn
yarn add @fingerprintiq/js
```

```bash pnpm
pnpm add @fingerprintiq/js
```

FingerprintIQ uses browser APIs (canvas, WebGL, audio context) and **cannot run in Server Components**. Any component that uses the SDK must be marked with `'use client'`.

## Using the built-in hook

For most apps, the built-in Next.js hook is the fastest path:

```tsx
// components/visitor-gate.tsx
'use client';

import { useFingerprintIQ } from '@fingerprintiq/js/next';

export function VisitorGate() {
  const { result, loading, error } = useFingerprintIQ({
    apiKey: process.env.NEXT_PUBLIC_FIQ_API_KEY!,
  });

  if (loading) return <p>Identifying…</p>;
  if (error) return <p>Error: {error.message}</p>;
  return <p>Visitor: {result?.visitorId}</p>;
}
```

The `/next` subpath ships with `"use client";` baked in, so you can import it from any file and only mark your own wrapper component as a client component. Under the hood it re-exports the same hook as `@fingerprintiq/js/react` — choose whichever import path you prefer.

If you need a custom wrapper (e.g. to integrate with your auth flow or route changes), see the "Custom hook" pattern below.

## Client-Side Identification

Create a reusable hook in a client component:

```tsx
// components/Fingerprint.tsx
'use client';

import { useEffect, useRef, useState } from 'react';
import FingerprintIQ from '@fingerprintiq/js';

export function useFingerprint() {
  const [visitorId, setVisitorId] = useState<string | null>(null);
  const [botProbability, setBotProbability] = useState<number | null>(null);
  const fiqRef = useRef<FingerprintIQ | null>(null);

  useEffect(() => {
    async function init() {
      if (!fiqRef.current) {
        fiqRef.current = new FingerprintIQ({
          apiKey: process.env.NEXT_PUBLIC_FIQ_API_KEY!,
        });
      }
      const result = await fiqRef.current.identify();
      setVisitorId(result.visitorId);
      setBotProbability(result.botProbability);
    }
    init().catch(console.error);
  }, []);

  return { visitorId, botProbability };
}
```

## Server-Side Verification

After identifying on the client, send the `visitorId` to your API route for verification. This prevents spoofed visitor IDs from bypassing your trust logic.

```typescript
// app/api/verify/route.ts
import { NextResponse } from 'next/server';

export async function POST(req: Request) {
  const { visitorId } = await req.json();

  const res = await fetch(
    `https://fingerprintiq.com/v1/demo/visits/${visitorId}`,
    {
      headers: {
        'X-API-Key': process.env.FIQ_SECRET_KEY!,
        'Content-Type': 'application/json',
      },
    }
  );

  const data = await res.json();

  const isLegitimate =
    data.totalVisits >= 1 &&
    data.visits[0]?.confidence >= 0.8 &&
    data.visits[0]?.botProbability < 0.3;

  return NextResponse.json({
    verified: isLegitimate,
    isReturning: data.totalVisits > 1,
    firstSeen: data.firstSeenAt,
    totalVisits: data.totalVisits,
  });
}
```

## Environment Variables

```env
# .env.local
NEXT_PUBLIC_FIQ_API_KEY=fiq_live_your_public_key
FIQ_SECRET_KEY=fiq_live_your_secret_key
```

Never expose your secret API key to the client. The `NEXT_PUBLIC_` prefix makes variables available in the browser — only use it for your public key. The secret key must stay server-side only.

## Full Integration Example

Putting it all together — identify on the client, verify on the server, gate a feature:

```tsx
// app/checkout/page.tsx
'use client';

import { useEffect } from 'react';
import { useFingerprint } from '@/components/Fingerprint';

export default function CheckoutPage() {
  const { visitorId, botProbability } = useFingerprint();

  useEffect(() => {
    if (!visitorId) return;

    // Send to your server for verification
    fetch('/api/verify', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ visitorId }),
    })
      .then(res => res.json())
      .then(data => {
        if (!data.verified) {
          // Redirect or show challenge
          window.location.href = '/verify';
        }
      });
  }, [visitorId]);

  if (botProbability !== null && botProbability > 0.7) {
    return <div>Access denied. Suspicious activity detected.</div>;
  }

  return <CheckoutForm />;
}
```

Add FingerprintIQ identification to your root layout so the visitor ID is available by the time users reach protected pages — avoiding a waterfall of identify → verify → render.

**Advanced: Middleware-based bot blocking**

For server-rendered pages, you can add bot detection at the middleware level. However, this requires passing the visitor ID via a cookie set during client-side identification:

  ```typescript
  // middleware.ts
  import { NextResponse } from 'next/server';
  import type { NextRequest } from 'next/server';

  export async function middleware(request: NextRequest) {
    const visitorId = request.cookies.get('fiq_visitor_id')?.value;

    if (!visitorId) {
      // First visit — allow through, fingerprint will run client-side
      return NextResponse.next();
    }

    // Optional: verify visitorId against FingerprintIQ API
    // Be mindful of latency — this adds an extra API call to every request
    return NextResponse.next();
  }

  export const config = {
    matcher: ['/checkout/:path*', '/api/protected/:path*'],
  };
  ```