Use this file to discover all available pages before exploring further.
Client SDK support for JavaScript agent v4 varies by framework. The React and Vue SDKs are supported, while other client SDKs are still in progress. See the current integration compatibility table. If your framework SDK is not supported yet, use the JavaScript agent directly.
You can use Fingerprint with any frontend framework or meta-framework, whether your page is rendered in the browser, on the server, or statically generated. You just need to ensure that loading the Fingerprint JavaScript agent and performing the visitor analysis happens on the client and not on the server.Since fingerprinting relies on signals from various browser APIs it cannot run outside the browser. Each (meta-)framework has its own way of specifying which code is client-only. If you use any of our client SDKs, it typically handles this for you automatically, but the details can vary depending on the SDK. You can find more information in the respective framework sections below.This guide will demonstrate the common patterns for Next.js, Nuxt, Gatsby, and Angular Universal.
Using our React SDKWe recommend using the Fingerprint React SDK which exposes the getData function and its result in a useVisitorData() hook. Since hooks cannot be used inside server components or server-side functions, you are forced to do the right thing by default.
TypeScript
import { useVisitorData } from '@fingerprint/react';export default function Page() { const { data } = useVisitorData(); return <div>Your visitor ID: {data?.visitor_id}</div>;}
In Next.js, the boundary between client and server is defined differently depending on if you are using the pages directory (how Next.js worked traditionally) or the new app directory (introduced in Next.js 13).
You can import and use the JavaScript agent inside components but not inside getStaticProps or getServerSideProps. You can still use the JavaScript agent on a page that is server-side rendered or statically generated, just do it in the component itself.
Note: In this context, “inside the component” means inside an event handler (e.g., onClick), a life cycle method (e.g., componentDidMount), or an effect (e.g., useEffect). Calling the JavaScript agent at the base of the component definition or its render method would also result in document is not defined error on server-side rendered pages.
Examples of correct JavaScript agent usage in a static page (with or without static props) and a server-rendered page:
import Fingerprint, { GetResult } from '@fingerprint/agent';import { useEffect, useState } from 'react';export default function Fingerprint() { const [fingerprintData, setFingerprintData] = useState<GetResult | null>(null); // ✅ This works, effects run in the browser only useEffect(() => { (async () => { const fp = Fingerprint.start({ apiKey: 'PUBLIC_API_KEY', endpoints: 'CUSTOM_SUBDOMAIN_URL', }); const data = await fp.get(); setFingerprintData(data); })(); }, []); return <div>Your visitor ID: {fingerprintData?.visitor_id}</div>;}
Some examples of antipatterns:
import Fingerprint from "@fingerprint/agent";// This is an antipattern// It's not possible to call Fingerprint agent on the server// It will result in `document is not defined` ReferenceErrorexport default function AntipatternGetServerSidePropsPage({ data }) { return <pre>{JSON.stringify(data)}</pre>;}// ❌ This won't work, this code will run server-side at runtimeexport async function getServerSideProps() { let data; const fp = Fingerprint.start({ apiKey: 'PUBLIC_API_KEY', endpoints: 'CUSTOM_SUBDOMAIN_URL', }); fp.get() .then((result) => { data = result; }); return { props: { data: data ?? "document is not defined", }, };}
All components inside the app directory are server-side by default. To use the JavaScript agent, wrap it inside a component that begins with the 'use client'; directive. This tells Next.js to render the component only in the browser. Then you can use it on a page inside app.
'use client';import Fingerprint, { GetResult } from '@fingerprint/agent';import { useEffect, useState } from 'react';export default function VisitorData() { const [fingerprintData, setFingerprintData] = useState<GetResult | null>(null); // ✅ This works, effects run in the browser only and // you can use useEffect here because of the `use client` directive useEffect(() => { (async () => { const fp = Fingerprint.start({ apiKey: 'PUBLIC_API_KEY', endpoints: 'CUSTOM_SUBDOMAIN_URL', }); const data = await fp.get(); setFingerprintData(data); })(); }, []); return ( <> <div>Your visitor ID: {fingerprintData?.visitor_id}</div> </> );};
If you are using the Fingerprint React SDK, you need to wrap your app (or the part of it that uses Fingerprint) inside FingerprintProvider. You can do this by putting the provider in a layout.tsx file. Since the provider uses Context under the hood, you either need to turn the entire layout into a client-side component with 'use client'; or wrap the FingerprintProvider inside a client component:
'use client';import { FingerprintProvider } from '@fingerprint/react';import { PropsWithChildren } from 'react';export function MyFingerprintProvider({ children }: PropsWithChildren) { return ( <FingerprintProvider apiKey="PUBLIC_API_KEY" endpoints="https://metrics.yourwebsite.com" > {children} </FingerprintProvider> );}
Using our Vue SDKInstead of importing the JavaScript agent directly, we recommend you take advantage of the Fingerprint Vue SDK, available as @fingerprint/vue. The same principle applies here:
Register Fingerprint as a client-side plugin by creating a fingerprintjs.client.ts file inside the plugins folder (the client suffix is important).
Wrap the component using Fingerprint inside the <ClientOnly> tag in your app template.
When using Nuxt, make sure to import and call the Fingerprint JavaScript agent in client-side code only. For example, you can create a component that calls the JS client inside its <script setup> tag, then wrap the component inside <ClientOnly>.
<template> <div> <h1>This Nuxt page is rendered server-side by default</h1> <ClientOnly> // ✅ This works, `VisitorData` will be rendered in the browser only // thanks to the `ClientOnly` wrapper <VisitorData /> </ClientOnly> </div></template>
Similar to Next.js, you can use the Fingerprint JavaScript agent inside component effects, event handlers and lifecycle methods. Using it inside getServerData(), component render functions and other server-side code will not work.
import * as React from 'react';import type { HeadFC, PageProps } from 'gatsby';import Fingerprint, {GetResult} from '@fingerprint/agent';const IndexPage: React.FC<PageProps> = () => { const [fingerprintData, setFingerprintData] = React.useState<GetResult | null>(null); // ✅ This works, effects run in the browser only React.useEffect(() => { (async () => { const fp = Fingerprint.start({ apiKey: 'PUBLIC_API_KEY', endpoints: 'CUSTOM_SUBDOMAIN_URL', }); const data = await fp.get(); setFingerprintData(data); })(); }, []); return ( <main> <h1>This site was statically generated by Gatsby</h1> <p>Your visitor ID is {fingerprintData?.visitor_id}</p> </main> );};export default IndexPage;
See the Gatsby documentation for more details and alternative approaches to running client-side-only code. For a smoother development experience, consider using the useVisitorData() hook from the Fingerprint React SDK.
Angular SDK support for JavaScript agent v4 is coming soonThe Fingerprint Angular SDK currently supports JavaScript agent v3. For Angular Universal with JavaScript agent v4, use the JavaScript agent directly in browser-only code as shown below.
When using server-side rendering with Angular Universal, make sure to run Fingerprint only in the browser. You can inject the Angular-provided PLATFORM_ID constant and check it with isPlatformBrowser:
app.component.ts
import { isPlatformBrowser } from '@angular/common';import { Component, Inject, PLATFORM_ID } from '@angular/core';import Fingerprint from '@fingerprint/agent';@Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'],})export class AppComponent { title = 'my-angular-app'; visitorId: string = 'Waiting...'; constructor(@Inject(PLATFORM_ID) private platformId: Object) { if (isPlatformBrowser(this.platformId)) { this.getVisitorId(); } } // ✅ Browser events run after hydration handler = () => { this.getVisitorId(); }; getVisitorId() { const fp = Fingerprint.start({ apiKey: 'PUBLIC_API_KEY', endpoints: 'CUSTOM_SUBDOMAIN_URL', }); fp.get().then((result) => { this.visitorId = result.visitor_id; console.log(result); }); }}
Astro is a multi-page application framework where all pages are static by default with “islands” of client-side interactivity. Use Fingerprint inside an island. Read more about Astro’s island architecture.
Remix is a React meta-framework similar to Next.js. For information on how to avoid running browser-only code on the server with Remix, see their Module constraints documentation.
SvelteKit is a Svelte meta-framework providing static generation and server-side rendering capabilities. You can run Fingerprint client-side only inside event handlers, lifecycle methods like onMount or by checking the browser constant in the @app/environment module.
Regardless of the framework you use, the principle is the same. Fingerprint relies on browser-only APIs so you can only run it in the browser, not on the server.