--- title: Build recommendation interfaces (SSR) slug: p25b0248 canonical_url: https://docs.coveo.com/en/p25b0248/ collection: coveo-for-commerce source_format: adoc --- # Build recommendation interfaces (SSR) > **Important** > > The Headless Commerce SSR utilities are in open beta. > Contact your Coveo representative for support in adopting this. To implement a [server-side rendering (SSR)](https://docs.coveo.com/en/p2af0263/) commerce recommendations interface, use the [Headless](https://docs.coveo.com/en/lcdf0493/) [`Recommendations`](https://docs.coveo.com/en/headless-react/latest/reference/interfaces/SSR_Commerce.index.Recommendations.html) controller hooks and a recommendation [provider](https://docs.coveo.com/en/obif0156#create-providers). ## Prerequisites Before you begin building your recommendation interfaces, make sure you: . [Understand how recommendation interfaces work](https://docs.coveo.com/en/o4ue0204/). . [Create recommendation configurations](https://docs.coveo.com/en/o8880463/). ## Define and retrieve the target recommendation controller hooks When [defining your commerce engine](https://docs.coveo.com/en/obif0156#define-the-commerce-engine-and-controllers), leverage the [`defineRecommendations`](https://docs.coveo.com/en/headless-react/latest/reference/functions/SSR_Commerce.index.defineRecommendations.html) functions to define and retrieve the target recommendation hooks. ```tsx // lib/commerce-engine-config.ts import { defineRecommendations, // ... } from '@coveo/headless-react/ssr-commerce'; export default { // ... controllers: { popularViewed: defineRecommendations({ <1> options: { slotId: 'd73afbd2-8521-4ee6-a9b8-31f064721e73', }, }), popularBought: defineRecommendations({ options: { slotId: 'af4fb7ba-6641-4b67-9cf9-be67e9f30174', }, }), viewedTogether: defineRecommendations({ options: { slotId: 'ff5d8804-d398-4dd5-b68c-6a729c66454b', }, }), // ... }, } satisfies CommerceEngineDefinitionOptions; ``` <1> For each target recommendation controller hook, specify the `slotId` of the recommendation slot configuration. The `slotId` is the unique identifier of the slot you want to retrieve recommendations for. This corresponds to the `id` field of the [recommendation slot configuration](https://docs.coveo.com/en/o8880463/) you've created. ## Create recommendation components Next, create recommendation components that use the target recommendation controller hooks. The following is an example implementation for the `popularBought` strategy. ```tsx // components/recommendations/popular-bought.tsx 'use client'; import {usePopularBought} from '@/lib/commerce-engine'; import ProductButtonWithImage from '../product-button-with-image'; export default function PopularBought() { const {state, methods} = usePopularBought(); return ( <> ); } ``` <1> Display each recommended product. <2> Use a product button component that uses the [`interactiveProduct`](https://docs.coveo.com/en/headless-react/latest/reference/interfaces/SSR_Commerce.index.InteractiveProduct.html) function to correctly log the product click and also handle navigation. See [Displaying products](https://docs.coveo.com/en/oc685393#display-the-target-product). The recommendation components can then be included in the target pages. ## Display recommendations with your recommendation provider When displaying your recommendation components in a page, wrap them in your recommendation provider. The following is an example of a cart page with a `popularBought` recommendation component, simplified to focus on the recommendation part. ```tsx // app/cart/page.tsx // runs server-side // ... import { RecommendationProvider, // ... } from '@/components/providers/providers'; import PopularBought from '@/components/recommendations/popular-bought'; import { recommendationEngineDefinition, // ... } from '@/lib/commerce-engine'; import {NextJsNavigatorContext} from '@/lib/navigatorContextProvider'; import {defaultContext} from '@/utils/context'; import {headers} from 'next/headers'; export default async function Search() { const navigatorContext = new NextJsNavigatorContext(headers()); <1> standaloneEngineDefinition.setNavigatorContextProvider( () => navigatorContext ); const items = // ... <2> const recsStaticState = await recommendationEngineDefinition.fetchStaticState( { controllers: { popularBought: {enabled: true}, <3> popularViewed: {enabled: false}, viewedTogether: {enabled: false}, cart: {initialState: [items](https://docs.coveo.com/en/210/)}, context: { language: defaultContext.language, country: defaultContext.country, currency: defaultContext.currency, view: { url: 'https://sports.barca.group/cart', }, }, }, } ); return ( // ... staticState={recsStaticState} navigatorContext={navigatorContext.marshal} > // ... ); } export const dynamic = 'force-dynamic'; ``` <1> [Create a navigation context provider](https://docs.coveo.com/en/obif0156#create-a-navigation-context-provider). <2> Retrieve [cart items](https://docs.coveo.com/en/oc685394/). <3> Setting `popularBought.enabled` to `true` lets Headless fetch and refresh `popularBought` recommendations. In the following line, you set `popularViewed.enabled` to `false` because you don't need to fetch and refresh `popularViewed` recommendations in this component. And again in the following, you set `viewedTogether.enabled` to `false` because you don't need to fetch and refresh `viewedTogether` recommendations in this component. <4> Wrap your recommendations components with your recommendation [provider](https://docs.coveo.com/en/obif0156#create-providers). This code sample was abbreviated to focus on recommendations. For the full sample, see the [Headless repository](https://github.com/coveo/ui-kit/tree/main/samples/headless-ssr/commerce-nextjs/app/cart/page.tsx).