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

# Identify visitors

> Learn best practices for timing identification requests, caching visitor IDs, or using linked IDs to associate your own identifiers with each visitor ID.

Once the [JavaScript agent is installed and initialized](/docs/install-the-javascript-agent), call the [`get()`](/reference/js-agent-get-function) function (or its [SDK equivalent](/docs/frontend-libraries)) to identify the browsers visiting your website. The `get()` function sends the collected browser signals to the Fingerprint Platform and returns a [response](/reference/js-agent-get-function#get-response) containing the visitor ID for the browser and associated metadata.

This guide covers best practices for timing identification requests, caching visitor IDs, and using linked IDs to associate your own identifiers with each visitor ID. To explore further, please refer to the [JavaScript Agent API reference](/reference/js-agent).

If you are looking to identify mobile devices instead, see [Android](/docs/native-android-integration) and [iOS](/docs/ios).

<Note>
  **Note:** The code snippets in this guide assume you have already set up some kind proxy integration for Fingerprint. Proxying requests through your own domain or subdomain like metrics.yourwebsite.com instead of connecting to Fingerprint servers directly helps avoid ad blockers and increases accuracy.

  See [Installing the JavaScript agent](/docs/install-the-javascript-agent) and [Evading ad-blockers (proxy integrations)](/docs/protecting-the-javascript-agent-from-adblockers) for more details.
</Note>

## Timing identification requests

For most use cases, we recommend identifying the visitor on demand, when they perform a specific action:

* Call [`start()`](/reference/js-agent-start-function) as early as possible, ideally, right after the page loads.
* Call [`get()`](/reference/js-agent-get-function) only when needed (e.g., upon login or product selection).
* Wait at least 1 second after calling `start()` before calling `get()`, to give the JavaScript Agent enough time to collect the required signals.

```ts HTML theme={"theme":"github-dark-dimmed"}
<script>
      // Initialize the agent on page load
      const fpPromise = import('https://metrics.yourwebsite.com/v4/PUBLIC_API_KEY')
        .then(Fingerprint => Fingerprint.start({/*...*/}))

      // Analyze the visitor if they submit a form
      document.querySelector('button[type="submit"]').addEventListener('click', async () => {
        const fp = await fpPromise
        const result = await fp.get()
        console.log(result.event_id, result.visitor_id)
      })

</script>
```

This just-in-time approach also helps you:

* Ensure browsers are identified only after receiving the required [consent](/docs/privacy-and-compliance#do-i-need-to-have-a-gdpr-consent-management-banner-if-using-fingerprint).
* Avoid unnecessary use of your [billable](/docs/billing#identification-api-request-as-a-billing-unit) API calls.

See [Optimizing the JavaScript agent](/docs/optimize-javascript-agent) to learn more about deploying Fingerprint effectively.

### Response

The `get()` function returns a promise of a [response](/reference/js-agent-get-function#get-response) object with the visitor ID and other metadata.

<CodeGroup>
  ```javascript get() response wrap theme={"theme":"github-dark-dimmed"}
  await fp.get()
  // response:
  {
    "event_id": "8nbmT18x79m54PQ0GvPq",
    "visitor_id": "2JGu1Z4d2J4IqiyzO3i4",
    "suspect_score": 0,
    "sealed_result": null // or BinaryOutput when Sealed Results are enabled
  }
  ```
</CodeGroup>

<Note>
  **JavaScript agent response limitations**

  Note that the response received by the JavaScript agent is limited on purpose. Since client-side code can be tampered with, we recommend consuming Fingerprint results securely through one of our server-side integrations. The full identification event including the visitor's [Smart Signals](/docs/smart-signals-reference) is available through the [Server API](/reference/server-api), [Webhooks](/docs/webhooks), or [Sealed results](/docs/sealed-client-results).

  See [Protecting from client-side tampering](/docs/protecting-from-client-side-tampering) to learn about getting Fingerprint results securely to your server.
</Note>

## Linking and tagging information

The `visitor_id` provided by Fingerprint Identification is especially useful when combined with information you already know about your users, for example, account IDs, order IDs, etc. You can follow user actions, track logged-in devices, and recognize malicious behavior.

You can pass a `linkedId` or `tag` parameters to the `get()` function (or its equivalent in your SDK) to associate your own metadata with the visitor ID.

```ts HTML theme={"theme":"github-dark-dimmed"}
<script>
      const fpPromise = import('https://metrics.yourwebsite.com/v4/PUBLIC_API_KEY')
        .then(Fingerprint => Fingerprint.start())

      // Pass your own data to get()
      fpPromise
        .then(fp => fp.get({
          linkedId: "accountNum12345",
          tag: {
            orders: ["orderNum6789"],
            location: { city: "Atlanta", country: "US" }
          }
        }))
        .then(result => console.log(result.visitor_id))

</script>
```

* [`linkedId`](/reference/js-agent-get-function#linkedid) is a string you can use to filter identification events in the Dashboard or to filter visitor history using the Server API.
* [`tag`](/reference/js-agent-get-function#tag) is a JavaScript object of any shape allowing you to store structured metadata. It is *not indexed*, you cannot use it to search for events.

For more details, see [Linking and tagging information](/docs/tagging-information).

## Caching the visitor ID

If your use case demands highly accurate identification, we recommend identifying the visitor [on demand](#timing-identification-requests) and always using a fresh visitor ID without caching.

Depending on your use case, you can choose to cache (store) the visitor ID in the browser to:

* Improve the responsiveness of your application.
* Stay within the limits of your monthly allowance of API calls.

Caching visitor IDs for extended periods can significantly reduce identification accuracy. Make sure to understand caching best practices and implications before caching visitor IDs.

### Caching using JavaScript agent

JavaScript agent provides caching out of the box but is disabled by default.
To use it, you need to specify the [cache](/reference/js-agent-start-function#cache) option when initializing the agent.

```ts HTML theme={"theme":"github-dark-dimmed"}
<script>
    const fpPromise = import('https://metrics.yourwebsite.com/v4/PUBLIC_API_KEY')
      .then(Fingerprint => Fingerprint.start({
            cache: {
                storage: 'sessionStorage',
                duration: 'optimize-cost',
            }
      }))
</script>
```

The `optimize-cost` value caches visitor data for one hour. For all available cache configuration options, see [`CacheConfig`](/reference/js-agent-start-function#cacheconfig) in the `start()` function reference.

### Cache expiration time

We strongly recommend a maximum cache expiration time of **1 hour**.

The properties (e.g. browser version, extensions, screen resolution, IP address, etc) that Fingerprint collects from a browser often change over time. When these incremental changes are captured as soon as they occur, Fingerprint can identify a returning browser with industry-leading accuracy.

Using a longer expiration time leads to:

* Lower identification accuracy. Fingerprint can miss out on the incremental changes thus increasing the risk of incorrectly identifying a returning browser as new.
* Outdated Smart Signals information returned from the [Server API](/reference/server-api-get-event).
* Increased risk of [replay attacks](https://en.wikipedia.org/wiki/Replay_attack).

### Cache location

We strongly recommend using [**sessionStorage**](https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage) to cache the visitor ID.

Our data indicates sessionStorage is the best option to minimize the impact on identification accuracy compared to both [localStorage](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage) and [cookies](https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie).

> Note: A cached visitor ID stored in sessionStorage, localStorage, and cookies will not be available if the user switches to or from Incognito mode.

## What's next

* To protect the JavaScript agent from ad blockers and get maximum identification accuracy and coverage, see [Proxy integrations](/docs/protecting-the-javascript-agent-from-adblockers).
* To improve your identification latency, see [Optimizing JavaScript agent usage](/docs/optimize-javascript-agent).
* See the full JavaScript agent [API Reference](/reference/js-agent).
* Integrate Fingerprint with your server using the [Server API](/reference/server-api), [Webhooks](/docs/webhooks), or [Sealed results](/docs/sealed-client-results).
* If you are looking for device intelligence about mobile devices instead of browsers, see [Android](/docs/native-android-integration) and [iOS](/docs/ios).
