Build your listing page interface

This is for:

Developer

Once a listing page configuration is created, you can use the Get a listing page endpoint to retrieve the listing page configuration and display the listing page in your user interface.

While there are several possible approaches for building your listing page interface, this article focuses on Coveo Headless.

Headless overview

Building product listing pages (PLPs) with Coveo Headless involves two main elements:

  1. Keeping the URL up to date as you navigate between pages using the Context controller

  2. Using the ProductListing 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.

Keeping URL up to date

To ensure that the correct listing page configuration is fetched when navigating between pages, you must keep the URL state updated in Headless.

The context helps Headless determine which listing page configuration to fetch products for.

For more information, Navigating between pages.

Initializing the ProductListing controller

After initializing your engine, you can pass in this instance to build the controller.

import { commerceEngine } from './Engine';
import { buildProductListing } from '@coveo/headless/commerce';

const productListing = buildProductListing(commerceEngine);

The ProductListing controller has a 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.

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 (
    <div className="row">
      <div className="column">
        <FacetGenerator 2
          controller={searchOrListingController.facetGenerator()}
        />
      </div>
      <div className="column">
        <Sort controller={searchOrListingController.sort()} /> 3
        <ProductList 4
          products={searchOrListingState.products}
          controllerBuilder={searchOrListingController.interactiveProduct}
          cartController={cartController}
          navigate={navigate}
        ></ProductList>
        <Pagination controller={searchOrListingController.pagination()} /> 5
      </div>
    </div>
  );
}
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.

Within the sample project, you can find additional components that were omitted in this article, such as the BreadcrumbManager (displays a summary of the currently active facet values) and Summary (provides a summary of search results such as the number of results returned).