---
title: Improvements with tracking
slug: commerce-connect-14/docs/improvements-with-tracking
docTags: 
createdAt: 2026-07-23T10:25:33.704Z
---

Previously, client browser calls to the Product Recommendation service directly with data were created on the server side, and the cuid/sessionid were included in the data. This created two problems when the rendered page got cached:

- The wrong tracking data was sent to Product Recommendations (formerly Perform). The call repeated what was rendered the first time, even though the page might have been served to a different user from cache.
- After the first time, no tracking was sent to Profile Store, as it occurs on the server and was not triggered when the page was cached.

The client-side API was rewritten to be more full-featured, like the server side APIs: creating different types of tracking requests and populating them with data. Instead of calling to Recommendation directly, JS APIs call to Proxy. The Proxy is an asynchronous webapi controller that handles tracking request from Js APIs and forwards requests to the Product Recommendation service.

You can use JS Tracking APIs and Server Tracking APIs in parallel. On the client side, you can use JS `TrackingDataFactory` to create tracking data and epiRecommendations to send tracking requests to the Proxy. On the server side, you can use Tracking APIs, or `TrackingAttribute` for short.

## Changes to support the rewriting of the Client APIs

### TrackingMode

:::hint{type="info"}
**Note**

`TrackingMode` is obsolete.
:::

As mentioned above, Js Tracking APIs and Server tracking APIs are independent and work in parallel.

### epiRecommendations

`epiRecommendations` support setting scope when sending tracking data.

```javascript
track(trackingData, scope, onSuccess, callbackOptions)
```

### JavaScript TrackingDataFactory

The `TrackingDataFactory` class creates JavaScript tracking data, which is sent to the Proxy. The following methods are available to create `TrackingData`.

| Method                            | Example                                                                          |
| --------------------------------- | -------------------------------------------------------------------------------- |
| Create Home tracking data         | `TrackingDataFactory.createHomeTrackingData()`                                   |
| Create Product tracking data      | `TrackingDataFactory.createProductTrackingData(productCode)`                     |
| Create SearchResult tracking data | `TrackingDataFactory.createSearchResultTrackingData(term, productCodes)`         |
| Create Checkout tracking data     | `TrackingDataFactory.createCheckoutTrackingData()`                               |
| Create Basket tracking data       | `TrackingDataFactory.createBasketTrackingData()`                                 |
| Create Order tracking data        | `TrackingDataFactory.createOrderTrackingData(orderId)`                           |
| Create Brand tracking data        | `TrackingDataFactory.createBrandTrackingData(brandName)`                         |
| Create Category tracking data     | `TrackingDataFactory.createCategoryTrackingData(categoryCode)`                   |
| Create Attribute tracking data    | `TrackingDataFactory.createAttributeTrackingData(attributeName, attributeValue)` |
| Create Wishlist tracking data     | `TrackingDataFactory.createWishlistTrackingData()`                               |

### The proxy

The Proxy has only one endpoint to handle tracking requests sent from the client.

- Endpoint url:  `episerverapi/commercetracking/track`
- Method: `POST`

### Handling recommendationId

In server-side mode, Optimizely uses cookies for handles. In client-side mode, Optimizely uses `QueryString` to handle `RecommendationId`.

- When *clicking* a product from a Recommendation, Optimizely passes the `RecommendationId` to the `QueryString`.
- When *viewing* a product, `TrackingDataFactory` gets `RecommendationId` from `QueryString` (if any), and sends the tracking request to the Proxy.
