Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
36a26ba
feat: migrate to v4 version of the agent
TheUnderScorer Dec 18, 2025
883a44c
chore: use FpProvider in error message for ssr
TheUnderScorer Dec 18, 2025
c46b0eb
chore: move agent to dependencies
TheUnderScorer Dec 18, 2025
ac3aa97
chore: add vite app example
TheUnderScorer Dec 19, 2025
66011fd
docs: update docs for v4
TheUnderScorer Dec 19, 2025
254a9cc
chore: fix broken SSR
TheUnderScorer Dec 19, 2025
81a09a7
chore: use new sdk in next example
TheUnderScorer Dec 19, 2025
066b2ad
test: fix tests
TheUnderScorer Dec 19, 2025
5107846
chore: apply copilot suggestions
TheUnderScorer Dec 19, 2025
5537d0d
Merge pull request #178 from fingerprintjs/feature/INTER-1708-agent-v4
TheUnderScorer Dec 19, 2025
074378b
chore(release): 3.0.0-test.1 [skip ci]
semantic-release-bot Dec 19, 2025
537e14a
chore: adjust cache parameter
TheUnderScorer Jan 6, 2026
c5d217d
feat: bump @fingerprint/agent to 4.0.0-beta.5
TheUnderScorer Jan 6, 2026
0eac7a3
Merge pull request #179 from fingerprintjs/feature/INTER-1708-agent-v4
TheUnderScorer Jan 6, 2026
60a42ca
chore(release): 3.0.0-test.2 [skip ci]
semantic-release-bot Jan 6, 2026
76a2fec
build(deps): use stable 4.0.0 version of the @fingerprint/agent
TheUnderScorer Jan 13, 2026
fb59d7f
feat: add usePromiseStore to prevent duplicate async requests
TheUnderScorer Jan 27, 2026
3f4afaf
build: migrate to vite and vitest
TheUnderScorer Jan 27, 2026
444587b
refactor: add useConst hook and update usePromiseStore to utilize it
TheUnderScorer Jan 27, 2026
f7c61b5
refactor: adjust @fingerprint/agent export structure
TheUnderScorer Jan 27, 2026
aba662c
refactor: remove unnecessary console log in isEnvDetails function
TheUnderScorer Jan 27, 2026
e28d921
build: update lock
TheUnderScorer Jan 27, 2026
87bbb80
refactor: replace FpjsProvider with FpProvider in Next.js app example
TheUnderScorer Jan 27, 2026
e9b5998
build: update lock
TheUnderScorer Jan 27, 2026
d94c8d9
build: update Vite external dependencies configuration
TheUnderScorer Jan 27, 2026
979e3ee
refactor: replace FpjsProvider with FpProvider in documentation and e…
TheUnderScorer Jan 27, 2026
b196ff5
refactor: remove redundant error name assignment in use-visitor-data
TheUnderScorer Jan 27, 2026
d9d9835
docs: update links and integration instructions in README and contrib…
TheUnderScorer Jan 27, 2026
4714fdf
feat: rename package to `@fingerprint/react`
TheUnderScorer Jan 27, 2026
e1eb0a1
docs: fix typo
TheUnderScorer Jan 27, 2026
3ff7810
test: use resetModules()
TheUnderScorer Jan 27, 2026
149a4a1
docs: fix link
TheUnderScorer Jan 27, 2026
c6ad1b6
build: update package output filenames and references to `fp-react`
TheUnderScorer Jan 27, 2026
63e437e
Merge remote-tracking branch 'origin/feature/INTER-1708-agent-v4' int…
TheUnderScorer Jan 27, 2026
1b6ca6e
refactor: rename `Fp` to `Fingerprint` in exports
TheUnderScorer Jan 27, 2026
a0ee321
Merge remote-tracking branch 'origin/test' into feature/INTER-1708-ag…
TheUnderScorer Jan 27, 2026
64c0c9c
refactor: replace `Fp` with `Fingerprint` in components, context, and…
TheUnderScorer Jan 27, 2026
e0aad39
Merge pull request #180 from fingerprintjs/feature/INTER-1708-agent-v4
TheUnderScorer Jan 27, 2026
6feb6be
chore(release): 3.0.0-test.3 [skip ci]
semantic-release-bot Jan 27, 2026
1957d6b
chore: revert pre-release version bump
TheUnderScorer Jan 27, 2026
6b3a09f
Merge pull request #181 from fingerprintjs/feature/INTER-1708-agent-v4
TheUnderScorer Jan 27, 2026
9013307
chore(release): 3.0.0-test.3 [skip ci]
semantic-release-bot Jan 27, 2026
d2117dd
chore: revert pre-release version bump
TheUnderScorer Jan 27, 2026
2bffeff
chore: update package.json to set publishConfig access to public
TheUnderScorer Jan 27, 2026
c8fad2d
chore: add custom agent loader support
TheUnderScorer Jan 28, 2026
7c4697d
refactor: remove extendedResult logic from examples
TheUnderScorer Jan 28, 2026
cf939ff
chore: remove pre-release changelog notes
TheUnderScorer Jan 28, 2026
1c4c877
chore: enable trusted publishing in release workflow
TheUnderScorer Jan 28, 2026
aa7c5cd
chore: update README title to "Fingerprint React"
TheUnderScorer Jan 29, 2026
1cf7602
chore: update README URLs to reflect repository rename to "react"
TheUnderScorer Jan 29, 2026
6e9b8aa
chore: update contributing guide to reflect repository rename to "Fin…
TheUnderScorer Jan 29, 2026
45e78af
chore: update README references to "Fingerprint React" for consistency
TheUnderScorer Jan 29, 2026
fef9d91
chore: update contributing guide to clarify package name as "@fingerp…
TheUnderScorer Jan 29, 2026
353e20b
chore: update README to replace "Fingerprint Pro" with "Fingerprint"
TheUnderScorer Jan 29, 2026
c8eca76
refactor: update VisitorDataPresenter to use Fingerprint.GetResult an…
TheUnderScorer Jan 29, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/coverage-diff.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@ jobs:
checks: write
pull-requests: write
uses: fingerprintjs/dx-team-toolkit/.github/workflows/coverage-diff.yml@v1
with:
testScript: pnpm test:coverage:diff
1 change: 1 addition & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ jobs:
uses: fingerprintjs/dx-team-toolkit/.github/workflows/release-typescript-project.yml@v1
with:
appId: ${{ vars.APP_ID }}
useTrustedPublishing: true
secrets:
APP_PRIVATE_KEY: ${{ secrets.APP_PRIVATE_KEY }}
NPM_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }}
7 changes: 6 additions & 1 deletion .releaserc
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,12 @@
}
],
"@semantic-release/changelog",
"@semantic-release/npm",
[
"@semantic-release/npm",
{
"npmPublish": false
}
],
[
"@semantic-release/exec",
{
Expand Down
107 changes: 38 additions & 69 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,28 @@
</a>
</p>
<p align="center">
<a href="https://github.com/fingerprintjs/fingerprintjs-pro-react/actions/workflows/release.yml"><img src="https://github.com/fingerprintjs/fingerprintjs-pro-react/actions/workflows/release.yml/badge.svg" alt="CI badge" /></a>
<a href="https://fingerprintjs.github.io/fingerprintjs-pro-react/coverage/"><img src="https://fingerprintjs.github.io/fingerprintjs-pro-react/coverage/badges.svg" alt="coverage"></a>
<a href="https://www.npmjs.com/package/@fingerprintjs/fingerprintjs-pro-react"><img src="https://img.shields.io/npm/v/@fingerprintjs/fingerprintjs-pro-react.svg" alt="Current NPM version"></a>
<a href="https://www.npmjs.com/package/@fingerprintjs/fingerprintjs-pro-react"><img src="https://img.shields.io/npm/dm/@fingerprintjs/fingerprintjs-pro-react.svg" alt="Monthly downloads from NPM"></a>
<a href="https://github.com/fingerprintjs/react/actions/workflows/release.yml"><img src="https://github.com/fingerprintjs/react/actions/workflows/release.yml/badge.svg" alt="CI badge" /></a>
<a href="https://fingerprintjs.github.io/react/coverage/"><img src="https://fingerprintjs.github.io/react/coverage/badges.svg" alt="coverage"></a>
<a href="https://www.npmjs.com/package/@fingerprint/react"><img src="https://img.shields.io/npm/v/@fingerprint/react.svg" alt="Current NPM version"></a>
<a href="https://www.npmjs.com/package/@fingerprint/react"><img src="https://img.shields.io/npm/dm/@fingerprint/react.svg" alt="Monthly downloads from NPM"></a>
<a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/:license-mit-blue.svg" alt="MIT license"></a>
<a href="https://discord.gg/39EpE2neBg"><img src="https://img.shields.io/discord/852099967190433792?style=logo&label=Discord&logo=Discord&logoColor=white" alt="Discord server"></a>
<a href="https://fingerprintjs.github.io/fingerprintjs-pro-react/"><img src="https://img.shields.io/badge/-Documentation-green" alt="Discord server"></a>
<a href="https://fingerprintjs.github.io/react/"><img src="https://img.shields.io/badge/-Documentation-green" alt="Discord server"></a>
</p>

# Fingerprint Pro React
# Fingerprint React

Fingerprint is a device intelligence platform offering industry-leading accuracy. Fingerprint Pro React SDK is an easy way to integrate **[Fingerprint Pro](https://fingerprint.com/)** into your React application. It's also compatible with Next.js and Preact. See application demos in the [examples](https://github.com/fingerprintjs/fingerprintjs-pro-react/tree/main/examples) folder.
Fingerprint is a device intelligence platform offering industry-leading accuracy. Fingerprint React SDK is an easy way to integrate **[Fingerprint](https://fingerprint.com/)** into your React application. It's also compatible with Next.js and Preact. See application demos in the [examples](https://github.com/fingerprintjs/react/tree/main/examples) folder.

## Table of contents


- [Fingerprint Pro React](#fingerprint-pro-react)
- [Fingerprint React](#fingerprint-react)
- [Table of contents](#table-of-contents)
- [Requirements](#requirements)
- [Installation](#installation)
- [Getting started](#getting-started)
- [1. Wrap your application (or component) in `<FpjsProvider>`.](#1-wrap-your-application-or-component-in-fpjsprovider)
- [1. Wrap your application (or component) in `<FingerprintProvider>`.](#1-wrap-your-application-or-component-in-FingerprintProvider)
- [2. Use the `useVisitorData()` hook in your components to identify visitors](#2-use-the-usevisitordata-hook-in-your-components-to-identify-visitors)
- [Linking and tagging information](#linking-and-tagging-information)
- [Caching strategy](#caching-strategy)
Expand All @@ -46,69 +46,59 @@ Fingerprint is a device intelligence platform offering industry-leading accuracy
- For Typescript users: Typescript 4.8 or higher

> [!NOTE]
> This package assumes you have a Fingerprint Pro subscription or trial, it is not compatible with the [source-available FingerprintJS](https://github.com/fingerprintjs/fingerprintjs). See our documentation to learn more about the [differences between Fingerprint Pro and FingerprintJS](https://dev.fingerprint.com/docs/identification-vs-fingerprintjs).
> This package assumes you have a Fingerprint subscription or trial, it is not compatible with the [source-available FingerprintJS](https://github.com/fingerprintjs/fingerprintjs). See our documentation to learn more about the [differences between Fingerprint and FingerprintJS](https://docs.fingerprint.com/docs/identification-vs-fingerprintjs).

## Installation

Using [npm](https://npmjs.org):

```sh
npm install @fingerprintjs/fingerprintjs-pro-react
npm install @fingerprint/react
```

Using [yarn](https://yarnpkg.com):

```sh
yarn add @fingerprintjs/fingerprintjs-pro-react
yarn add @fingerprint/react
```

Using [pnpm](https://pnpm.js.org):

```sh
pnpm add @fingerprintjs/fingerprintjs-pro-react
pnpm add @fingerprint/react
```

## Getting started

In order to identify visitors, you'll need a Fingerprint Pro account (you can [sign up for free](https://dashboard.fingerprint.com/signup/)).
To get your API key and get started, see the [Fingerprint Pro Quick Start Guide](https://dev.fingerprint.com/docs/quick-start-guide).
In order to identify visitors, you'll need a Fingerprint account (you can [sign up for free](https://dashboard.fingerprint.com/signup/)).
To get your API key and get started, see the [Fingerprint Quick Start Guide](https://docs.fingerprint.com/docs/quick-start-guide).

### 1. Wrap your application (or component) in `<FpjsProvider>`.
### 1. Wrap your application (or component) in `<FingerprintProvider>`.

- Set `apiKey` to your Fingerprint [Public API Key](https://dashboard.fingerprint.com/api-keys).
- Set `region` if you have chosen a non-global [region](https://dev.fingerprint.com/docs/regions) during registration.
- Set `endpoint` and `scriptUrlPattern` if you are using [one of our proxy integrations to increase accuracy](https://dev.fingerprint.com/docs/protecting-the-javascript-agent-from-adblockers) and effectiveness of visitor identification.
- You can use all the [load options](https://dev.fingerprint.com/reference/load-function#load-options) available in the JavaScript agent `load` function.
- Set `region` if you have chosen a non-global [region](https://docs.fingerprint.com/docs/regions) during registration.
- Set `endpoint` if you are using [one of our proxy integrations to increase accuracy](https://docs.fingerprint.com/docs/protecting-the-javascript-agent-from-adblockers) and effectiveness of visitor identification.
- You can use all the [start options](https://docs.fingerprint.com/reference/js-agent-v4-start-function#start-options) available in the JavaScript agent `load` function.

```jsx
// src/index.js
import React from 'react'
import ReactDOM from 'react-dom/client'
import {
FpjsProvider,
FingerprintProvider,
FingerprintJSPro,
} from '@fingerprintjs/fingerprintjs-pro-react'
} from '@fingerprint/react'
import App from './App'

const root = ReactDOM.createRoot(document.getElementById('app'))

// <FingerprintProvider /> supports the same options as `start()` function.
root.render(
<FpjsProvider
loadOptions={{
apiKey: 'your-public-api-key',
// region: 'eu',
endpoint: [
// 'metrics.yourwebsite.com',
FingerprintJSPro.defaultEndpoint,
],
scriptUrlPattern: [
// 'https://metrics.yourwebsite.com/web/v<version>/<apiKey>/loader_v<loaderVersion>.js',
FingerprintJSPro.defaultScriptUrlPattern,
],
}}
<FingerprintProvider
apiKey='your-public-api-key'
>
<App />
</FpjsProvider>
</FingerprintProvider>
)
```

Expand All @@ -117,10 +107,10 @@ root.render(
```jsx
// src/App.js
import React from 'react'
import { useVisitorData } from '@fingerprintjs/fingerprintjs-pro-react'
import { useVisitorData } from '@fingerprint/react'

function App() {
const { isLoading, error, data } = useVisitorData()
const { isLoading, error, isFetched, data } = useVisitorData()

if (isLoading) {
return <div>Loading...</div>
Expand All @@ -129,36 +119,29 @@ function App() {
return <div>An error occured: {error.message}</div>
}

if (data) {
// Perform some logic based on the visitor data
return (
<div>
Welcome {data.visitorFound ? 'back' : ''}, {data.visitorId}!
</div>
)
} else {
return null
if (isFetched) {
return <div>Welcome {data.visitor_id}!</div>
}

return null
}

export default App
```

The `useVisitorData` hook also returns a `getData` method you can use to make an API call on command.

- You can pass `{ ignoreCache: true }` to `useVisitorData` to force a fresh identification request.
- You can pass `{ immediate: false }` to `useVisitorData` to disable automatic visitor identification on render.

Both `useVisitorData` and `getData` accept all the [get options](https://dev.fingerprint.com/reference/get-function#get-options) available in the JavaScript agent `get` function.
Both `useVisitorData` and `getData` accept all the [get options](https://docs.fingerprint.com/reference/get-function#get-options) available in the JavaScript agent `get` function.

```jsx
// src/App.js
import React, { useState } from 'react'
import { useVisitorData } from '@fingerprintjs/fingerprintjs-pro-react'
import { useVisitorData } from '@fingerprint/react'

function App() {
const { isLoading, error, getData } = useVisitorData(
{ ignoreCache: true },
{ immediate: false }
)
const [email, setEmail] = useState('')
Expand Down Expand Up @@ -206,7 +189,7 @@ export default App

## Linking and tagging information

The `visitorId` provided by Fingerprint Identification is especially useful when combined with information you already know about your users, for example, account IDs, order IDs, etc. To learn more about various applications of the `linkedId` and `tag`, see [Linking and tagging information](https://dev.fingerprint.com/docs/tagging-information).
The `visitorId` provided by Fingerprint Identification is especially useful when combined with information you already know about your users, for example, account IDs, order IDs, etc. To learn more about various applications of the `linkedId` and `tag`, see [Linking and tagging information](https://docs.fingerprint.com/docs/tagging-information).

Associate the visitor ID with your data using the `linkedId` or `tag` parameter of the options object passed into the `useVisitorData()` hook or the `getData` function:

Expand All @@ -224,32 +207,18 @@ function App() {
// ...
```

## Caching strategy

Fingerprint Pro usage is billed per API call. To avoid unnecessary API calls, it is a good practice to cache identification results. By default, the SDK uses `sessionStorage` to cache results.

- Specify the `cacheLocation` prop on `<FpjsProvider>` to instead store results in `memory` or `localStorage`. Use `none` to disable caching completely.
- Specify the `cacheTimeInSeconds` prop on `<FpjsProvider>` to set the cache time in seconds. It cannot exceed 86400 seconds (24 hours).
- Specify the `cache` prop on `<FpjsProvider>` to use your custom cache implementation instead. For more details, see [Creating a custom cache](https://github.com/fingerprintjs/fingerprintjs-pro-spa#creating-a-custom-cache)
in the Fingerprint Pro SPA repository (a lower-level Fingerprint library used by this SDK).
- Pass `{ignoreCache: true}` to the `getData()` function to ignore cached results for that specific API call.

> [!NOTE]
> If you use data from [`extendedResult`](https://dev.fingerprint.com/reference/get-function#extendedresult), pay additional attention to your caching strategy.
> Some fields, for example, `ip` or `lastSeenAt`, might change over time for the same visitor. Use `getData({ ignoreCache: true })` to fetch the latest identification results.

## Error handling

The `getData` function throws errors directly from the JS Agent without changing them. See [JS Agent error handling](https://dev.fingerprint.com/reference/error-handling) for more details.
The `getData` function throws errors directly from the JS Agent without changing them. See [JS Agent error handling](https://docs.fingerprint.com/reference/js-agent-v4-error-handling) for more details.

## API Reference

See the full [generated API reference](https://fingerprintjs.github.io/fingerprintjs-pro-react/).
See the full [generated API reference](https://fingerprintjs.github.io/react/).

## Support and feedback

To ask questions or provide feedback, use [Issues](https://github.com/fingerprintjs/fingerprintjs-pro-react/issues). If you need private support, please email us at `oss-support@fingerprint.com`. If you'd like to have a similar React wrapper for the [source-availalbe FingerprintJS](https://github.com/fingerprintjs/fingerprintjs), consider creating an issue in the main [FingerprintJS repository](https://github.com/fingerprintjs/fingerprintjs/issues).
To ask questions or provide feedback, use [Issues](https://github.com/fingerprintjs/react/issues). If you need private support, please email us at `oss-support@fingerprint.com`. If you'd like to have a similar React wrapper for the [source-availalbe FingerprintJS](https://github.com/fingerprintjs/fingerprintjs), consider creating an issue in the main [FingerprintJS repository](https://github.com/fingerprintjs/fingerprintjs/issues).

## License

This project is licensed under the MIT license. See the [LICENSE](https://github.com/fingerprintjs/fingerprintjs-pro-react/blob/main/LICENSE) file for more info.
This project is licensed under the MIT license. See the [LICENSE](https://github.com/fingerprintjs/react/blob/main/LICENSE) file for more info.
1 change: 1 addition & 0 deletions __tests__/detect-env.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { detectEnvironment } from '../src/detect-env'
import { Env } from '../src/env.types'
import { describe, it, expect } from 'vitest'

describe('Detect user env', () => {
describe('Preact', () => {
Expand Down
58 changes: 26 additions & 32 deletions __tests__/fpjs-provider.test.tsx
Original file line number Diff line number Diff line change
@@ -1,42 +1,36 @@
import { useContext } from 'react'
import { renderHook } from '@testing-library/react'
import { FpjsContext } from '../src'
import { FingerprintContext } from '../src'
import { createWrapper, getDefaultLoadOptions } from './helpers'
import { CacheLocation, FpjsClient, FpjsClientOptions } from '@fingerprintjs/fingerprintjs-pro-spa'
import * as packageInfo from '../package.json'
import { version } from '../package.json'
import { describe, it, expect, vi } from 'vitest'
import * as agent from '@fingerprint/agent'

jest.mock('@fingerprintjs/fingerprintjs-pro-spa', () => {
return {
...jest.requireActual<any>('@fingerprintjs/fingerprintjs-pro-spa'),
FpjsClient: jest.fn(() => ({
init: jest.fn(),
})),
}
})
vi.mock('@fingerprint/agent', { spy: true })

const mockStart = vi.mocked(agent.start)

describe(`FpjsProvider`, () => {
it('should configure an instance of the FpjsClient', async () => {
describe('FingerprintProvider', () => {
it('should configure an instance of the Fp Agent', async () => {
const loadOptions = getDefaultLoadOptions()
const options: FpjsClientOptions = {
loadOptions,
cacheLocation: CacheLocation.LocalStorage,
cachePrefix: 'TEST_PREFIX',
cacheTimeInSeconds: 60 * 15,
}
const wrapper = createWrapper(options)
renderHook(() => useContext(FpjsContext), {
const wrapper = createWrapper({
cache: {
cachePrefix: 'cache',
storage: 'sessionStorage',
duration: 100,
},
})
renderHook(() => useContext(FingerprintContext), {
wrapper,
})
expect(FpjsClient).toHaveBeenCalledWith(
expect.objectContaining({
loadOptions: expect.objectContaining({
...loadOptions,
integrationInfo: [`react-sdk/${packageInfo.version}/react`],
}),
cacheLocation: CacheLocation.LocalStorage,
cachePrefix: 'TEST_PREFIX',
cacheTimeInSeconds: 60 * 15,
})
)
expect(mockStart).toHaveBeenCalledWith({
...loadOptions,
integrationInfo: [`react-sdk/${version}/react`],
cache: {
cachePrefix: 'cache',
storage: 'sessionStorage',
duration: 100,
},
})
})
})
13 changes: 6 additions & 7 deletions __tests__/helpers.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
import { PropsWithChildren } from 'react'
import { FpjsClientOptions } from '@fingerprintjs/fingerprintjs-pro-spa'
import { FpjsProvider } from '../src'
import { act } from 'react-dom/test-utils'
import { FingerprintProvider, FingerprintProviderOptions } from '../src'
import { act } from '@testing-library/react'

export const getDefaultLoadOptions = () => ({
apiKey: 'test_api_key',
})

export const createWrapper =
({ loadOptions = getDefaultLoadOptions(), ...options }: Partial<FpjsClientOptions> = {}) =>
({ children }: PropsWithChildren<{}>): JSX.Element => (
<FpjsProvider loadOptions={loadOptions} {...options}>
(providerProps: Partial<FingerprintProviderOptions> = {}) =>
({ children }: PropsWithChildren<{}>) => (
<FingerprintProvider {...getDefaultLoadOptions()} {...providerProps}>
{children}
</FpjsProvider>
</FingerprintProvider>
)

export const wait = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms))
Expand Down
Loading
Loading