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

# insights

> Middleware for setting the user token and sending click and conversion events to the Insights API.

<Note>
  This is the **React InstantSearch v7** documentation.
  If you're upgrading from v6, see the [upgrade guide](/doc/guides/building-search-ui/upgrade-guides/react/#migrate-from-react-instantsearch-v6-to-react-instantsearch-v7).
  If you were using React InstantSearch Hooks,
  this v7 documentation applies—just check for [necessary changes](/doc/guides/building-search-ui/upgrade-guides/react/#migrate-from-react-instantsearch-hooks-to-react-instantsearch-v7).
  To continue using v6, you can find the [archived documentation](https://algolia.com/old-docs/deprecated/instantsearch/react/v6/api-reference/instantsearch/).
</Note>

```tsx Signature theme={"system"}
const middleware = createInsightsMiddleware({
  // Optional parameters
  insightsClient?: InsightsClient | null,
  insightsInitParams?: object,
  onEvent?: function,
})
```

## Import

```js JavaScript icon=code theme={"system"}
import { createInsightsMiddleware } from "instantsearch.js/es/middlewares";
```

## About this middleware

<Note>
  You can use [`<InstantSearch insights={true}>`](/doc/api-reference/widgets/instantsearch/react#param-insights)
  instead of setting up the Insights middleware yourself.
</Note>

The `createInsightsMiddleware` creates an insights middleware to help you achieve the following:

1. Set the `userToken` for insights purposes (Analytics, Personalization, etc.).
2. Automatically send events from built-in widgets. You can turn this off if needed.
3. Send events from your own custom widgets.

### Requirements

* [`search-insights`](https://github.com/algolia/search-insights.js) v1.6.2 or later.

See also: [Send click and conversion events with React InstantSearch](/doc/guides/building-search-ui/events/react)

## Examples

```jsx JavaScript icon=code theme={"system"}
import { createInsightsMiddleware } from "instantsearch.js/es/middlewares";
import { useInstantSearch } from "react-instantsearch";
import { useLayoutEffect } from "react";
import { liteClient as algoliasearch } from "algoliasearch/lite";

function InsightsMiddleware() {
  const { addMiddlewares } = useInstantSearch();

  useLayoutEffect(() => {
    const middleware = createInsightsMiddleware({
      insightsClient: window.aa,
    });

    return addMiddlewares(middleware);
  }, [addMiddlewares]);

  return null;
}

const searchClient = algoliasearch("YourApplicationID", "YourSearchOnlyAPIKey");

function App() {
  return (
    <InstantSearch indexName="instant_search" searchClient={searchClient}>
      {/* ... */}
      <InsightsMiddleware />
    </InstantSearch>
  );
}
```

## Options

<ParamField body="insightsClient" type="InsightsClient | null">
  The [Insights client](/doc/libraries/search-insights?client=javascript) is used to send events.
  It synchronizes the [user token](/doc/guides/sending-events/concepts/usertoken#exclude-users-who-want-to-opt-out-of-analytics-recommend-and-personalization) between search and analytics calls.

  To disable `userToken` synchronization and automatic event sending, set this to `null`.

  ```jsx JavaScript icon=code theme={"system"}
  const middleware = createInsightsMiddleware({
    insightsClient: aa,
  });

  const userToken = // Get the user token (synchronously or asynchronously).
    // The `insights` middleware receives a notification
    // and attaches the `userToken` to search calls onwards.
    aa("setUserToken", userToken);
  ```
</ParamField>

<ParamField body="insightsInitParams" type="object">
  Insights parameters to forward to the Insights client's [`init`](/doc/libraries/search-insights/init) method.

  With `search-insights >= v1.7.0 and < 2.0.0`,
  the Insights client accepts `useCookie` and `userToken` parameters in the [`init`](/doc/libraries/search-insights/init) method.
  You can pass `useCookie: false` to prevent the usage of cookies to store an anonymous `userToken`.
  You can also pass a custom `userToken` while creating `insights` middleware, if you have one.

  With `search-insights >= 2.0.0`, the default value of `useCookie` is `false`.

  <Note>
    You can set an authenticated user token and a user token in `insightsInitParams`.
    Both tokens are passed to the Insights API for sending events.
    If both are set, InstantSearch uses the authenticated user token for search queries.
  </Note>

  <CodeGroup>
    ```jsx Cookie theme={"system"}
    createInsightsMiddleware({
      insightsInitParams: {
        useCookie: true,
      },
    });
    ```

    ```jsx Tokens theme={"system"}
    createInsightsMiddleware({
      insightsInitParams: {
        userToken: "user-token",
        authenticatedUserToken: "auth-user-token",
      },
    });
    ```
  </CodeGroup>
</ParamField>

<ParamField body="onEvent" type="(event: InsightsEvent, aa: null | InsightsClient) => void" default="undefined">
  By default, the middleware sends events to Algolia using the provided `insightsClient`.
  You can also control events and send them yourself by implementing an `onEvent` method for the middleware to call instead.
  This method lets you access data and filter or modify the payload.
  You can also use it to send events to third-party trackers.

  If you want to use `onEvent` to send events to third-party trackers,
  but don't want to send them to Algolia,
  you can set `insightsClient` to `null`,
  and you don't need the `search-insights` library in your application.

  <Expandable title="event properties">
    <ParamField body="event.insightsMethod" type="string">
      The Insights method, such as, `'viewedObjectIDs'`, `'clickedObjectIDsAfterSearch'`.
      For more information, see the [Insights API reference](/doc/libraries/search-insights).
    </ParamField>

    <ParamField body="event.payload" type="[key: string]: any">
      Event payload.
    </ParamField>

    <ParamField body="event.widgetType" type="string">
      Widget type given by connectors, such as `'ais.refinementList` or `'ais.hits`.
    </ParamField>

    <ParamField body="event.eventType" type="string">
      Event type, such as `'view'`, `'click'`, `'conversion'`, or anything else if you customized it.
    </ParamField>
  </Expandable>

  ```jsx JavaScript icon=code theme={"system"}
  createInsightsMiddleware({
    insightsClient: window.aa,
    onEvent: (event, aa) => {
      const { insightsMethod, payload, widgetType, eventType } = event;

      // Send the event to Algolia
      if (insightsMethod) {
        aa(insightsMethod, payload);
      }

      // Send the event to a third-party tracker
      if (widgetType === "ais.hits" && eventType === "click") {
        thirdPartyTracker.send("Product Clicked", payload);
      }
    },
  });
  ```
</ParamField>

## Custom events

Many InstantSearch connectors expose the `sendEvent` method,
which you can use for sending custom events from your custom widgets.

Here's a list of connectors that expose `sendEvent` and they're exposed at the default slot of corresponding React InstantSearch components.

* [`useHierarchicalMenu`](/doc/api-reference/widgets/hierarchical-menu/react#hook)
* [`useHits`](/doc/api-reference/widgets/hits/react#hook)
* [`useInfiniteHits`](/doc/api-reference/widgets/infinite-hits/react#hook)
* [`useMenu`](/doc/api-reference/widgets/menu/react#hook)
* [`useNumericMenu`](/doc/api-reference/widgets/numeric-menu/react) \*
* [`useRange`](/doc/api-reference/widgets/range-input/react#hook) \*
* [`useRefinementList`](/doc/api-reference/widgets/refinement-list/react#hook)
* [`useToggleRefinement`](/doc/api-reference/widgets/toggle-refinement/react#hook)

<Note>
  \* The `sendEvent` method provided to `useNumericMenu` and `useRange` can't be used to send [clicked filter](/doc/libraries/sdk/v1/methods/clicked-filters) events.
</Note>

```jsx JavaScript icon=code theme={"system"}
function Hits() {
  const { items, sendEvent } = useHits();

  return (
    <ol>
      {items.map((item) => (
        <li key={item.objectID}>
          <p>{item.name}</p>
          <button
            type="button"
            onClick={() => sendEvent("click", item, "Item Starred")}
          >
            Star
          </button>

          <button
            type="button"
            onClick={() => sendEvent("conversion", item, "Item Ordered")}
          >
            Order
          </button>
        </li>
      ))}
    </ol>
  );
}
```
