SDKs

Next.js

Identify visitors in Next.js 15 and newer. A provider that works from a Server Component layout, a hidden form field, and a Server Action helper that reads it.

@fingerly/next builds on @fingerly/react for the App Router and the Pages Router. It adds a provider you can render from a Server Component, a form field that carries the request ID, and a server entry point with helpers that never import React.

Requirements

  • Next.js 15 or newer, with React 19.
  • A public key with your site in its allowed origins.

Install

npm install @fingerly/next

Add the provider

Read the key in your root layout, which stays a Server Component, and pass it to the provider.

app/layout.tsx
import { FingerlyProvider } from '@fingerly/next'

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        <FingerlyProvider apiKey={process.env.FINGERLY_PUBLIC_KEY}>{children}</FingerlyProvider>
      </body>
    </html>
  )
}

The provider also reads NEXT_PUBLIC_FINGERLY_API_KEY, NEXT_PUBLIC_FINGERLY_ENDPOINT and NEXT_PUBLIC_FINGERLY_ENDPOINTS (a JSON array) when a prop is not given. Passing the key as a prop is the arrangement that always works. With the Pages Router, render the same provider in _app.tsx.

Carry the request ID through a Server Action

FingerlyRequestId renders a hidden input that fills itself once the identification finishes. readRequestId reads it back on the server.

import { FingerlyRequestId } from '@fingerly/next'
import { signUp } from './actions'

export default function Page() {
  return (
    <form action={signUp}>
      <input name="email" type="email" />
      <FingerlyRequestId />
      <button>Create account</button>
    </form>
  )
}
  • The field is named fingerly_request_id (REQUEST_ID_FIELD). Pass name to change it.
  • readRequestId returns null for a missing, empty or malformed value and never throws.
  • Several fields on one page still make one identification.

Hooks

useIdentify, useVerdict and useFingerly are re-exported from @fingerly/react and behave identically. See the React SDK.

app/checkout/Checkout.tsx
'use client'
import { useIdentify } from '@fingerly/next'

export function Checkout() {
  const { identify, isLoading } = useIdentify()
  // …
}

Entry points

ImportRuns inContains
@fingerly/nextThe browserThe provider, FingerlyRequestId and the hooks. A 'use client' module.
@fingerly/next/serverThe serverreadRequestId, REQUEST_ID_FIELD and createFingerlyProxy. No React.

Proxy through a route handler

createFingerlyProxy is the Node.js SDK's createProxy, re-exported. Mount it on a catch-all route and point the provider at it.

import { createFingerlyProxy } from '@fingerly/next/server'

export const POST = createFingerlyProxy({
  proxyKey: process.env.FINGERLY_PROXY_KEY!,
  prefix: '/metrics',
  clientIp: (request) => request.headers.get('x-real-ip') ?? '',
})

Resolve the client address only from a header your hosting platform sets. See proxy integrations.