--- title: Headless commerce usage (client-side rendering) slug: o6r70022 canonical_url: https://docs.coveo.com/en/o6r70022/ collection: coveo-for-commerce source_format: adoc --- # Headless commerce usage (client-side rendering) The Coveo Headless library acts as a middle-layer for applications, opening a line of communication between the UI elements and the Commerce API. A project built on top of Headless will typically involve two main building-blocks: * the _engine,_ which manages the state of the product discovery interface and communicates with the Coveo Platform * the _controllers,_ which dispatch actions to the engine based on user interactions ## Install Headless Use [npm](https://www.npmjs.com/get-npm) to install the Headless library. ```bash npm install @coveo/headless ``` ## Initialize the Headless commerce engine > **Tip** > > All controllers must depend on a single `CommerceEngine` instance. > This instance is responsible for managing the state across all commerce solutions (such as search, recommendations, listings). For more details on the initialization options given below, see [`buildCommerceEngine`](https://docs.coveo.com/en/headless/latest/reference/functions/Commerce.buildCommerceEngine.html). ```ts import { buildCommerceEngine } from '@coveo/headless/commerce'; import { loadCartItemsFromLocalStorage } from '../utils/cart-utils'; export const getEngine = () => { if (_engine !== null) { return _engine; } _engine = buildCommerceEngine({ configuration: { organizationId: '', <1> accessToken: '', <2> analytics: { <3> trackingId: '' }, context: { <4> currency: '', country: '', language: '', view: { url: '' }, } cart: { items: loadCartItemsFromLocalStorage() ?? [], <5> }, }, }); return _engine; }; ``` <1> Organization ID is the [unique identifier of your Coveo organization](https://docs.coveo.com/en/n1ce5273/). <2> Access token is a [search token](https://docs.coveo.com/en/56/) or an [API key](https://docs.coveo.com/en/105/) that grants the **Allowed** [access level](https://docs.coveo.com/en/2818/) on the [**Execute queries**](https://docs.coveo.com/en/1707#execute-queries-domain) [domain](https://docs.coveo.com/en/2819/) and the **Push** [access level](https://docs.coveo.com/en/2818/) on the [**Analytics data**](https://docs.coveo.com/en/1707#analytics-data-domain) [domain](https://docs.coveo.com/en/2819/) in the target [organization](https://docs.coveo.com/en/185/). To improve security, client-side specification of user IDs isn't supported by Event Protocol. To specify user IDs, enforce them through [search tokens](https://docs.coveo.com/en/56/). <3> Via the [`analytics`](https://docs.coveo.com/en/headless/latest/reference/interfaces/Commerce.AnalyticsConfiguration.html) object, specify the [tracking ID](https://docs.coveo.com/en/o8rb0139/). <4> The [`context`](https://docs.coveo.com/en/headless/latest/reference/interfaces/Commerce.ContextOptions.html) object contains information about the user's context, such as the currency, country, language, and the URL. Every time the user [navigates between pages](https://docs.coveo.com/en/o7v87331/), you must update this URL. <5> Pass in the initial state of the cart by specifying the [`CartInitialState`](https://docs.coveo.com/en/headless/latest/reference/interfaces/Commerce.CartInitialState.html) object. In this code sample, a custom `loadCartItemsFromLocalStorage` function is used to initialize the cart state by fetching the cart items from local storage. Learn more about how to [manage the cart state](https://docs.coveo.com/en/o7v87042/). For more details on how an engine is initialized in an actual project, see [the sample in the Headless repository](https://github.com/coveo/ui-kit/tree/master/packages/samples/headless-commerce-react/src/context/engine.ts) ## Headless controllers A Headless _controller_ is an abstraction that simplifies the implementation of a specific Coveo-powered UI feature or component. In other words, controllers provide programming interfaces for interacting with the Headless engine's state. Headless provides a set of controllers for each commerce solution (such as search, recommendations, and listings). Additionally, there are controllers for common features such as interacting with the cart or modifying context. ### Initialize a controller instance You can initialize a Headless controller by calling its builder function. A controller's builder function always requires a Headless engine instance as a first argument. ```ts import { buildSearch } from "@coveo/headless/commerce"; const search = buildSearch(commerceEngine); ``` Many builder functions also accept, and sometimes require, a configuration object as a second argument. In the following example, you can initialize a [`Recommendations`](https://docs.coveo.com/en/headless/latest/reference/interfaces/Commerce.Recommendations.html) controller with an initial state that specifies your recommendations configuration information. ```ts import { buildRecommendations } from "@coveo/headless/commerce"; const recommendations = buildRecommendations(commerceEngine, { options: { slotId: "", productId: "" }, }); ``` ### Interact with a controller The Commerce Headless engine exposes different controllers. Each controller exposes a public interface, which you can use to interact with the Headless engine's state. You can either call a method directly on a controller, or create a sub-controller first, and then call a method on the sub-controller. For example, certain common functionality such as sorting, pagination, and facets are available as sub-controllers on each commerce solution controller you're using (such as `Search`, `Recommendations`, and `ProductListing`). When you call a method on a controller instance (or a sub-controller instance), one or more actions are dispatched. The Headless engine's reducers listen to those actions and react to them by altering the state as necessary. The following code sample showcases how to interact with a `search` controller by directly calling methods and how to use it to create sub-controllers. ```ts import { buildSearch } from "@coveo/headless/commerce"; const search = buildSearch(commerceEngine); <1> search.executeFirstSearch(); <2> const facetGenerator = search.facetGenerator(); <3> const facets = facetGenerator.facets; <4> ``` <1> Use the `buildSearch` builder function to create a `search` controller instance. <2> Call the `executeFirstSearch` method on the `search` controller instance to execute the first search. <3> Use the `facetManager` method on the `search` controller instance to create a `FacetGenerator` sub-controller instance that will manage facets. <4> Call the `facets` getter on the sub-controller to retrieve a list of facets. > **Note** > > Note that due to the [descriptive nature of the Commerce API](https://docs.coveo.com/en/o6od0220/), which Headless is using under the hood, the list of facets returned by Coveo aren't specified in the front-end. ### Subscribe to state changes You can use the `subscribe` method on a controller instance to listen to its state changes. The listener function you pass when calling the `subscribe` method will be executed every time an action is dispatched that affects the state that's relevant to the controller. The following code sample showcases how you can run a custom function every time the state of the `search` controller changes. ```ts import { buildSearch } from "@coveo/headless/commerce"; const search = buildSearch(commerceEngine); const onSearchStateUpdate = () => { // custom code } search.subscribe(onSearchStateUpdate); ``` ## Dispatch actions "You'll often dispatch methods in response to changes in the state. However, you may want to dispatch actions manually, when you need more fine-grained control over a feature than what a controller offers through its public interface. You can create actions using action loaders and dispatch them using the Headless engine's dispatch method. ```ts import { loadQueryActions } from "@coveo/headless/commerce"; const queryActions = loadQueryActions(commerceEngine); <1> const action = queryActions.updateQuery({query: ''}); <2> commerceEngine.dispatch(action); <3> ``` <1> Use the `loadQueryActions` function to add the necessary reducers to the engine, if they haven't been added already, and return an object holding the relevant action creator functions. <2> Create a dispatchable action by calling the `updateQuery` action creator function, passing in the updated `query`. <3> Dispatch the action by calling the `dispatch` method on the commerce engine instance. For more details on the available actions, see the [reference documentation](https://docs.coveo.com/en/headless/latest/reference/modules/Commerce.html).