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

# Label and boost purchased items in search results

> Learn how to label and boost previously purchased items in search results.

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

Enhancing search results with labels for previously purchased items creates a more personalized and relevant user experience. This guide demonstrates how to implement a "Purchased" badge and prioritize these items in search results, helping users quickly identify products they've already bought.

Implementing this aspect of the Advanced Personalization feature offers several advantages:

* Lets users identify items for potential repurchase or review
* Prevents accidental repurchases by reminding users of previous purchases
* Guides users to related or updated versions of products they've bought before
* Potentially increases customer loyalty and repeat purchases

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

## Before you begin

This guide assumes that you're familiar with [React InstantSearch](/doc/guides/building-search-ui/getting-started/react)
and that you have access to user purchase history data.

## Preview

<Frame caption="Storefront displaying labeled purchased items in search results">
  <img src="https://mintcdn.com/algolia/aN8Lr52w2iijNnTe/images/guides/advanced-personalization/boost-purchased-items.png?fit=max&auto=format&n=aN8Lr52w2iijNnTe&q=85&s=8289bba26933dac3b13cb6d78304b133" alt="Storefront displaying labeled purchased items in search results" width="1440" height="1292" data-path="images/guides/advanced-personalization/boost-purchased-items.png" />
</Frame>

## Provide purchase history data

Start with the purchase history as an array of objects,
ordered by purchase date in descending order:

```js JavaScript icon=code theme={"system"}
const purchaseHistory = [
  { objectID: "3433069", date: "2024-09-10T08:56:22.062Z" },
  { objectID: "8918056", date: "2024-08-28T08:23:58.987Z" },
];
```

This structure lets you look up purchase dates by `objectID`,
the unique identifier used in your Algolia <Index /> for each product.

Pass this data to the search component:

```jsx React icon=code theme={"system"}
function App() {
  return <SearchPage purchaseHistory={purchaseHistory} />;
}
```

## Display a badge for purchased items

To display a badge for purchased items,
modify the search results by adding a custom attribute to each hit.
This information allows to label items in your search results.

Create a `SearchPage` component that handles the InstantSearch setup:

```jsx React icon=code theme={"system"}
import algoliasearch from "algoliasearch/lite";
import { InstantSearch, Hits } from "react-instantsearch";

const searchClient = algoliasearch("ALGOLIA_APPLICATION_ID", "ALGOLIA_SEARCH_API_KEY");

function SearchPage({ purchaseHistory }) {
  const purchaseDateByObjectID = purchaseHistory.reduce((acc, current) => {
    if (current.date && !acc[current.objectID]) {
      acc[current.objectID] = current.date;
    }
    return acc;
  }, {});

  return (
    <InstantSearch searchClient={searchClient} indexName="instant_search">
      <Hits
        transformItems={(items) =>
          items.map((item) => ({
            ...item,
            __lastPurchasedAt: purchaseDateByObjectID[item.objectID] || null,
          }))
        }
        hitComponent={Hit}
      />
    </InstantSearch>
  );
}
```

This component:

1. Creates a lookup object (`purchaseDateByObjectID`) to look up purchase dates.
2. Uses the [`transformItems`](/doc/api-reference/widgets/hits/react#param-transform-items) prop of the [`Hits`](/doc/api-reference/widgets/hits/react)
   component to add a custom `__lastPurchasedAt` attribute to each hit.
3. Specifies a custom `Hit` component to render each search result.

Next, create the custom `Hit` component to display the badge:

```jsx React icon=code theme={"system"}
function Hit({ hit }) {
  return (
    <article>
      <h1>{hit.name}</h1>
      <HitPurchasedBadge hit={hit} />
    </article>
  );
}

const shortMonthYearFormatter = new Intl.DateTimeFormat("en-US", {
  year: "numeric",
  month: "short",
});

function HitPurchasedBadge({ hit }) {
  if (!hit.__lastPurchasedAt) {
    return null;
  }

  const purchaseDate = new Date(hit.__lastPurchasedAt);
  const formattedDate = shortMonthYearFormatter.format(purchaseDate);

  return <span>Purchased {formattedDate}</span>;
}
```

The `HitPurchasedBadge` component:

1. Checks if the item has been purchased (has a `__lastPurchasedAt` value).
2. If purchased, it formats the date and displays the "Purchased" badge.
3. If not purchased, it renders nothing.

## Optional: re-rank results based on purchase date

To prioritize purchased items in the search results,
you can implement a custom sorting function.
This step can enhance the user experience by bringing previously purchased items to the top of the results.

Implement a custom sorting function:

```js JavaScript icon=code theme={"system"}
function sortItemsByPurchaseDate(items, purchaseDateByObjectID) {
  return [...items].sort((itemA, itemB) => {
    const isItemAPurchased = Boolean(purchaseDateByObjectID[itemA.objectID]);
    const isItemBPurchased = Boolean(purchaseDateByObjectID[itemB.objectID]);

    if (isItemAPurchased === isItemBPurchased) {
      return 0;
    }

    if (isItemAPurchased) {
      return -1;
    } else {
      return 1;
    }
  });
}
```

Update the `SearchPage` component to use this sorting function:

```jsx React icon=code theme={"system"}
function SearchPage({ purchaseHistory }) {
  const purchaseDateByObjectID = purchaseHistory.reduce((acc, current) => {
    if (current.date && !acc[current.objectID]) {
      acc[current.objectID] = current.date;
    }
    return acc;
  }, {});

  return (
    <InstantSearch searchClient={searchClient} indexName="instant_search">
      <Hits
        transformItems={(items) =>
          sortItemsByPurchaseDate(
            items.map((item) => ({
              ...item,
              __lastPurchasedAt: purchaseDateByObjectID[item.objectID] || null,
            })),
            purchaseDateByObjectID,
          )
        }
        hitComponent={Hit}
      />
    </InstantSearch>
  );
}
```

Be cautious not to over-prioritize purchased items,
as this might hide relevant new items from the user.
