# JSONata data mapping Use JSONata expressions in data mappings inside the Product sync module to transform your commercetools product data into the format required by the AI provider. [JSONata](https://jsonata.org/) is a lightweight query and transformation language for JSON data. In AI Hub, JSONata expressions power the **Data mapping** configuration in the **Product sync** tab, where you define how product fields map to the target feed schema. Each expression is evaluated against a single entry in the product feed. Expressions can access product fields directly, apply conditional logic, and call built-in helper functions called bindings. For instructions on accessing the data mapping editor, see [Configure Product sync](/agentic-commerce/ai-hub/agentic-channels.md#configure-product-sync). ## Product data object The product feed is flattened by variant: each entry in the feed represents one product variant, not a product. A product with two variants produces two separate feed entries. Your expressions always run in the context of a single variant entry. The payload structure follows standard commercetools [ProductProjection](/urn?urn=ctp%3Aapi%3Atype%3AProductProjection) resource data. Each feed entry has the following top-level fields: - `productData`: the full [ProductProjection](/urn?urn=ctp%3Aapi%3Atype%3AProductProjection) for the current product. - `variant`: the [Product Variant](/urn?urn=ctp%3Aapi%3Atype%3AProductVariant) that this feed entry represents, extracted from the product's variants. - `store`: the [Store](/urn?urn=ctp%3Aapi%3Atype%3AStore) context for the Agentic Channel. - `shippingMethods`: available [ShippingMethod](/urn?urn=ctp%3Aapi%3Atype%3AShippingMethod) resources. For ProductProjection data resolved in Store context, the variant usually includes a scoped `price` field (singular). For mapping expressions, prefer `variant.price` as the primary price source. The following simplified example shows the structure of a single feed entry. Fields not relevant to data mapping are omitted. ```json title="Feed entry" { "productData": { "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "name": { "en-US": "Classic Running Shoe", "de-DE": "Klassischer Laufschuh" }, "description": { "en-US": "A versatile everyday running shoe." }, "slug": { "en-US": "classic-running-shoe" }, "masterVariant": { "id": 1, "key": "classic-running-shoe-master", "sku": "CRS-001-BLK-42" }, "variants": [ { "id": 2, "key": "classic-running-shoe-v2", "sku": "CRS-001-BLK-43" } ] }, "variant": { "id": 1, "key": "classic-running-shoe-master", "sku": "CRS-001-BLK-42", "price": { "id": "a1b2c3d4-5678-4abc-b3fc-2c963f66afa6", "value": { "centAmount": 12999, "currencyCode": "USD", "fractionDigits": 2 }, "channel": { "id": "956d220a-fde7-44be-8496-c852fed723ca" } }, "attributes": [ { "name": "color", "value": "black" }, { "name": "size", "value": 42 } ], "availability": { "isOnStock": true, "availableQuantity": 100 } }, "store": { "id": "store-ABC" }, "shippingMethods": [ { "id": "sm-standard" }, { "id": "sm-express" } ] } ``` This example shows how multiple resources are combined in a single feed entry. For full field-level details, refer to the API type definitions: - `productData` follows the [ProductProjection](/urn?urn=ctp%3Aapi%3Atype%3AProductProjection) shape. - `variant` follows the [ProductVariant](/urn?urn=ctp%3Aapi%3Atype%3AProductVariant) shape. - `store` follows the [Store](/urn?urn=ctp%3Aapi%3Atype%3AStore) shape. - `shippingMethods` contains [ShippingMethod](/urn?urn=ctp%3Aapi%3Atype%3AShippingMethod) resources. ## Default bindings Bindings are values and helper functions available to expressions at runtime. Variable bindings are always injected from your Agentic Channel configuration as read-only values. Function bindings can be available in provider templates as reusable helpers. ### Variable bindings The following variable bindings are available in every expression. Their values are derived from the Store and Channel configuration of your Agentic Channel, and cannot be reassigned. They are always injected and read-only. | Binding | Type | Example value | Description | | --- | --- | --- | --- | | `$country` | string | `"US"` | Country code from the Store configuration. | | `$locale` | string | `"en-US"` | Default locale from the Store configuration. | ### Function bindings The following function bindings are common helper examples. Depending on the selected provider template, additional helper functions can be available, and some functions can differ. | Binding | Description | | --- | --- | | `$getAttribute(attributes, name)` | Returns the value of a named attribute from a variant's `attributes` array. | | `$priceToAmount(price)` | Extracts the numeric price amount from the variant `price` object, accounting for `fractionDigits`. | | `$formatPrice(price)` | Returns a formatted price string from the variant `price` object (for example, `"129.99"`). | ## Expression examples The following examples show expressions of increasing complexity, from direct field access to derived transformations. ### Access fields directly The simplest expressions access a field directly from the product entry. Get the variant SKU (feed product ID): ```text title="Get variant SKU" variant.sku ``` Get the product name in a specific locale: Localized fields are plain objects keyed by locale. Use a string key with backticks when the locale contains a hyphen. ```text title="Get localized product name" productData.name.`en-US` ``` Get the product ID: ```text title="Get product ID" productData.id ``` ### Use bindings and conditionals Intermediate expressions use bindings, conditionals, or string operations. Get the product name in the configured locale: Use the `$locale` variable binding and `$lookup` to access the localized value dynamically, without hardcoding a language. ```text title="Dynamic locale lookup" $lookup(productData.name, $locale) ``` Map stock availability to a feed-compatible string: Use a conditional expression to return the string value expected by the provider. ```text title="Map stock availability" variant.availability.isOnStock ? "in_stock" : "out_of_stock" ``` Get a custom attribute value by name: If your template provides `$getAttribute`, use it to retrieve a named attribute from the variant's `attributes` array. ```text title="Get attribute by name" $getAttribute(variant.attributes, "color") ``` ### Build derived values Complex expressions combine multiple fields, optional helper functions, and logic to produce derived values. Extract a numeric price amount: Use `$priceToAmount` to correctly account for the currency's `fractionDigits` value. ```text title="Extract numeric price" $priceToAmount(variant.price) ``` Alternatively, if you need manual control, divide `centAmount` by the appropriate power of 10 based on `fractionDigits`: ```text title="Manual fractionDigits conversion" variant.price.value.centAmount / $power(10, variant.price.value.fractionDigits) ``` Return a formatted price string: If your template provides `$formatPrice`, you can format the same scoped `price` value. ```text title="Format price string" $formatPrice(variant.price) ``` Build a title from the product name and variant attributes: Combine the localized product name with custom attribute values to produce a richer title string. ```text title="Build composite title" $lookup(productData.name, $locale) & " - " & $getAttribute(variant.attributes, "color") & " / " & $string($getAttribute(variant.attributes, "size")) ``` If an expression evaluates to `null` or `undefined`, no value is included in the feed for that field. The effect depends on the field and the provider: - For required fields, the provider fails to process the product. - For optional fields, the provider removes any existing value, depending on its implementation. Ensure your expressions handle missing data gracefully, for example, by providing fallback values with the JSONata `$default` operator or conditional logic. ## Related pages - [Area overview page with navigation](/agentic-commerce.md) - [Previous page: Manage agentic channels](/agentic-commerce/ai-hub/agentic-channels.md) - [Next page: Checkout extensibility](/agentic-commerce/ai-hub/checkout-extensibility.md)