---
title: Context mapping with Headless
slug: q4894151
canonical_url: https://docs.coveo.com/en/q4894151/
collection: coveo-for-commerce
source_format: adoc
---
# Context mapping with Headless
If you have [configured context mappings](https://docs.coveo.com/en/q3bc0472.md) on a tracking ID, you can use the [`setCustom`](https://docs.coveo.com/en/headless/latest/reference/interfaces/Commerce.Context.html#setcustom) method on the `Context` controller to specify custom context values at query time.

Context mappings let you extend the default `context` object in Commerce API requests with custom fields.
Each mapping defines a key, a data type, and one or more destinations that control where the Commerce API routes the value, such as the [query pipeline](https://docs.coveo.com/en/180.md) context, [Coveo ML](https://docs.coveo.com/en/188.md) context, or [field aliases](https://docs.coveo.com/en/q1q94008.md).

> **Type definitions**
>
> * [`Context`](https://docs.coveo.com/en/headless/latest/reference/interfaces/Commerce.Context.html)
> * [`ContextState`](https://docs.coveo.com/en/headless/latest/reference/interfaces/Commerce.ContextState.html)
> * [`buildContext`](https://docs.coveo.com/en/headless/latest/reference/functions/Commerce.buildContext.html)
## Prerequisites

Before using `setCustom`, you must [create context mappings](https://docs.coveo.com/en/q3bc0472.md#create-a-context-mapping) on your [tracking ID](https://docs.coveo.com/en/o8rb0139.md) using the Context Mappings API.
The Commerce API validates each value you send against its configured type and silently drops any key that doesn't match.

## Example context mappings

The following examples assume the target tracking ID has been configured with these context mappings, expanding on the [List context mappings](https://docs.coveo.com/en/q3bc0472.md#list-context-mappings) example in the documentation:

```json

[

  {

    "key": "fitmentProducts",

    "type": "PRODUCT_LIST",

    "destinations": [{"attribute": "QUERY_PIPELINE_CONTEXT"}]

  },

  {

    "key": "shoppingIntent",

    "type": "STRING",

    "destinations": [

      {"attribute": "ML_CONTEXT"},

      {"attribute": "QUERY_PIPELINE_CONTEXT"}

    ]

  },

  {

    "key": "storeId",

    "type": "STRING",

    "destinations": [

      {

        "attribute": "FIELD_ALIASES",

        "fieldAlias": "price_dict",

        "fieldSource": "price_dict.{{contextValue}}"

      }

    ]

  },

  {

    "key": "contractCustomer",

    "type": "BOOLEAN",

    "destinations": [{"attribute": "QUERY_PIPELINE_CONTEXT"}]

  },

  {

    "key": "loyaltyTier",

    "type": "NUMBER",

    "destinations": [{"attribute": "QUERY_PIPELINE_CONTEXT"}]

  }

]

```
[%header,cols="1,1,2,2"]
|===
|Key
|Type
|Destinations
|Typical use case

|`fitmentProducts`
|`PRODUCT_LIST`
|`QUERY_PIPELINE_CONTEXT`
|Filter results to compatible parts via a pipeline filter rule.

|`shoppingIntent`
|`STRING`
|`ML_CONTEXT`, `QUERY_PIPELINE_CONTEXT`
|Influence ML relevance and enable intent-based ranking expressions.

|`storeId`
|`STRING`
|`FIELD_ALIASES`
|Resolve store-specific pricing from a dictionary field.

|`contractCustomer`
|`BOOLEAN`
|`QUERY_PIPELINE_CONTEXT`
|Apply contract-specific pricing or catalog rules.

|`loyaltyTier`
|`NUMBER`
|`QUERY_PIPELINE_CONTEXT`
|Boost results or unlock promotions based on loyalty level.
|===

### Context value retrieval

The values you pass to `setCustom` depend on the context mapping type and your application's runtime state.

* **`STRING`** values like `shoppingIntent` are typically derived from the section of the site the user is browsing (for example, a category page) or from an explicit user selection.
* **`STRING`** values like `storeId` often come from a user preference stored in a cookie or session, such as a selected store location.
* **`PRODUCT_LIST`** values like `fitmentProducts` are usually derived from user interactions (for example, a vehicle selector that resolves to compatible part SKUs) or from [product recommendations](https://docs.coveo.com/en/3132.md).
* **`BOOLEAN`** values like `contractCustomer` are typically resolved from authentication state or user profile data.
* **`NUMBER`** values like `loyaltyTier` may come from a CRM or loyalty system.

## Set custom context at query time

Call [`setcustom`](https://docs.coveo.com/en/headless/latest/reference/interfaces/Commerce.Context.html#setCustom) on the [`Context`](https://docs.coveo.com/en/headless/latest/reference/interfaces/Commerce.Context.html) controller before dispatching a search action.
The controller automatically includes the custom context in all subsequent Commerce API requests.

### JavaScript example

The following is a complete vanilla JavaScript example that demonstrates `setCustom` with the context mappings above.

> **Type definitions**
>
> * [`CommerceEngineOptions`](https://docs.coveo.com/en/headless/latest/reference/interfaces/Commerce.CommerceEngineOptions.html)
> * [`Context`](https://docs.coveo.com/en/headless/latest/reference/interfaces/Commerce.Context.html)
> * [`SearchActionCreators`](https://docs.coveo.com/en/headless/latest/reference/interfaces/Commerce.SearchActionCreators.html)
> * [`buildCommerceEngine`](https://docs.coveo.com/en/headless/latest/reference/functions/Commerce.buildCommerceEngine.html)
> * [`buildContext`](https://docs.coveo.com/en/headless/latest/reference/functions/Commerce.buildContext.html)
> * [`buildSearch`](https://docs.coveo.com/en/headless/latest/reference/functions/Commerce.buildSearch.html)
> * [`loadSearchActions`](https://docs.coveo.com/en/headless/latest/reference/functions/Commerce.loadSearchActions.html)
[%collapsible]

**Details**

#### ```js

// engine.js

import {

  buildCommerceEngine,

  buildContext,

  buildSearch,

  getSampleCommerceEngineConfiguration,

  loadSearchActions,

} from 'https://static.cloud.coveo.com/headless/v3.51.3/commerce/headless.esm.js';

import {renderSearchResults} from './renderSearchResults.js';



const coveoHeadlessCustomContext = () => {

  const intentSelect = document.getElementById('shopping-intent');

  const storeSelect = document.getElementById('store-id');

  const fitmentTextarea = document.getElementById('fitment-products');

  const contractSelect = document.getElementById('contract-customer');

  const loyaltySelect = document.getElementById('loyalty-tier');

  const applyButton = document.getElementById('apply-context');

  const contextStateEl = document.querySelector('#context-state pre code');

  const searchResultsEl = document.getElementById('search-results');



  const engine = buildCommerceEngine({

    configuration: getSampleCommerceEngineConfiguration(), <1>

  });



  const contextController = buildContext(engine);

  const searchController = buildSearch(engine);

  const {executeSearch} = loadSearchActions(engine);



  searchController.subscribe(

    () => renderSearchResults(searchResultsEl, searchController.state.products) <2>

  );



  contextController.subscribe(() => {

    const {custom, ...rest} = contextController.state;

    contextStateEl.textContent = JSON.stringify({...rest, custom}, null, 2); <3>

  });



  applyButton.addEventListener('click', () => {

    const customContext = {

      ...contextController.state.custom, <4>

      shoppingIntent: intentSelect.value,

      storeId: storeSelect.value,

      fitmentProducts: fitmentTextarea.value.split(',').map((s) => s.trim()),

      contractCustomer: contractSelect.value === 'true',

      loyaltyTier: Number(loyaltySelect.value),

    }; <5>



    contextController.setCustom(customContext); <6>



    engine.dispatch(executeSearch());

  });

};



document.addEventListener('DOMContentLoaded', coveoHeadlessCustomContext);

```


<1> This configuration doesn't have context mapping defined, meaning changing values for the context mapping elements won't affect the returned results.

<2> Dispatch updates to a render function when the search controllers received updates.

<3> This is just for demonstration purposes. In a real-world implementation, displaying the values of the context being passed would not add value.

<4> `setCustom` replaces the entire custom object each time it is called. To preserve previous values while updating a single key, spread the existing `contextController.state.custom` values into your new object.

<5> Refer to [Determine suitable values](#determine-suitable-values) for examples on how to derive real world examples.

<6> Set the values for context mapping before dispatching the search action to ensure the search results reflect the updated user intent.

#### == Set custom context at engine initialization

You can also provide initial custom context values when building the commerce engine, through the `context.custom` property of the engine configuration.

```js

import {

  buildCommerceEngine,

  getSampleCommerceEngineConfiguration,

} from '@coveo/headless/commerce';



export const engine = buildCommerceEngine({

  configuration: {

    ...getSampleCommerceEngineConfiguration(),

    context: {

      language: 'en',

      country: 'US',

      currency: 'USD',

      view: {

        url: 'https://my-store.example.com',

      },

      custom: {

        shoppingIntent: 'fishing',

        storeId: '10010',

        fitmentProducts: ['SP-00301', 'SP-01202'],

        contractCustomer: true,

        loyaltyTier: 3,

      },

    },

  },

});

```
Values set at initialization are included in all Commerce API requests from the start.
Use `setCustom` to update them dynamically as the user navigates or interacts with your application.