> For the complete documentation index, see [llms.txt](https://docs.fact-finder.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.fact-finder.com/webcomponents-overview/api/more-features/recently-viewed.md).

# Recently Viewed

Recently Viewed records product visits in browser storage and displays the latest entries. Use \`ff-recently-viewed\` with the JavaScript API to track views.

## Documentation

The Recently Viewed component enables you to display the products that a user has visited most recently.

It works entirely in the **browser** using `localStorage` and therefore requires no special backend setup. **Click tracking**, etc., is built-in as you are used to from other components.

```html
<ff-recently-viewed>
    <ff-record-list>
        ...
    </ff-record-list>
</ff-recently-viewed>
```

The component:

* Shows entries in the order they were visited, starting from the most recent.
* Removes duplicates.
* Does not show the product currently being viewed.
* Displays up to four items by default.
* Allows you to configure the number of displayed items on a per-component basis.

## Integration

The integration of Recently Viewed consists of **two parts**:

* A JavaScript part to **record** the user's view history and configure the feature.
* An HTML part to **visualize** the most recently viewed products.

{% stepper %}
{% step %}

## Configure and record the current product on the product detail page

On the product page, add the product details to the Recently Viewed history by calling `factfinder.components.recentlyViewed.addEntry(flatRecord)`.

`flatRecord` is a plain object of keys and values that represent the product data. The FactFinder API calls this format `FlatRecord`.

```js
document.addEventListener(`ffCoreReady`, ({ factfinder, init }) => {
    // Web Components initialization as usual.
    init({
        ff: { ... },  // Your FactFinder instance configuration.

        appConfig: {
            fieldRoles: { ... },  // Field roles are required for tracking.
        },
    });

    // Configuration is optional. If not provided, default values are as shown below.
    factfinder.components.recentlyViewed.config({

        // Maximum number of items stored in history.
        maxLength: 12,

        // Storage target. "local" for `localStorage`, "session" for `sessionStorage`.
        storage: `local`,
    });

    // The data provided here will become accessible in ff-recently-viewed's HTML template.
    factfinder.components.recentlyViewed.addEntry({
        // Field names must align with your datafeed.
        Title: `The Product`,
        ArticleNumber: `123-456`,
        Price: 1.99,
        ...
    });
});
```

### Adding the current product

Calling `addEntry` adds the entry to the top of the history, removes duplicates, and remembers it as the "currently viewed" item for the current page context. It also discards items from the history that exceed `maxLength`.

If you have an `ff-recently-viewed` element on the product page, the newly added item will not appear in the list yet. Only if you navigate to another page that doesn't call `addEntry` or calls it with a different product.

### Configuration

The call to `config` offers you two options.

`maxLength` defines the maximum number of entries the Recently Viewed history can store. When the limit is exceeded, the oldest entries are automatically discarded.

* **Default**: `12` (applies if not explicitly set)
* **Required for**: `addEntry()` operations
* **Not required for**: Reading the history

Only set `maxLength` if you are adding entries. Reading the history does not depend on this value.

{% hint style="info" %}
`maxLength` does not control the number of items shown in `ff-recently-viewed`.

That value is set individually per `ff-recently-viewed` instance. Ensure `maxLength` is no less than the largest item count used across all instances.
{% endhint %}

## API

### `ff-recently-viewed`

#### Properties

| Name                                    | Description                                                                                                   |
| --------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
| **max-results** (Number) (default: `4`) | The maximum number of displayed items.                                                                        |
| **wait-for-update** (Boolean)           | Use on a **product detail page**. The element waits for `addEntry()` to identify and exclude the viewed item. |

#### Methods

| Name                    | Description                                                                              |
| ----------------------- | ---------------------------------------------------------------------------------------- |
| **getRecentlyViewed()** | Refreshes recently viewed products. Use it after clearing history without a page reload. |

`storage` defines whether the Recently Viewed history is stored in the browser's `localStorage` or `sessionStorage`. Use values `"local"` or `"session"` accordingly. **Default** is `localStorage`.

Unless you choose to use `sessionStorage`, you never have to set this value. If you do, you have to configure it on every page that uses Recently Viewed because the configuration itself is not preserved across page contexts. Changing it does **not** move a previously recorded history to the new storage.
{% endstep %}

{% step %}

## Visualize products on the product detail page

To visualize the Recently Viewed products, use the `ff-recently-viewed` element.

Use the `wait-for-update` attribute on the product page. This attribute tells `ff-recently-viewed` to wait for the `addEntry` call so it may correctly identify the currently viewed product and exclude it from visualization.

```html
<!-- [wait-for-update] is required on the product page. It prevents a race condition with the JS API. -->
<ff-recently-viewed wait-for-update>

    <!-- You may define additional HTML that is shown together with the history. -->
    <h3>Recently viewed:</h3>

    <ff-record-list subscribe="false">
        <template data-role="record">
            <ff-record>
                ...
            </ff-record>
        </template>
    </ff-record-list>
</ff-recently-viewed>
```

For details on how to set up the nested record list, see [ff-record-list](/webcomponents-overview/api/basic-elements/record-list.md).
{% endstep %}

{% step %}

## Visualize products on non-product detail pages

On non-product pages, you typically only need the `ff-recently-viewed` element.

```html
<!-- [max-results] is optional. Its default value is 4. -->
<ff-recently-viewed max-results="6">
    <ff-record-list subscribe="false">
        <template data-role="record">
            <ff-record>
                ...
            </ff-record>
        </template>
    </ff-record-list>
</ff-recently-viewed>
```

The `max-results` attribute allows you to configure up to how many items this particular component shall display. You can have multiple `ff-recently-viewed` elements on the page, each with a different `max-results` setting.
{% endstep %}
{% endstepper %}

## Remember to define field roles

For the tracking from `ff-recently-viewed` (or any other component) to work, the Web Components application must know your FactFinder's field roles configuration.

While the field roles do appear in search, suggest, and other types of responses, these responses have to be triggered before Web Components can pick them up. Certain pages such as the product detail page, the shopping cart page, etc., do not typically interact with FactFinder before a user clicks on a recently viewed product.

It is therefore **best practice** to always specify them explicitly during initialization.

```js
document.addEventListener(`ffCoreReady`, ({ factfinder, init }) => {
    init({
        ff: { ... },  // Your FactFinder instance configuration.

        appConfig: {
            fieldRoles: { ... },  // Always explicitly define field roles.
        },
    });
});
```

## JavaScript API

The related JavaScript API can be found in the `factfinder.components.recentlyViewed` namespace.

### `config(options)`

Calling `config` is optional and only required if you want to override the default values.

`options` has two optional fields:

| Name        | Type    | Default   | Description                                                             |
| ----------- | ------- | --------- | ----------------------------------------------------------------------- |
| `maxLength` | Integer | `12`      | Maximum number of items stored in history.                              |
| `storage`   | String  | `"local"` | Either `"local"` or `"session"` for `localStorage` or `sessionStorage`. |

### `addEntry(flatRecord)`

Call `addEntry` on product pages.

`flatRecord` corresponds to the `FlatRecord` data type defined in the FactFinder API specification. It is a flat object where the keys are the product's field names from your data feed, and the values are the related values.

Adding an entry removes duplicates and places the added entry at the top of the view history. Calling `addEntry` also marks the added entry as the current entry, allowing it to be excluded from visualization. Always call it with every product page load. There is no need to distinguish first-time visits and page reloads.

### `getEntries() => [Object]`

Returns an array of all stored entries.

It does **not** return the entry most recently added via `addEntry` within the current page session.

You only need this function if you want to visualize the view history yourself.

### `getEntriesAfterUpdate() => Promise<[Object]>`

The same as `getEntries`, but it returns a *Promise* that resolves once `addEntry` was called. It is only required on product pages.

This function is necessary during page loading in order to avoid race conditions when the call order of `addEntry` and `getEntries` cannot be guaranteed. If `getEntries` is called before `addEntry`, the *current* entry cannot be determined and all entries would be returned and subsequently displayed.

You only need this function if you want to visualize the view history yourself.

### `clear()`

Clears the view history.

{% hint style="warning" %}
Visual components are not automatically updated.
{% endhint %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.fact-finder.com/webcomponents-overview/api/more-features/recently-viewed.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
