> ## 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.

# 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.

| Use case                         | Description                                                                                                                                                                               |
| :------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Account Takeover Prevention**  | Link visitor ID to account username to prevent malicious login attempts. Require multi-factor authentication if an unfamiliar visitor ID is trying to log in.                             |
| **Account Sharing Prevention**   | Link visitor ID to account username to prevent users from sharing accounts.  Flag accounts that exceed a certain number of visitor IDs as suspected of account sharing.                   |
| **Trial Abuse Prevention**       | Link visitor ID to account username to prevent multiple sign-ups from a single visitor. Flag visitor IDs that exceed a certain number of associated accounts as suspected of trial abuse. |
| **Credit Card Fraud Prevention** | Link visitor ID to hashed credit card numbers to prevent repeated use of faulty credit cards. Flag visitors that exceed a certain number of credit cards.                                 |

There are three ways to link visitor IDs with your own metadata:

* **On your server, in your own database**: Process visitor ID and metadata on your server and store them in your own database table. This approach is secure, durable, and recommended for most security use cases.
* **On your client, during the identification event**: Use the `linkedId` or `tag` parameters to pass your metadata to the Fingerprint API when requesting the visitor ID. Fingerprint stores this data for 30 or 90+ days, depending on your plan. This method is recommended for use cases where spoofing and long-term storage are not a concern.
* **On your server, after the identification event**: Update existing events by sending the `linked_id` or `tags` information to the `/v4/events/:event_id` endpoint with a PATCH request. This method allows for modifying event data after the initial identification, which is useful if the information was not available at the time of the client-side request. The updated data is stored the same way as the client-side parameters.

## Linking information in your own database

On the client, use the Fingerprint JavaScript agent to get a visitor ID and send it to your server for processing.

```javascript client/login.js theme={"theme":"github-dark-dimmed"}
import * as Fingerprint from '@fingerprint/agent';

// ...
const fp = Fingerprint.start({ apiKey: PUBLIC_API_KEY });

fp.get()
  .then((result) => {
    const { visitor_id, event_id } = result;
    fetch(`/api/linking-data`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        visitor_id,
        event_id,
        accountId: '123456',
      }),
    });
  });
```

Inside the server endpoint, verify the authenticity of the visitor ID and save it to your database together with your internal ID or other metadata.

```javascript server/api/linking-data.js theme={"theme":"github-dark-dimmed"}
export default async function submitEndpointHandler(req, res) {
  const { event_id, visitor_id, accountId } = req.body;
  if (!areIDsValid(event_id, visitor_id)) {
    res.status(400).send('Something went wrong.');
    return;
  }
  saveToAccountsDatabaseTable({
    visitor_id,
    accountId
  });
  res.status(200).send('visitor ID and accountId link saved to database');
}
```

<Note>
  [Verifying the visitor ID](/docs/protecting-from-client-side-tampering) involves calling our [Server API](/reference/server-api) to make sure it was recently generated by Fingerprint. See our [Fingerprint Use Cases](https://github.com/fingerprintjs/fingerprintjs-pro-use-cases) project for implementation examples.
</Note>

This approach requires more setup but is more secure. You have full control over the data and can store it indefinitely.

## Using `linkedId` and `tag` on the client

Associate your data with a visitor ID using the `linkedId` or `tag` parameter of the [JavaScript agent](/reference/js-agent-get-function#linkedid)'s `get()` function.

```html client/identify.js theme={"theme":"github-dark-dimmed"}
<script>
  const fpPromise = import('https://fpjscdn.net/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>
```

Your information will be part of that identification event and available through [Webhooks](/docs/webhooks) and [Server API](/reference/server-api). You can use webhooks to automatically store the events in your own database indefinitely.

```json Event data theme={"theme":"github-dark-dimmed"}
{
  "event_id": "1680110819553.B2U183",
  "linked_id": "accountNum12345",
  "tags": {
    "location": {
      "city": "Atlanta",
      "country": "US"
    },
    "orders": [
      "orderNum6789"
    ]
  },
  "identification": {
    "visitor_id": "cMBjS1eCyObMgQ4BiYEO"
    // ...
  }
}
```

## Updating `linked_id` and `tags` on the server

Associate `linked_id` or `tags` data with a visitor ID using the `/v4/events/:event_id` endpoint of the Fingerprint Server API with a PATCH request.

On the client, use the Fingerprint JavaScript agent to get an event ID and send it to your server.

```javascript client/order.js theme={"theme":"github-dark-dimmed"}
import * as Fingerprint from '@fingerprint/agent';

// ...
const fp = Fingerprint.start({ apiKey: PUBLIC_API_KEY });

fp.get()
  .then((result) => {
    const { event_id } = result;

    // Send information to the server for processing the order
    // At this point, we do not have the order ID yet
    fetch(`/api/process-order`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        event_id,
        // Any other relevant information related to the order process can be sent here. e.g., cart ID, products, etc.
      }),
    });
  });
```

On the backend, use the event ID to make a PATCH request to the `/v4/events/:event_id` endpoint of the Fingerprint Server API.

```javascript server/api/process-order.js theme={"theme":"github-dark-dimmed"}
const response = await fetch(`https://api.fpjs.io/v4/events/${event_id}`, {
  method: "PATCH",
  headers: {
    "Content-Type": "application/json",
    "Authorization": "Bearer SECRET_API_KEY",
  },
  body: JSON.stringify({
    linked_id: orderId, // Use the order ID as the linked_id
    tags: {
      orderStatus: "completed", // Example additional tag
      paymentMethod: "credit_card", // Example additional tag
    },
  }),
});
```

Your information will be added to the event and available through the Dashboard and [Server API](/reference/server-api).

```json Event data theme={"theme":"github-dark-dimmed"}
{
  "event_id": "1730134629123.MALXYZ",
  "linked_id": "orderNum12345",
  "tags": {
    "orderStatus": "completed",
    "paymentMethod": "credit_card"
  },
  "identification": {
    "visitor_id": "cxhbePz123zrMpABC2r3"
    // ...
  }
}
```

Tagged or linked information has no influence on identification accuracy. Both `tags` and `linked_id` are arbitrary pieces of information linked to a particular Fingerprint event for your own use.

### What's the difference between `linked ID` and `tag`?

* `linked_id` is a simple string identifier. Fingerprint indexes it so you can use it as a filter when retrieving the [visit history](/reference/server-api-search-events) of a specific visitor ID via the [Server API](/reference/server-api). Objects, arrays, or non-string values passed to `linked_id` are converted to strings.
* `tag` accepts any simple value or any JavaScript object smaller than 16KB. It cannot be used to filter visits but can store a large amount of structured data about your visitor.

<Warning>
  **Limitations**

  #### Spoofing

  Defining `linkedId` and `tag` in the browser is vulnerable to tampering, as is all client-side code. More sophisticated attackers can spoof the `linkedId` or `tag` and send any arbitrary value to Fingerprint API.
  We don't recommend relying on `linked_id` and `tag` for security use cases. Link visitor IDs to other metadata [on your server instead](#linking-information-in-your-own-database).

  #### Data storage

  Fingerprint stores the visit history [for a limited time](/docs/billing#account-limits) (30 days for accounts, 90 or more for Enterprise). After that, the identification events and their `linked_id` and `tags` values will not be available through the Server API.
  If your use case requires long-term data storage, you can use webhooks to [store the events](/docs/regions#data-retention) in your database as they happen or link visitor IDs to your metadata [on your server entirely](#linking-information-in-your-own-database).
</Warning>

### Hashing linked or tagged information

Fingerprint Identification is often useful when your internal IDs are unavailable, for example, on a login or signup page. To avoid sending emails, phone numbers, or other sensitive information to Fingerprint, you can hash the information first and pass only the hash into the `tag` or `linkedId`.

<Note>
  **Hashing explained**

  A [hash function](https://en.wikipedia.org/wiki/Hash_function) is a mathematical function that takes an input of arbitrary length and outputs a random-looking fixed-length representation of it. Hash functions are used to represent the original data in a more efficient and secure way.

  * For the same input, a hash function always returns the same result.
  * Any change in input leads to a different result (collisions are rare).
  * Computing the original input from its hash is practically impossible.
</Note>

You can use the [crypto browser API](https://developer.mozilla.org/en-US/docs/Web/API/Crypto) to hash sensitive information before sending it to Fingerprint:

```javascript Hashing information before passing it to &#x60;linkedId&#x60; theme={"theme":"github-dark-dimmed"}
async function hash(sensitiveInfo) {
  const hashBytes = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(sensitiveInfo));
  return Array.prototype.map
    .call(new Uint8Array(hashBytes), (byte) => byte.toString(16).padStart(2, '0'))
    .join('');
}

const email = "personalemail@gmail.com";
const linkedId = await hash(email);
// linkedId is now '9663a85cfcd473cba225ab15bbb4ca6a424203297f62e87abd5fa897a6f0aef7'

fp.get({ linkedId })
  .then(result => console.log(result.visitor_id));
```

For example, you might want to reduce multiple signups from the same visitor ID. On submit, you can use the Server API to retrieve all email hashes recently linked to that visitor ID. Then flag or block the visitor ID if it exceeds a certain number of linked emails.
