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

# Distinguish users for analytics

> Learn how to set the user token for more accurate analytics.

export const SearchRequest = () => <Tooltip tip="A search request is a single HTTP call to the Algolia Search API that can run one or more search operations. It can include multiple queries, for example, when querying several indices at once.">
    search request
  </Tooltip>;

By default, Algolia uses IP addresses to distinguish users.
To get more accurate analytics, set a `userToken` on search requests.

If you send searches from your backend, set a `userToken` to avoid grouping many users under the same server IP address.

To learn what a user token is, how to generate it, and how to handle anonymous and authenticated users, see [User token](/doc/guides/sending-events/concepts/usertoken).

<Info>
  A `userToken` is also required for [Personalization](/doc/guides/personalization/classic-personalization/personalizing-results#turn-on-personalization-in-production).
</Info>

## Before you begin

Use the same `userToken` for searches and click and conversion events so analytics can associate activity with the same user.

## Set the user token in InstantSearch and Autocomplete

Set the `insights` option to `true` when initializing InstantSearch or Autocomplete.

<CodeGroup>
  ```js Autocomplete expandable theme={"system"}
  import { autocomplete } from "@algolia/autocomplete-js";
  import algoliasearch from "algoliasearch/lite";

  const appID = "ALGOLIA_APPLICATION_ID";
  const apiKey = "ALGOLIA_SEARCH_API_KEY";

  const searchClient = algoliasearch(appID, apiKey);

  autocomplete({
  	container: "#autocomplete",
  	placeholder: "Search ...",
  	insights: true,
  	getSources({ query }) {
  		// ...
  	},
  });

  // Set an anonymous user token
  window.aa("setUserToken", "ANONYMOUS_USER_TOKEN");

  // Set an authenticated user token
  window.aa("setAuthenticatedUserToken", "AUTHENTICATED_USER_TOKEN");
  ```

  ```js InstantSearch.js theme={"system"}
  import instantsearch from "instantsearch.js";

  const search = instantsearch({
  	indexName: "INDEX_NAME",
  	searchClient,
  	insights: {
  		insightsInitParams: {
  			// Set anonymous user token
  			userToken: "ANONYMOUS_USER_TOKEN",

  			// Set authenticated user token
  			authenticatedUserToken: "AUTHENTICATED_USER_TOKEN",
  		},
  	},
  });

  // Set an anonymous user token
  window.aa("setUserToken", "ANONYMOUS_USER_TOKEN");

  // Set an authenticated user token
  window.aa("setAuthenticatedUserToken", "AUTHENTICATED_USER_TOKEN");
  ```

  ```jsx React InstantSearch expandable theme={"system"}
  import { InstantSearch } from "react-instantsearch";

  <InstantSearch
  	indexName="INDEX_NAME"
  	searchClient={searchClient}
  	insights={{
  		insightsInitParams: {
  			// Set your own user token
  			userToken: "ANONYMOUS_USER_TOKEN",

  			// Set an authenticated user token
  			authenticatedUserToken: "AUTHENTICATED_USER_TOKEN",
  		},
  	}}
  >
  	{/* ... */}
  </InstantSearch>;

  // Set an anonymous user token
  window.aa("setUserToken", "ANONYMOUS_USER_TOKEN");

  // Set an authenticated user token
  window.aa("setAuthenticatedUserToken", "AUTHENTICATED_USER_TOKEN");
  ```

  ```vue Vue InstantSearch expandable theme={"system"}
  <template>
    <ais-instant-search
      :index-name="INDEX_NAME"
      :search-client="searchClient"
      :insights="insights"
    >
      <!--  widgets  -->
    </ais-instant-search>
  </template>

  <script>
  // Set an anonymous user token
  window.aa("setUserToken", "ANONYMOUS_USER_TOKEN");

  // Set an authenticated user token
  window.aa("setAuthenticatedUserToken", "AUTHENTICATED_USER_TOKEN");

  export default {
    data() {
      return {
        insights: {
          insightsInitParams: {
            // Set your own user token
            userToken: "ANONYMOUS_USER_TOKEN",

            // Set an authenticated user token
            authenticatedUserToken: "AUTHENTICATED_USER_TOKEN",
          },
        },
      };
    },
  };
  </script>
  ```
</CodeGroup>

For more information, see:

* [Send click and conversion events with Autocomplete](/doc/ui-libraries/autocomplete/guides/sending-algolia-insights-events)
* [Send click and conversion events with InstantSearch.js](/doc/guides/building-search-ui/events/js)
* [Send click and conversion events with React InstantSearch](/doc/guides/building-search-ui/events/react)
* [Send click and conversion events with Vue InstantSearch](/doc/guides/building-search-ui/events/vue)

## Set the user token in InstantSearch iOS and Android

Add the `userToken` as an API parameter to your search requests:

<CodeGroup>
  ```kotlin Android theme={"system"}
  val query = query {
      userToken {
          'ANONYMOUS_USER_TOKEN'
      }
  }

  val searcher = HitsSearcher(client, indexName, query)
  ```

  ```swift iOS theme={"system"}
  let query = Query()
  query.userToken = "ANONYMOUS_USER_TOKEN"
  let searcher = HitsSearcher(index: index, query: query)
  ```
</CodeGroup>

## Set the user token with API clients

Use the same [`userToken`](/doc/libraries/search-insights/set-user-token#param-user-token) in search requests and click and conversion events.

To set the user token **per search request**:

<CodeGroup>
  ```cs C# theme={"system"}
  var response = await client.SearchSingleIndexAsync<Hit>(
    "INDEX_NAME",
    new SearchParams(new SearchParamsObject { Query = "query", UserToken = "user-1234" })
  );
  ```

  ```dart Dart theme={"system"}
  final response = await client.searchSingleIndex(
    indexName: "INDEX_NAME",
    searchParams: SearchParamsObject(
      query: "query",
      userToken: "user-1234",
    ),
  );
  ```

  ```go Go theme={"system"}
  response, err := client.SearchSingleIndex(client.NewApiSearchSingleIndexRequest(
    "INDEX_NAME").WithSearchParams(search.SearchParamsObjectAsSearchParams(
    search.NewEmptySearchParamsObject().SetQuery("query").SetUserToken("user-1234"))))
  if err != nil {
    // handle the eventual error
    panic(err)
  }
  ```

  ```java Java theme={"system"}
  SearchResponse response = client.searchSingleIndex(
    "INDEX_NAME",
    new SearchParamsObject().setQuery("query").setUserToken("user-1234"),
    Hit.class
  );
  ```

  ```js JavaScript theme={"system"}
  const response = await client.searchSingleIndex({
    indexName: 'indexName',
    searchParams: { query: 'query', userToken: 'user-1234' },
  });
  ```

  ```kotlin Kotlin theme={"system"}
  var response =
    client.searchSingleIndex(
      indexName = "INDEX_NAME",
      searchParams = SearchParamsObject(query = "query", userToken = "user-1234"),
    )
  ```

  ```php PHP theme={"system"}
  $response = $client->searchSingleIndex(
      'INDEX_NAME',
      ['query' => 'query',
          'userToken' => 'user-1234',
      ],
  );
  ```

  ```python Python theme={"system"}
  response = client.search_single_index(
      index_name="INDEX_NAME",
      search_params={
          "query": "query",
          "userToken": "user-1234",
      },
  )
  ```

  ```ruby Ruby theme={"system"}
  response = client.search_single_index(
    "INDEX_NAME",
    Algolia::Search::SearchParamsObject.new(query: "query", user_token: "user-1234")
  )
  ```

  ```scala Scala theme={"system"}
  val response = Await.result(
    client.searchSingleIndex(
      indexName = "INDEX_NAME",
      searchParams = Some(
        SearchParamsObject(
          query = Some("query"),
          userToken = Some("user-1234")
        )
      )
    ),
    Duration(100, "sec")
  )
  ```

  ```swift Swift theme={"system"}
  let response: SearchResponse<Hit> = try await client.searchSingleIndex(
      indexName: "INDEX_NAME",
      searchParams: SearchSearchParams.searchSearchParamsObject(SearchSearchParamsObject(
          query: "query",
          userToken: "user-1234"
      ))
  )
  ```
</CodeGroup>

To set the user token when you initialize an API client:

<CodeGroup>
  ```cs C# theme={"system"}
  namespace Algolia;

  using System;
  using System.Collections.Generic;
  using System.Net.Http;
  using System.Text.Json;
  using Algolia.Search.Clients;
  using Algolia.Search.Http;
  using Algolia.Search.Models.Search;

  class GlobalAlgoliaUserID
  {
    async Task Main(string[] args)
    {
      var client = new SearchClient(
        new SearchConfig("ALGOLIA_APPLICATION_ID", "ALGOLIA_API_KEY")
        {
          DefaultHeaders = new Dictionary<string, string>
          {
            { "X-Algolia-UserToken", "test-user-123" },
          },
        }
      );
      Console.WriteLine(client);
    }
  }

  ```

  ```dart Dart theme={"system"}
  import 'package:algolia_client_search/algolia_client_search.dart';

  void globalAlgoliaUserID() async {
    final client = SearchClient(
        appId: 'ALGOLIA_APPLICATION_ID',
        apiKey: 'ALGOLIA_API_KEY',
        options: ClientOptions(
          headers: {
            'X-Algolia-User-ID': 'test-user-123',
          },
        ));
    print(client.options.headers);
  }

  ```

  ```go Go theme={"system"}
  package main

  import (
  	"fmt"

  	"github.com/algolia/algoliasearch-client-go/v4/algolia/search"
  )

  func globalAlgoliaUserID() {
  	client, err := search.NewClient("ALGOLIA_APPLICATION_ID", "ALGOLIA_API_KEY")
  	if err != nil {
  		fmt.Println(err)
  	}

  	client.AddDefaultHeader("X-Algolia-UserToken", "test-user-123")
  }

  ```

  ```java Java theme={"system"}
  package com.algolia;

  import com.algolia.api.SearchClient;
  import com.algolia.config.*;
  import com.algolia.model.search.*;

  public class globalAlgoliaUserID {

    public static void main(String[] args) throws Exception {
      SearchClient client = new SearchClient(
        "ALGOLIA_APPLICATION_ID",
        "ALGOLIA_API_KEY",
        ClientOptions.builder().addDefaultHeader("X-Algolia-UserToken", "test-user-123").build()
      );
      client.close();
    }
  }

  ```

  ```js JavaScript theme={"system"}
  import { algoliasearch } from 'algoliasearch';

  const client = algoliasearch('ALGOLIA_APPLICATION_ID', 'ALGOLIA_API_KEY', {
    baseHeaders: {
      'X-Algolia-User-ID': 'test-user-123',
    },
  });
  console.log(client);

  ```

  ```kotlin Kotlin theme={"system"}
  import com.algolia.client.api.SearchClient
  import com.algolia.client.configuration.*
  import com.algolia.client.extensions.*
  import com.algolia.client.model.search.*
  import com.algolia.client.transport.*

  suspend fun globalAlgoliaUserID() {
    val client =
      SearchClient(
        appId = "ALGOLIA_APPLICATION_ID",
        apiKey = "ALGOLIA_API_KEY",
        options = ClientOptions(defaultHeaders = mapOf("X-Algolia-User-ID" to "test-user-123")),
      )
    println(client.options.defaultHeaders)
  }

  ```

  ```php PHP theme={"system"}
  <?php

  require __DIR__.'/../vendor/autoload.php';
  use Algolia\AlgoliaSearch\Api\SearchClient;

  $config = SearchConfig::create('ALGOLIA_APPLICATION_ID', 'ALGOLIA_API_KEY');
  $config->setDefaultHeaders(['X-Algolia-UserToken' => 'test-user-123']);
  $client = SearchClient::createWithConfig($config);
  echo $client->getClientConfig()->getDefaultHeaders();

  ```

  ```python Python theme={"system"}
  from algoliasearch.search.client import SearchClientSync
  from algoliasearch.search.config import SearchConfig


  _config = SearchConfig("ALGOLIA_APPLICATION_ID", "ALGOLIA_API_KEY")
  _config.headers["x-algolia-userToken"] = "test-user-123"
  _client = SearchClientSync.create_with_config(_config)
  print(_client)

  ```

  ```ruby Ruby theme={"system"}
  import(time)

  require "algolia"

  client = Algolia::SearchClient.create(app_id, api_key)
  client.api_client.config.header_params["X-Algolia-UserToken"] = "test-user-123"
  puts(client.api_client.config.header_params)

  ```

  ```scala Scala theme={"system"}
  import algoliasearch.api.SearchClient
  import algoliasearch.config.*
  import algoliasearch.extension.SearchClientExtensions

  def globalAlgoliaUserID(): Unit = {
    val client = SearchClient(
      appId = "ALGOLIA_APPLICATION_ID",
      apiKey = "ALGOLIA_API_KEY",
      clientOptions = ClientOptions(
        defaultHeaders = Map("X-Algolia-UserToken" -> "test-user-123")
      )
    )
    println(client)
  }

  ```
</CodeGroup>

## If you can't set a user token

If you search from your backend and can't or don't want to set a `userToken`,
you can [forward user IP addresses](/doc/guides/search-analytics/concepts/query-aggregation#forward-user-ip-addresses) to improve analytics accuracy.
