Documentation
Feedback
Guides
API Reference

Guides
Guides
Recommendations

Integrating product recommendations in headless or FastStore web stores (Beta)

Learn how to integrate product recommendations in headless and FastStore web storefronts using the Recommendations BFF API and Activity Flow.

This feature is in beta, and we are actively working to improve it. If you have questions about enablement, account configuration, or campaigns, please contact our Support.

This guide explains how to integrate product recommendations in headless or FastStore web stores using the VTEX Recommendations BFF API.

{"base64":"  ","img":{"width":1504,"height":496,"type":"gif","mime":"image/gif","wUnits":"px","hUnits":"px","length":3351718,"url":"https://vtexhelp.vtexassets.com/assets/docs/src/shelf-recommendation___403f15739cf14318a5b9ad8f16582d71.gif"}}

Before you begin

Before implementing recommendations in a headless or FastStore web store, make sure you have:

  • A headless or FastStore web frontend capable of making authenticated HTTPS requests.
  • Requested and received approval for the product recommendations feature for the account.
  • Recommendation campaigns created and their respective VRNs.
  • Automatic cart and order event capture through Activity Flow configured for your headless or FastStore web store. For custom headless web storefronts, follow Installing Activity Flow in headless stores. FastStore includes Activity Flow natively.

Step 1: Initial setup

After the feature is approved, the VTEX team prepares the recommendations environment for the account. This setup includes:

  • Creating and configuring the recommendations workspace.

  • Synchronizing the product catalog with the recommendation service.

  • Configuring the access credentials used by the integration.

  • Configuring automatic cart and order event capture for your headless or FastStore web store through Activity Flow.

  • Cart events, such as add_to_cart and remove_from_cart, are consumed from the Data Layer and sent to the recommendations platform.

  • Completed orders are automatically processed and transformed into transactions used to train and improve the models.

  • When the order contains the recommendations identifier saved in the orderForm, the purchase can be associated with the user who browsed the store anonymously.

Once these configurations are complete, you can proceed with the implementation steps below.

Step 2: Start the user session

Your headless or FastStore web store must call the POST Start session endpoint.

This endpoint starts or updates the user's recommendations session. It associates the userId used during browsing with the current orderFormId, saves this identifier in the orderForm custom data, and returns the recommendationsUserId that must be used in subsequent requests.

Sending orderFormId in the JSON body is optional for web storefronts when the request forwards the checkout.vtex.com cookie: the API can resolve the order form from that cookie when it isn't in the body. If the client can't send cookies (for example, some server-only calls), include orderFormId in the body manually. For FastStore, the recommended approach is to forward cookies on the start-session request.

Call POST Start session:

  • On the first session load where an order form is available (via the request body or the checkout.vtex.com cookie).
  • Every time the vtex-rec-user-start-session cookie expires.

The endpoint also sets the vtex-rec-user-id cookie with the returned recommendationsUserId, and the vtex-rec-user-start-session cookie, which controls when a new start-session call must be made. The recommendationsUserId must be sent as userId in recommendation and event endpoints.

start-session is important because it allows navigation and interaction events collected during the session to be linked later to the completed purchase. When the order is processed, the service uses the recommendationsUserId saved in the orderForm to associate the anonymous browsing behavior with the VTEX user who completed the purchase.

Request example with checkout.vtex.com cookie:

When the request includes the shopper's checkout.vtex.com cookie, you can omit the JSON body. That applies to FastStore and to headless storefronts that forward the browser's checkout cookies.

In tools like curl, pass that cookie explicitly like in the example below. In the browser it is forwarded automatically. The cookie value includes the cart identifier (for example, _ofid and the orderFormId), as described in Get cart information by ID.

In tools like curl, pass that cookie explicitly like below. In the browser it is forwarded automatically. The cookie value includes the cart identifier, for example _ofid={orderFormId}, as described in Get cart information by ID.


_10
curl --request POST \
_10
--url 'https://api.vtexcommercestable.com.br/api/recommend-bff/v2/users/start-session?an=apiexamples' \
_10
--header 'Accept: application/json' \
_10
--header 'Content-Type: application/json' \
_10
--header 'host: apiexamples.vtexcommercestable.com.br' \
_10
--header 'x-forwarded-host: www.apiexamples.com' \
_10
--header 'x-vtex-rec-origin: apiexamples/storefront/vtex.recommendation-shelf@2.x' \
_10
--cookie 'checkout.vtex.com=_ofid=d761924de4254f6883a8ec2e9a28597d'

Request example with orderFormId:

When the request cannot send checkout cookies (for example, some server-side calls), include orderFormId in the body.


_10
curl --request POST \
_10
--url 'https://api.vtexcommercestable.com.br/api/recommend-bff/v2/users/start-session?an=apiexamples' \
_10
--header 'Accept: application/json' \
_10
--header 'Content-Type: application/json' \
_10
--header 'host: apiexamples.vtexcommercestable.com.br' \
_10
--header 'x-forwarded-host: www.apiexamples.com' \
_10
--header 'x-vtex-rec-origin: apiexamples/storefront/vtex.recommendation-shelf@2.x' \
_10
--data '{"orderFormId":"d761924de4254f6883a8ec2e9a28597d"}'

Response example:


_10
{
_10
"recommendationsUserId": "198e0f50-acf8-42f7-998a-5cd125464749"
_10
}

The returned recommendationsUserId is the same value persisted in the vtex-rec-user-id cookie. The endpoint also sets the vtex-rec-user-start-session cookie.

Step 3: Implement the recommendation flow

To display recommendations in your headless or FastStore web store:

  1. Start the session by calling POST Start session.
  2. Use the returned recommendationsUserId, which is the same value stored in the vtex-rec-user-id cookie, while the vtex-rec-user-start-session cookie is valid.
  3. Fetch recommendations for each shelf using the campaign VRN.
  4. Render the returned products.

Fetch recommendations

Use the GET Fetch recommendations endpoint whenever a page contains a recommendation shelf.

The campaignVrn is the VRN (Virtual Resource Name) that identifies the recommendation strategy. It follows the vrn:recommendations:{store-name}:{campaignType}:{campaignId} format.

The full VRN can be obtained through our Support or from the store Admin in Storefront > Recommendations. In the shelf list, click the three dots on the right side of the shelf and then click Copy ID.

Available campaign types:

  • rec-top-items-v2: Best Sellers
  • rec-persona-v2: For You
  • rec-similar-v2: Similar Products
  • rec-cross-v2: Who Viewed Also Bought
  • rec-cross-v2: Buy Together
  • rec-last-v2: Recently Viewed
  • rec-visual-v2: Visually Similar Products
  • rec-search-v2: Manual collection or search
  • rec-next-v2: Next Interaction

Main parameters:

  • an: VTEX account name.
  • campaignVrn: Campaign VRN.
  • userId: recommendationsUserId returned by start-session.
  • products: Comma-separated product IDs. Required for contextual campaigns, such as similar products, who viewed also bought, visually similar products, next interaction, and cart recommendations.
  • salesChannel: Store sales channel.
  • locale: User locale, for example en-US.

Request example:


_10
curl --request GET \
_10
--url 'https://api.vtexcommercestable.com.br/api/recommend-bff/v2/recommendations?an=apiexamples&campaignVrn=vrn%3Arecommendations%3Aapiexamples%3Arec-top-items-v2%3A123e4567-e89b-12d3-a456-426614174000&userId=198e0f50-acf8-42f7-998a-5cd125464749&salesChannel=1&locale=en-US' \
_10
--header 'Accept: application/json' \
_10
--header 'x-vtex-rec-origin: apiexamples/storefront/vtex.recommendation-shelf@2.x'

For campaigns that require product context, include products:


_10
curl --request GET \
_10
--url 'https://api.vtexcommercestable.com.br/api/recommend-bff/v2/recommendations?an=apiexamples&campaignVrn=vrn%3Arecommendations%3Aapiexamples%3Arec-similar-v2%3A123e4567-e89b-12d3-a456-426614174000&userId=198e0f50-acf8-42f7-998a-5cd125464749&products=product-id-1&salesChannel=1&locale=en-US' \
_10
--header 'Accept: application/json' \
_10
--header 'x-vtex-rec-origin: apiexamples/storefront/vtex.recommendation-shelf@2.x'

Response example:


_65
{
_65
"products": [
_65
{
_65
"brand": "Mizuno",
_65
"productId": "14",
_65
"productName": "Standard Sunglasses",
_65
"link": "/standard-sunglasses/p",
_65
"items": [
_65
{
_65
"itemId": "31",
_65
"nameComplete": "Standard Sunglasses",
_65
"images": [
_65
{
_65
"imageUrl": "https://biggy.vtexassets.com/arquivos/ids/155412/images.png?v=637528820142830000"
_65
}
_65
],
_65
"sellers": [
_65
{
_65
"sellerId": "1",
_65
"commertialOffer": {
_65
"Price": 330,
_65
"ListPrice": 330,
_65
"AvailableQuantity": 10000
_65
}
_65
}
_65
]
_65
}
_65
]
_65
},
_65
{
_65
"brand": "Google",
_65
"productId": "12",
_65
"productName": "Trail Backpack",
_65
"link": "/trail-backpack/p",
_65
"tags": ["advertisement"],
_65
"items": [
_65
{
_65
"itemId": "29",
_65
"nameComplete": "Trail Backpack - variant 2",
_65
"images": [
_65
{
_65
"imageUrl": "https://biggy.vtexassets.com/arquivos/ids/155410/mochila-para-trilha-thule-alltrail-25l-masc-01.jpg?v=637528813555100000"
_65
}
_65
],
_65
"sellers": [
_65
{
_65
"sellerId": "1",
_65
"commertialOffer": {
_65
"Price": 121,
_65
"ListPrice": 121,
_65
"AvailableQuantity": 10000
_65
}
_65
}
_65
]
_65
}
_65
]
_65
}
_65
],
_65
"correlationId": "d2e8c706-e67c-45d7-8de9-b80976960f89",
_65
"campaign": {
_65
"id": "ca2acae8-41a4-4bcd-9ffd-0ac40b7c0a57",
_65
"title": "Complementary products",
_65
"type": "CROSS_SELL"
_65
}
_65
}

When the shelf returns a sponsored product, the product will be marked with the advertisement tag. In this case, render the card with a sponsored label.

Render the returned products as product cards on the shelf.

Step 4: Track product view events

To measure performance and improve recommendations, your headless or FastStore web store must send product-view events when the user opens a product detail page.

For accurate tracking, ensure that you always use the same session recommendationsUserId in the userId field.

Use the POST Product view endpoint when the user views a product detail page.

Request example:


_10
curl --request POST \
_10
--url 'https://api.vtexcommercestable.com.br/api/recommend-bff/v2/events/product-view?an=apiexamples' \
_10
--header 'Content-Type: application/json' \
_10
--header 'user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36' \
_10
--header 'x-vtex-rec-origin: apiexamples/storefront/vtex.recommendation-shelf@2.x' \
_10
--data '{
_10
"userId": "198e0f50-acf8-42f7-998a-5cd125464749",
_10
"product": "1234",
_10
"source": "WEB_DESKTOP"
_10
}'

The response returns 202 Accepted.

The source field accepts values such as WEB_DESKTOP and WEB_MOBILE. When source is not sent, the BFF tries to infer the value from the user-agent.

Step 5: Configure shelf event tracking through Activity Flow

Recommendation shelf view events and recommended product click events are automatically captured through Activity Flow.

To capture view events, render the following attributes on the recommendation shelf parent container:


_10
<div
_10
data-af-element="recommendation-shelf"
_10
data-af-onimpression={shouldAddAFAttr}
_10
data-af-onview={shouldAddAFAttr}
_10
data-af-correlation-id={shouldAddAFAttr && correlationId}
_10
data-af-campaign-id={shouldAddAFAttr && campaignId}
_10
data-af-products={shouldAddAFAttr && productIds}
_10
>
_10
{/* Recommendation shelf products */}
_10
</div>

To capture click events, render the following attributes on each product in the recommendation shelf:


_10
<div
_10
data-af-element="recommendation-shelf-product"
_10
data-af-correlation-id={correlationId}
_10
data-af-campaign-id={campaignId}
_10
data-af-product-id={product?.productId}
_10
data-af-onclick={!!product?.productId}
_10
data-af-product-position={(index ?? 0) + 1}
_10
>
_10
{/* Product card content */}
_10
</div>

Use the correlationId returned in the recommendation response, the campaignId returned in campaign.id, and the list of rendered product IDs in productIds.

Implementation example:


_44
<div class="recommendations-embedded-shelf">
_44
<div
_44
class="recommendationShelfContainer"
_44
data-af-element="recommendation-shelf"
_44
data-af-onimpression="true"
_44
data-af-onview="true"
_44
data-af-correlation-id="d2e8c706-e67c-45d7-8de9-b80976960f89"
_44
data-af-campaign-id="ca2acae8-41a4-4bcd-9ffd-0ac40b7c0a57"
_44
data-af-products="14,12"
_44
>
_44
<div class="rs-title">Complementary products</div>
_44
<div class="rs-track">
_44
<div
_44
class="rs-card"
_44
data-af-element="recommendation-shelf-product"
_44
data-af-correlation-id="d2e8c706-e67c-45d7-8de9-b80976960f89"
_44
data-af-campaign-id="ca2acae8-41a4-4bcd-9ffd-0ac40b7c0a57"
_44
data-af-product-id="14"
_44
data-af-onclick="true"
_44
data-af-product-position="1"
_44
>
_44
<img class="rs-card-img" alt="" loading="lazy" src="https://biggy.vtexassets.com/arquivos/ids/155412/images.png?v=637528820142830000" />
_44
<a class="rs-card-name" href="/standard-sunglasses/p">Standard Sunglasses</a>
_44
<div class="rs-card-price">$330.00</div>
_44
<button type="button" class="rs-btn-add">Add to cart</button>
_44
</div>
_44
_44
<div
_44
class="rs-card"
_44
data-af-element="recommendation-shelf-product"
_44
data-af-correlation-id="d2e8c706-e67c-45d7-8de9-b80976960f89"
_44
data-af-campaign-id="ca2acae8-41a4-4bcd-9ffd-0ac40b7c0a57"
_44
data-af-product-id="12"
_44
data-af-onclick="true"
_44
data-af-product-position="2"
_44
>
_44
<img class="rs-card-img" alt="" loading="lazy" src="https://biggy.vtexassets.com/arquivos/ids/155410/mochila-para-trilha-thule-alltrail-25l-masc-01.jpg?v=637528813555100000" />
_44
<a class="rs-card-name" href="/trail-backpack/p">Trail Backpack</a>
_44
<div class="rs-card-price">$121.00</div>
_44
<button type="button" class="rs-btn-add">Add to cart</button>
_44
</div>
_44
</div>
_44
</div>
_44
</div>

Contributors
1
Photo of the contributor
Was this helpful?
Yes
No
Suggest Edits (GitHub)
Contributors
1
Photo of the contributor
Was this helpful?
Suggest edits (GitHub)
On this page