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

# Prepare your search implementation

> Learn how to prepare your search implementation for Advanced Personalization.

export const UserToken = () => <Tooltip tip="A user token is a pseudonymous ID that represents an individual user across Algolia searches and events. It links queries, clicks, and conversions to a user profile, enabling user-level analytics, personalization, and recommendations." cta="User token" href=" /doc/guides/sending-events/concepts/usertoken">
    user token
  </Tooltip>;

export const SearchQuery = () => <Tooltip tip="The text users enter into a search box. In the Search API, this corresponds to the query parameter. A search query is often used with filters, facets, and other parameters, but these aren't part of the query text itself.">
    search query
  </Tooltip>;

export const UserProfile = () => <Tooltip tip="A user profile contains data about a single user, including behavior, preferences, and affinities collected from events. Algolia uses this data to deliver personalized content.">
    user profile
  </Tooltip>;

export const Index = () => <Tooltip tip="An Algolia index is a searchable dataset that consists of records and configuration settings. These settings define how the records are searched and ranked.">
    index
  </Tooltip>;

After [preparing your event implementation](/doc/guides/personalization/advanced-personalization/configure/prerequisites/event-implementation),
focus on your search implementation.

## Attach user tokens to queries

To ensure that the Advanced Personalization feature can understand each user's journey and continuously improve their personalization experience, attach a <UserToken /> to each query.
The user tokens attached to the queries must match the user tokens sent with events.

<Callout icon="credit-card" color="#c084fc">
  This feature isn't available on every plan.
  Refer to your [pricing plan](https://www.algolia.com/pricing) to see if it's included.
</Callout>

### Attach user tokens with InstantSearch

To include the [`userToken`](/doc/api-reference/api-parameters/userToken) in a <SearchQuery /> using InstantSearch,
use the [`configure`](/doc/api-reference/widgets/configure/js) widget to set the [`userToken`](/doc/api-reference/api-parameters/userToken) search parameter.

<CodeGroup>
  ```js JavaScript theme={"system"}
  instantsearch.widgets.configure({
    userToken: 'user-1234',
  });
  ```

  ```jsx React theme={"system"}
  <Configure userToken="user-1234" />
  ```

  ```vue-html Vue theme={"system"}
  <ais-configure userToken="user-1234" />
  ```

  ```kotlin Android theme={"system"}
  searcher.query.userToken = 'user-1234'
  ```

  ```swift Swift theme={"system"}
  searcher.request.query.userToken = 'user-1234'
  ```

  ```dart Flutter theme={"system"}
  final hitsSearcher = HitsSearcher.create(
    applicationID: 'undefined',
    apiKey: 'ALGOLIA_SEARCH_API_KEY',
    state: const SearchState(userToken: 'user-1234'),
  );
  ```
</CodeGroup>

### Attach user tokens with an API client

To include the [`userToken`](/doc/api-reference/api-parameters/userToken) in your search queries with one of the API clients,
use the [`search`](/doc/libraries/sdk/v1/methods/search) method to send the [`userToken`](/doc/api-reference/api-parameters/userToken) search parameter.

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

## Persist user tokens

For a <UserProfile /> to be found and retrieved at search time,
you should [persist anonymous user tokens](/doc/guides/sending-events/concepts/usertoken#persistent-user-token) and authenticated user tokens across sessions.

## Avoid enabling personalization at query time

Rather than using the [`enablePersonalization`](/doc/api-reference/api-parameters/enablePersonalization) search parameter at query time,
set it in the <Index /> settings when moving to production.
This lets you [A/B test the impact of personalization](/doc/guides/personalization/advanced-personalization/monitor/in-depth/ab-test) without having to modify code.

## Next step

Now that you've [prepared your index structure](/doc/guides/personalization/advanced-personalization/configure/prerequisites/index-structure), [event implementation](/doc/guides/personalization/advanced-personalization/configure/prerequisites/event-implementation) and search implementation, Advanced Personalization can build a holistic view of each user's journey and personalize search results accordingly.

You're ready to [configure Advanced Personalization indices](/doc/guides/personalization/advanced-personalization/configure/setup/indices) without additional code changes.
