--- title: Build product listing pages (CSR) slug: p25a3258 canonical_url: https://docs.coveo.com/en/p25a3258/ collection: coveo-for-commerce source_format: adoc --- # Build product listing pages (CSR) Building [product listing pages (PLPs)](https://docs.coveo.com/en/m1sf3187/) with Coveo Headless involves two main elements: . Keeping the URL up to date as you navigate between pages using the [`Context`](https://docs.coveo.com/en/headless/latest/reference/interfaces/Commerce.Context.html) controller . Using the [`ProductListing`](https://docs.coveo.com/en/headless/latest/reference/interfaces/Commerce.ProductListing.html) controller to fetch product listings and display the results A complete example of a listing page component is available in the [sample project in the Headless repository](https://github.com/coveo/ui-kit/tree/master/packages/samples/headless-commerce-react/src/pages/product-listing-page.tsx). ## Prerequisite Make sure that you understand how to [build product listing pages (PLPs)](https://docs.coveo.com/en/o4ue0471/). ## Keep the URL up to date Keep the URL state updated in Headless to ensure that the correct [product listing page (PLP)](https://docs.coveo.com/en/m1sf3187/) is fetched when navigating between pages. The `context` helps Headless determine which [product listing page (PLP)](https://docs.coveo.com/en/m1sf3187/) to fetch products for. For more information, [Navigating between pages](https://docs.coveo.com/en/o7v87331/). ## Initializing the `ProductListing` controller After [initializing your engine](https://docs.coveo.com/en/o6r70022#initialize-the-headless-commerce-engine), you can pass in this instance to build the controller. ```tsx import { commerceEngine } from './Engine'; import { buildProductListing } from '@coveo/headless/commerce'; const productListing = buildProductListing(commerceEngine); ``` The `ProductListing` controller has a [`refresh`](https://docs.coveo.com/en/headless/latest/reference/interfaces/Commerce.ProductListing.html#refresh) method you can use to fetch product listings. ## Display the listing pages using the `ProductListing` controller In addition to ensuring that page navigation correctly updates the `url` using the `Context` controller, you must also display the products fetched by the `ProductListing` controller. ```tsx import { Cart, Search as HeadlessSearch, ProductListing, } from '@coveo/headless/commerce'; import { useState, useEffect } from 'react'; import FacetGenerator from '../../facets/facet-generator/facet-generator'; import Pagination from '../../pagination/pagination'; import ProductList from '../../product-list/product-list'; import Sort from '../../sort/sort'; interface ISearchAndListingInterface { searchOrListingController: HeadlessSearch | ProductListing; cartController: Cart; navigate: (pathName: string) => void; } export default function SearchAndListingInterface( props: ISearchAndListingInterface ) { const {searchOrListingController, cartController, navigate} = props; const [searchOrListingState, setSearchOrListingState] = useState( searchOrListingController.state ); useEffect(() => { <1> searchOrListingController.subscribe(() => setSearchOrListingState(searchOrListingController.state) ); }, [searchOrListingController]); return (
controller={searchOrListingController.facetGenerator()} />
<3> products={searchOrListingState.products} controllerBuilder={searchOrListingController.interactiveProduct} cartController={cartController} navigate={navigate} > <5>
); } ``` <1> Subscribe to the state of the `ProductListing` controller. <2> [Display the facets generated by the `FacetGenerator` sub-controller](https://docs.coveo.com/en/o7vb0270/). <3> [Display the sorting options generated by the `Sort` sub-controller](https://docs.coveo.com/en/o7vb0270/). <4> [Render the list of `products` returned by the controller](https://docs.coveo.com/en/o8ce0239/). <5> [Display the pagination generated by the `Pagination` sub-controller](https://docs.coveo.com/en/o7vb0270/). > **Note** > > The previous component can be re-used for both displaying and interacting with results from both search and listing pages. A complete example of how to build a PLP component is available in the [Headless repository](https://github.com/coveo/ui-kit/tree/master/packages/samples/headless-commerce-react/src/pages/product-listing-page.tsx). Within the sample project, you can find additional components that were omitted in this article, such as the [`BreadcrumbManager`](https://docs.coveo.com/en/headless/latest/reference/interfaces/Commerce.ProductListing.html#breadcrumbmanager) (displays a summary of the currently active facet values) and [`Summary`](https://docs.coveo.com/en/headless/latest/reference/interfaces/Commerce.ProductListing.html#summary) (provides a summary of search results such as the number of results returned).