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

# Send events

> Send a list of events in a single request.

export const Legacy = ({title, href}) => {
  return <Note>

    This page documents an earlier version of the API client.
    For the latest version, see <a href={href}>{title}</a>.

    </Note>;
};

<Legacy title="Send events" href="/doc/libraries/sdk/methods/insights/push-events" />

**Required ACL:** `search`

Sending multiple events in a batch can be useful when:

* Importing historical data
* Sending events through your own servers

You can include up to 1,000 events in a single request.

When you're sending historical events, make sure to **set correct
[timestamps](#param-timestamp)** for all events, or else every event will have
the same timestamp.

For sending real-time events, use the dedicated methods instead:

* [`clickedObjectIDsAfterSearch`](/doc/libraries/sdk/v1/methods/clicked-object-ids-after-search)
* [`convertedObjectIDsAfterSearch`](/doc/libraries/sdk/v1/methods/converted-object-ids-after-search)
* [`addedToCartObjectIDsAfterSearch`](/doc/libraries/sdk/v1/methods/added-to-cart-object-ids-after-search)
* [`purchasedObjectIDsAfterSearch`](/doc/libraries/sdk/v1/methods/purchased-object-ids-after-search)
* [`clickedObjectIDs`](/doc/libraries/sdk/v1/methods/clicked-object-ids)
* [`convertedObjectIDs`](/doc/libraries/sdk/v1/methods/converted-object-ids)
* [`addedToCartObjectIDs`](/doc/libraries/sdk/v1/methods/added-to-cart-object-ids)
* [`purchasedObjectIDs`](/doc/libraries/sdk/v1/methods/purchased-object-ids)
* [`clickedFilters`](/doc/libraries/sdk/v1/methods/clicked-filters)
* [`convertedFilters`](/doc/libraries/sdk/v1/methods/converted-filters)
* [`viewedObjectIDs`](/doc/libraries/sdk/v1/methods/viewed-object-ids)
* [`viewedFilters`](/doc/libraries/sdk/v1/methods/viewed-filters)

For more information, see
[Click and conversion events](/doc/guides/sending-events).

## Examples

The following example sends three events for the same user:
one click event, one view event, and one conversion event.

For more information about initializing the JavaScript Insights client `aa`, see
[Initialize the Insights client](/doc/libraries/search-insights/init).

<CodeGroup>
  ```cs C# theme={"system"}
  var insights = new InsightsClient(
    "YourApplicationID",
    "YourSearchOnlyAPIKey"
  );

  var events = new List<InsightsEvent>(){
    // `clickedObjectIDsAfterSearch`
    new InsightsEvent(
      EventType = "click",
      UserToken = "user-123456",
      EventName = "Example Clicked",
      Index = "YourIndexName",
      ObjectIDs = new List<string>{ "objectID-1", "objectID-2" },
      Positions = new List<uint> { 17, 19 },
      QueryID = "queryID",
      Timestamp = 1771576917
    ),
    // `viewedObjectIDs`
    new InsightsEvent(
      EventType = "view",
      UserToken = "user-123456",
      EventName = "Example Viewed",
      Index = "YourIndexName",
      ObjectIDs = new List<string>{ "objectID-1", "objectID-2" },
      Timestamp = 1771576913;
    ),
    // `convertedObjectIDsAfterSearch`
    new InsightsEvent(
      EventType = "conversion",
      UserToken = "user-123456",
      EventName = "Example Converted",
      Index = "YourIndexName",
      ObjectIDs = new List<string>{ "objectID-1", "objectID-2" },
      QueryID = "queryID",
    )
  };

  insights.sendEventsAsync(events);
  ```

  ```go Go theme={"system"}
  client := insights.NewClient("YourApplicationID", "YourAPIKey")

  events := []insights.Event{
  	// `clickedObjectIDsAfterSearch`
  	{
  		EventType: "click",
  		EventName: "Example Clicked",
  		Index:     "YourIndexName",
  		UserToken: "user-123456",
  		Timestamp: time.Unix(1771576934, 0),
  		ObjectIDs: []string{"objectID-1", "objectID-2"},
  		Positions: []int{17, 19},
  		QueryID:   "queryID",
  	},
  	// `viewedObjectIDs`
  	{
  		EventType: "view",
  		EventName: "Example Viewed",
  		Index:     "YourIndexName",
  		UserToken: "user-123456",
  		Timestamp: time.Unix(1771576941, 0),
  		ObjectIDs: []string{"objectID-1", "objectID-2"},
  	},
  	// `convertedObjectIDsAfterSearch`
  	{
  		EventType: "conversion",
  		EventName: "Example Converted",
  		Index:     "YourIndexName",
  		UserToken: "user-123456",
  		Timestamp: time.Unix(1771576946, 0),
  		ObjectIDs: []string{"objectID-1", "objectID-2"},
  		QueryID:   "queryID",
  	},
  }

  res, err := client.SendEvents(events)
  ```

  ```java Java theme={"system"}
  InsightsClient insights = DefaultInsightsClient.create(
      "YourApplicationID",
      "YourSearchOnlyAPIKey"
  );

  // `clickedObjectIDsAfterSearch`
  InsightsEvent eventClick =
      new InsightsEvent()
        .setEventType("click")
        .setUserToken("user-123456")
        .setEventName("Example Clicked")
        .setIndex("YourIndexName")
        .setObjectIDs(Arrays.asList("objectID-1", "objectID-2"))
        .setPositions(Arrays.asList(17L, 19L))
        .setQueryID("queryID")
        .setTimestamp(1757066975147L);

  // `viewedObjectIDs`
  InsightsEvent eventView =
      new InsightsEvent()
        .setEventType("view")
        .setUserToken("user-123456")
        .setEventName("Example Viewed")
        .setIndex("YourIndexName")
        .setObjectIDs(Arrays.asList("objectID-1", "objectID-2"))
        .setTimestamp(1757066975147L);

  // `convertedObjectIDsAfterSearch`
  InsightsEvent eventConversion =
        new InsightsEvent()
        .setEventType("conversion")
        .setUserToken("user-123456")
        .setEventName("Example Converted")
        .setIndex("YourIndexName")
        .setObjectIDs(Arrays.asList("objectID-1", "objectID-2"))
        .setQueryID("queryID");

  List < InsightsEvent > events = Arrays.asList(eventClick, eventView, eventConversion);
  insights.sendEventsAsync(events);
  ```

  ```js JavaScript theme={"system"}
  // This requires the `search-insights` library version 2.9.0 or later
  aa("sendEvents", [
  	// `clickedObjectIDsAfterSearch`
  	{
  		userToken: "anonymous-123456",
  		authenticatedUserToken: "user-123456",
  		eventType: "click",
  		eventName: "Example Clicked",
  		index: "YourIndexName",
  		queryID: "queryID",
  		objectIDs: ["objectID-1", "objectID-2"],
  		positions: [17, 19],
  	},
  	// `viewedObjectIDs`
  	{
  		userToken: "anonymous-123456",
  		authenticatedUserToken: "user-123456",
  		eventType: "view",
  		eventName: "Example Viewed",
  		index: "YourIndexName",
  		objectIDs: ["objectID-1", "objectID-2"],
  	},
  	// `convertedObjectIDsAfterSearch`
  	{
  		userToken: "anonymous-123456",
  		authenticatedUserToken: "user-123456",
  		eventType: "conversion",
  		eventSubtype: "purchase",
  		eventName: "Example Converted",
  		index: "YourIndexName",
  		objectIDs: ["objectID-1", "objectID-2"],
  		objectData: [
  			{
  				queryID: "object1-query",
  				price: "1.50",
  				quantity: 2,
  			},
  			{
  				queryID: "object2-query",
  				price: "2.00",
  				quantity: 1,
  			},
  		],
  		value: 5.0,
  		currency: "USD",
  	},
  ]);
  ```

  ```kotlin Kotlin theme={"system"}
  val insights =
      ClientInsights(
          applicationID = ApplicationID("YourApplicationID"), apiKey = APIKey("YourSearchOnlyAPIKey"))

  // `clickedObjectIDsAfterSearch`
  val eventClick =
      InsightsEvent.Click(
          eventName = EventName("Example Clicked"),
          indexName = IndexName("YourIndexName"),
          userToken = UserToken("user-123456"),
          timestamp = 1757066975147L,
          queryID = QueryID("queryID"),
          resources =
              InsightsEvent.Resources.ObjectIDs(
                  listOf(ObjectID("objectID-1"), ObjectID("objectID-2"))),
          positions = listOf(17, 19),
      )

  // `viewedObjectIDs`
  val eventView =
      InsightsEvent.View(
          eventName = EventName("Example Viewed"),
          indexName = IndexName("YourIndexName"),
          userToken = UserToken("user-123456"),
          timestamp = 1757066975147L,
          resources =
              InsightsEvent.Resources.ObjectIDs(
                  listOf(ObjectID("objectID-1"), ObjectID("objectID-2"))),
      )

  // `convertedObjectIDsAfterSearch`
  val eventConversion =
      InsightsEvent.Conversion(
          eventName = EventName("Example Converted"),
          indexName = IndexName("YourIndexName"),
          userToken = UserToken("user-123456"),
          timestamp = 1757066975147L,
          queryID = QueryID("queryID"),
          resources =
              InsightsEvent.Resources.ObjectIDs(
                  listOf(ObjectID("objectID-1"), ObjectID("objectID-2"))),
      )

  insights.sendEvents(events = listOf(eventClick, eventView, eventConversion))
  ```

  ```php PHP theme={"system"}
  $insights = Algolia\AlgoliaSearch\InsightsClient::create(
      'YourApplicationID',
      'YourSearchOnlyAPIKey'
  );

  $response = $insights->sendEvents(array(
          // `clickedObjectIDsAfterSearch`
          array(
              'eventType' => 'click',
              'eventName' => 'Example Clicked',
              'index' => 'YourIndexName',
              'userToken' => 'user-123456',
              'objectIDs' => array('objectID-1', 'objectID-2'),
              'timestamp' => 1757066975147,
              'queryID' => 'queryID'
          ),
          // `viewedObjectIDs`
          array(
              'eventType' => 'view',
              'eventName' => 'Example Viewed',
              'index' => 'YourIndexName',
              'userToken' => 'user-123456',
              'objectIDs' => array('objectID-1', 'objectID-2'),
              'timestamp' => 1757066975147
          ),
          // `convertedObjectIDsAfterSearch`
          array(
              'eventType' => 'conversion',
              'eventName' => 'Example Converted',
              'index' => 'YourIndexName',
               'userToken' => 'user-123456',
              'objectIDs' => array('objectID-1', 'objectID-2'),
              'timestamp' => 1757066975147,
              'queryID' => 'queryID'
          ),
        )
  );
  ```

  ```python Python theme={"system"}
  insights = InsightsClient.create(
      "YourApplicationID",
      "YourSearchOnlyAPIKey",
  )

  insights.send_events(
      [
          {
              "eventType": "click",
              "eventName": "Example Clicked",
              "index": "YourIndexName",
              "userToken": "user-123456",
              "timestamp": 1757066975147,
              "objectIDs": ["objectID-1", "objectID-2"],
              "queryID": "queryID",
              "positions": [17, 19],
          },
          {
              "eventType": "view",
              "eventName": "Example Viewed",
              "index": "YourIndexName",
              "userToken": "user-123456",
              "timestamp": 1757066975147,
              "objectIDs": ["objectID-1", "objectID-2"],
          },
          {
              "eventType": "conversion",
              "eventName": "Example Converted",
              "index": "YourIndexName",
              "userToken": "user-123456",
              "timestamp": 1757066975147,
              "objectIDs": ["objectID-1", "objectID-2"],
              "queryID": "queryID",
          },
      ],
  )
  ```

  ```ruby Ruby theme={"system"}
  insights = Algolia::Insights::Client.create("YourApplicationID", "YourSearchOnlyAPIKey")

  insights.send_events(
    [
      {
        eventType: "click",
        eventName: "Example Clicked",
        index: "YourIndexName",
        userToken: "user-123456",
        timestamp: 1757066975147,
        objectIDs: ["objectID-1", "objectID-2"],
        queryID: "queryID",
        positions: [17, 19]
      },
      {
        eventType: "view",
        eventName: "Example Viewed",
        index: "YourIndexName",
        userToken: "user-123456",
        timestamp: 1757066975147,
        objectIDs: ["objectID-1", "objectID-2"]
      },
      {
        eventType: "conversion",
        eventName: "Example Converted",
        index: "YourIndexName",
        userToken: "user-123456",
        timestamp: 1757066975147,
        objectIDs: ["objectID-1", "objectID-2"],
        queryID: "queryID"
      }
    ]
  )
  ```

  ```scala Scala theme={"system"}
  client.execute {
    val eventClick = InsightsEvent(
      eventType = "click",
      eventName = "Example Clicked",
      index = "YourIndexName",
      userToken = "user-123456",
      objectIDs = Some(Seq("objectID-1", "objectID-2")),
      positions = Some(Seq(17, 19)),
      queryID = Some("queryID"),
      timestamp = Some(1757066975147L))

    val eventView = InsightsEvent(
      eventType = "view",
      eventName = "Example Viewed",
      index = "YourIndexName",
      userToken = "user-123456",
      objectIDs = Some(Seq("objectID-1", "objectID-2")),
      timestamp = Some(1757066975147L))

    val eventConversion = InsightsEvent(
      eventType = "conversion",
      eventName = "Example Converted",
      index = "YourIndexName",
      userToken = "user-123456",
      objectIDs = Some(Seq("objectID-1", "objectID-2")),
      queryID = Some("queryID"),
      timestamp = Some(1757066975147L))

    send events Seq(eventClick, eventView, eventConversion)
  }
  ```

  ```swift Swift theme={"system"}
  let insightsClient = InsightsClient(appID: "YourApplicationID", apiKey: "YourSearchOnlyAPIKey")

  // `clickedObjectIDsAfterSearch`
  let eventClick: InsightsEvent = .click(
    eventName: "Example Clicked",
    indexName: "YourIndexName",
    userToken: "user-123456",
    queryID: "queryID",
    objectIDsWithPositions: [
      ("objectID-1", 17),
      ("objectID-2", 19),
    ])

  // `viewedObjectIDs`
  let eventView: InsightsEvent = .view(
    eventName: "Example Viewed",
    indexName: "YourIndexName",
    userToken: "user-123456",
    objectIDs: [
      "objectID-1",
      "objectID-2",
    ])

  // `convertedObjectIDsAfterSearch`
  let eventConversion: InsightsEvent = .conversion(
    eventName: "Example Converted",
    indexName: "YourIndexName",
    userToken: "user-123456",
    queryID: "queryID",
    objectIDs: [
      "objectID-1",
      "objectID-2",
    ])

  let events = [eventClick, eventView, eventConversion]

  insightsClient.sendEvents(events) { result in
    if case .success(let response) = result {
      print("Response: \(response)")
    }
  }
  ```
</CodeGroup>

## Parameters

<ParamField body="events" type="object[]" required>
  An array of event objects

  <Expandable>
    <ParamField body="eventName" type="string" required>
      Name of the specific event.

      **Format:** 1-64 ASCII characters, except control characters.

      To maximize the impact of your events, use consistent event names and consistent
      formatting, for example, "Product Added To Cart" (always in title case).

      For example, you can adopt Twilio Segment's
      [object-action framework](https://segment.com/academy/collecting-data/naming-conventions-for-clean-data/#the-object-action-framework).
    </ParamField>

    <ParamField body="eventType" type="enum<string>" required>
      Type of the event:
      `click`, `conversion`, or `view`.

      See also:
      [Event types](/doc/guides/sending-events/concepts/event-types)
    </ParamField>

    <ParamField body="index" type="string" required>
      Name of the Algolia index.

      **Format**:
      same as the index name used by the search engine.
    </ParamField>

    <ParamField body="userToken" type="string" required>
      Anonymous user identifier.

      See also:
      [User token](/doc/guides/sending-events/concepts/usertoken)
    </ParamField>

    <ParamField body="authenticatedUserToken" type="string">
      Pseudonymous identifier for authenticated users.

      <Warning>
        Don't include personally identifiable information in user tokens.
      </Warning>

      See also:
      [User token](/doc/guides/sending-events/concepts/usertoken)
    </ParamField>

    <ParamField body="currency" type="string">
      **PHP, Ruby, JavaScript, Python only:** If you include pricing information in
      the `objectData` parameter or provide `value`, you must also specify the
      currency as ISO-4217 currency code, such as USD or EUR.
    </ParamField>

    <ParamField body="eventSubtype" type="addToCart | purchase">
      **PHP, Ruby, JavaScript, Python, Go only:** Subtype of a conversion event
      (`eventType:
            conversion`).
      Either `addToCart` or `purchase`.
      For other event types, this should be omitted.

      This lets Algolia provide more detailed analytics reports.
    </ParamField>

    <ParamField body="filters" type="string[]">
      List of facet filters.

      You can include up to 10 filters.

      **Format:** `${attribute}:${value}`—for example, `brand:apple`.
      Both the `attribute` and `value` in each facet filter must be
      [URL-encoded](https://developer.mozilla.org/en-US/docs/Glossary/Percent-encoding)
      individually and separated by a `:`, such as, `"discount:10%25"`.

      A single event **must not** include both `objectIDs` and `filters`.
    </ParamField>

    <ParamField body="objectData" type="object[]">
      **PHP, Ruby, JavaScript, Python, Kotlin only:** Extra information about the
      records involved in the event, for example, price and quantities of purchased
      products.

      If provided, must be the same length as `objectIDs`.

      If you include pricing information, you must also specify the `currency`
      parameter.
    </ParamField>

    <ParamField body="objectIDs" type="string[]">
      List of object IDs for items of an Algolia index.

      You can include up to 20 object IDs.

      A single event **must not** include both `objectIDs` and `filters`.
    </ParamField>

    <ParamField body="positions" type="string[]">
      Positions of the clicked objects in the search results.
      This property is required for **click events** with `queryID`.
      The first search result has a position of 1.

      You must provide one `position` for each `objectID`.

      Algolia uses this parameter to calculate the
      [average click position](/doc/guides/search-analytics/concepts/metrics#click-position).

      The position is absolute, and not relative, to any results page.
      For example, if there are 10 results per page, the position of the third record
      of the second results page is 13.
      Since [`page`](/doc/api-reference/api-parameters/page) starts at 0, you can use
      the following formula:
      `$positionOnPage + $page * hitsPerPage`.

      If you're using InstantSearch, you can get the position through the
      `hit.__position` attribute.
    </ParamField>

    <ParamField body="timestamp" type="integer">
      Time of the event in milliseconds since the
      [Unix epoch](https://en.wikipedia.org/wiki/Unix_time).
      By default, the Insights API uses the time it receives an event as its
      timestamp.

      If you're not sending events in real time, for example, if you're doing
      **backend search**, it's important to set correct timestamps.
      If you're sending events in batches and you're not including a timestamp, all
      events will have the same timestamp.

      * Timestamps may be up to 4 days in the past.
      * For **events with query ID**:
        timestamps must be within 1 hour of the corresponding search or browse
        requests.
    </ParamField>

    <ParamField body="value" type="number | string">
      **PHP, Ruby, JavaScript, Python only:** The monetary value of the event,
      measured in `currency`.
      For example, the total value of a purchase.

      If you assign a `value`, you must also specify the `currency` parameter.

      Must be a decimal number with no more than 16 characters (including non-digit
      characters).
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="additionalParams" type="object">
  **JavaScript only:** Additional parameters for the `search-insights` library.

  **Example:**

  ```js JavaScript icon=code theme={"system"}
  aa(
  	"sendEvents",
  	[
  		// …
  	],
  	{
  		headers: {
  			"X-Algolia-Application-Id": "YourApplicationID",
  			"X-Algolia-API-Key": "YourSearchOnlyAPIKey",
  		},
  		inferQueryID: true,
  	},
  );
  ```

  <Expandable>
    <ParamField body="headers" type="object">
      Additional headers you want to add to the request as key-value pairs.
      For example, you can add your credentials as headers, which lets multiple
      clients use different credentials for every request.
    </ParamField>

    <ParamField body="inferQueryID" type="boolean">
      Whether to infer the query ID for conversion events from previous click events.
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="discount" type="number | string">
  Absolute value of the discount in effect for this object, measured in
  `currency`.

  Must be a decimal number with no more than 16 characters (including non-digit
  characters).
</ParamField>

<ParamField body="price" type="number | string">
  The price of the item.
  This should be the final price, including any discounts.

  Must be a decimal number with no more than 16 characters (including non-digit
  characters).
</ParamField>

<ParamField body="quantity" type="number">
  The quantity of the purchased or added-to-cart item.
  The total value of a purchase is the sum of `quantity` multiplied by the `price`
  of each purchased item.
</ParamField>

<ParamField body="queryID" type="string">
  ID of the query that this specific record is attributable to.
  Used to track purchase events with multiple items originating from different
  searches.

  Objects without a query ID aren't included in revenue analytics.
  For more information, see
  [Revenue transactions](/doc/guides/search-analytics/concepts/query-aggregation#revenue-transactions).

  See also:
  [Keep track of query IDs](/doc/guides/sending-events/guides/queryid)
</ParamField>
