---
updatedAt: 2026-01-22T11:10:01.000Z
---

# SAP Hybris

[Extension files](https://support.dynamicyield.com/hc/en-us/article_attachments/16674314040349)

The Dynamic Yield SAP Hybris integration is a quick and seamless way to implement Dynamic Yield. The integration takes care of the basic implementation of Dynamic Yield on your site (script, page context, e-commerce events, and product feed). Part of the setup requires technical knowledge of SAP Hybris.

## Prerequisites

* SAP Hybris version 1905 or higher.
* Standard Spring MVC/JSP/JS SAP Hybris application (Spartacus and Angular are not supported).

## Implementing Dynamic Yield on SAP Hybris

### Step 1: Create a Dynamic Yield section

A section in Dynamic Yield Experience OS represents your store's site in our system. Each section has an associated product feed, which is your product catalog. You'll configure the sync of the catalog/feed in the following steps.

To create the section, go to Experience OS and follow the directions in our support site article, [Managing Sections](https://support.dynamicyield.com/hc/en-us/articles/360022833894).

### Step 2: Install the Dynamic Yield extension

1. [Download the extension files](https://support.dynamicyield.com/hc/en-us/article_attachments/16674314040349) and save them locally.
2. Copy the folder into your root project to **/hybris/bin/custom/dynamicyieldintegration**. Push the folder to your repository to allow us to access the files for future updates.
3. Include the addonsupport extension in your localextensions.xml
   ```
   <extension name="addonsupport"/>
   ```
4. Include the extension in your **localextensions.xml**
   ```
   <extension name="dynamicyieldaddon"/>
   ```
5. Install the extension by using the following command:
   ```
   ant addoninstall -Daddonnames="dynamicyieldaddon"
       -DaddonStorefront.<storefrontTemplateName>="Storefront1"
   ```
   `Storefront1` is the name of your storefront, and `storefrontTemplateName` is the template name you are using
6. Rebuild the SAP system by running `ant clean all` from the **hybris/bin/platform** directory.

### Step 3: Enter the basic settings

1. Restart your SAP Hybris server and update the platform.
2. In SAP Hybris, go to **Backoffice › Administration Cockpit ›  System** and open **Dynamic Yield Integration**.
3. Create a new item in **Dynamic Yield Integration** by clicking **+**.

   1. Enter the **Site ID** of your Dynamic Yield site.

   2. If you are connecting to Dynamic Yield through our EU data center, select **Europe** as the CDN location and **Product Feed Upload Location**.

[block:image]{"images":[{"image":["https://files.readme.io/d289628-sap1.png","",""],"align":"center"}]}[/block]

4. Edit the item you just created and add the following attributes:

   1. The Product Feed’s S3 Access Key ID and Secret Access Key.

   2. Define the Sync rate of the Product Feed (default is 1 day).

   3. If you are using a custom CDN, specify the CDN Location and CDN Location Custom URL.

[block:image]{"images":[{"image":["https://files.readme.io/fa1cd2b-sap2.png","",""],"align":"center"}]}[/block]

### Step 4: Add the Dynamic Yield script to your site

The Dynamic Yield script is implemented within the Dynamic Yield extension, but needs to be included in the implementation of your storefront as follows:

1. Open the file that contains your main <head> tags in your storefront extension. By default, this is **master.tag**.
2. Include the `taglib` reference:
   ```
   <%@ taglib prefix="dynamicYieldIntegration" 
       tagdir="/WEB-INF/tags/addons/dynamicyieldaddon/responsive"
       %>
   ```
3. Add the main Dynamic Yield tag file as the first element within <head> tag:
   ```
   <dynamicYieldIntegration:dynamicyieldintegration />
   ```

### Step 5: Define the product feed export job

Define values for the properties that define your product catalog, base store, base site, and properties.

1. Go to Backoffice › Administration Cockpit › System › Dynamic Yield Integration › Product Export Job.
2. Replace the values in the following settings:

   * **Product Catalog Version:** Products from this catalog version will be exported.

   * **Base Store:** Base store of the products that are exported.

   * **Base Site:** Base site of the products that are exported. Its property UID will be used in identifying the URL of the product and product image.

   * **Properties:** Product properties that will be exported.

[block:image]{"images":[{"image":["https://files.readme.io/9914aa4-sap3.png","",""],"align":"center"}]}[/block]

### Step 6: Validate base site URL properties

Make sure that one property exists for every base site that is using Dynamic Yield. The properties must exist in the **.properties** file. By default, this is located in **local.properties** in the **config** folder of your project.

The format of the properties must be `website.{Base Site UID}.https`. For example:

```
website.electronics.https=https://electronics.local:9002/dynamicyieldintegrationstorefront
```

### Step 7: Validate your implementation

Verify that the implementation has been configured correctly in Settings › General Settings › Implementation Status. For more details, see [Validating Your Web Implementation](https://dy.dev/dy-dev/docs/validate-web).

## Technical details

The following sections contain details about how the extension handles page context, events, and the export job. No action is needed on your part, unless you have customized your implementation of SAP Hybris and need to customize the extension.

### Page context

The extension automatically adds the Page Context API to each of your pages via the extension’s **dynamicyieldcontextapi.tag** file. SAP Hybris adds this to the main `<head>` tag of your pages by default.

* **Homepage API:** Placed in pages where the `pageBodyCssClasses` has a class `page-homepage`.
* **Category Page API:** Placed in pages where the `pageBodyCssClasses` has a class `page-CategoryPage`.
* **Product Page API:** Placed on pages that have the product attribute within the model. This attribute is filled in the model in the backend controller of Hybris, only on product detail pages. By default, this is done in **ProductPageController.java**.
* **Other Page API:** Placed on all pages that don't match any of the conditions for the other page types.

### Events

The Dynamic Yield event API calls are automatically implemented by the extension. The data bindings are done in **dynamicyieldjsvariables.tag**, and the event logic is implemented in **dynamicyieldaddon.js**.

There are twelve events:

<details>
<summary><strong>Purchase</strong></summary>

This event is fired when a visitor purchases a product by completing the last step in the checkout process, after which they are redirected to the order confirmation page.

All the necessary data is taken from `orderData` attribute from the model, on the order confirmation page. By default, this attribute is filled in **AccountPageController.java**.

This event triggers in one of the following cases:

* There is a `DIV` element with the class `place-order-form` and a form within it that is submitted.
* There is a `FORM` element with the class `place-order-form` that is submitted.

Additionally, when the customer is redirected to order confirmation page, the class` page-orderConfirmationPage` should be present on the page.

</details>

<details>
<summary><strong>Add to Cart</strong></summary>

This event is fired every time the customer successfully adds a product to cart. It may occur on three types of pages by default:

* Product Details Page (Add to Cart button)
* Category Page (Add to Cart button next to a product)
* Search Results Page (Add to Cart button next to a product)

Technically, the event triggers when any `FORM` with the class `add_to_cart_form` is submitted.

The data binding on the product details page is done from the `product` attribute from the model (**ProductPageController.java**) as well as from the `cartData` attribute from the model (custom **DynamicYieldControllerAdvice.java**). Additionally, quantity is taken from the `frontend` element with the class `js-qty-selector-input`.

The data binding on other pages is done from the front-end elements.

* For `productCode`, `INPUT` with the attribute `name ="productCodePost"` is used.
* For `productPrice`, `INPUT` with the attribute `input[name ="productPostPrice"` is used.
* For `productCurrency`, the `MAIN` element is used with the `attribute data-currency-iso-code`.

</details>

<details>
<summary><strong>Signup</strong></summary>

This event is fired upon visitor registration to the site as defined in the following scenarios:

* User successfully registers and `FORM` with the ID `#registerForm` is submitted.
* User is automatically logged in.

The data (hashed user email address) is taken from **DynamicYieldControllerAdvice.java**.

</details>

<details>
<summary><strong>Login</strong></summary>

This event is fired every time the visitor logs into the account. This is when the `FORM` with the ID `#loginForm` is submitted, and the user successfully logs in.

The data (hashed user email) is taken from **DynamicYieldControllerAdvice.java**.

</details>

<details>
<summary><strong>Newsletter Subscription</strong></summary>

This event is fired every time the visitor signs up for a newsletter. Technically, this is when a `LABEL` that has a `FOR` attribute with the value `MARKETING_NEWSLETTER` and a class `toggle-button__switch` is turned on.

In Hybris, by default, this occurs in the example Consent Page (My Account › Consent Management), when the visitor turns the example context element to true.

The data (hashed user email) is taken from **DynamicYieldControllerAdvice.java**.

</details>

<details>
<summary><strong>Remove from Cart</strong></summary>

This event is fired every time a visitor removes an item from the cart.

The data binding is done on the Cart page.

The event is triggered when the user clicks the `LI` element with the class `js-execute-entry-action-button` on a Cart page (remove from cart button).

* **Product ID** is taken from the `data-entry-product-code` element within the `LI` element.
* **Quantity** is taken from the `data-entry-initial-quantity` element within the `LI` element.
* For **productCurrency**, `MAIN` element is used with the attribute `data-currency-iso-code`.
* The other values are taken from the `cartData` attribute in the model.

</details>

<details>
<summary><strong>Sync Cart Content</strong></summary>

This event is fired every time the visitor starts a new session. For this, `sessionStorage` is used with custom attributes.

Data binding is done from the `cartData` attribute in the model.

</details>

<details>
<summary><strong>Sort Items</strong></summary>

This event is fired every time a visitor changes the sorting options on a product listing page (category page).

The event is triggered when the `FORM` with the ID `sortForm1` or `sortForm2` (top and bottom commerce sorting forms) within the `DIV` element with the class `sort-refine-bar` is changed (select box element within it is changed).

The data is taken from the select box elements. In default commerce accelerators, the select boxes are filled with `SolrSort` item values. Based on whether the item in its code contains `-asc` or `-desc`, the sorting is done in ascending or descending order. This logic is also checked in the event, and based on that, the sortOrder is filled.

`sortBy` is taken from the value of the selected option within the form (select box).

</details>

<details>
<summary><strong>Filter Items</strong></summary>

This event is fired every time a visitor filters the items on a product listing page (category page).

The event is triggered when the checkbox with the class `js-facet-checkbox` within the `DIV` element with the `class js-product-facet` is marked.

Data binding is done from the `searchPageData` attribute within the model, filled in `AbstractSearchPageController` (searchPageData.facets).

`facetElement` is the element closest to the triggered checkbox, which has a class `js-facet`. Then, `filterType` is taken based on this element and all facet codes.

`filterStringValue` and `filterNumericValue` are taken from the element with the class `facet_list_text`.

</details>

<details>
<summary><strong>Change Attribute</strong></summary>

This event is fired every time a visitor filters the items on a product listing page (category page).

This event is fired every time a visitor changes a product attribute on a product page. By default, this can occur in two scenarios:

* A visitor clicks the picture icon of a different variant (for example, style). The event in this scenario is triggered when the user clicks the `LI` element within a `DIV` that includes the class `variant-selector`.
* A visitor selects a different variant in the selection box (for example, size). The event in this scenario is triggered when the selection box with the class `variant-select` is changed.

The data binding is done from the product attribute within the model (product.baseOptions).

</details>

<details>
<summary><strong>Promo Code Entered</strong></summary>

This event is fired every time a visitor successfully uses a promo code (cart page).

The event is triggered when the `INPUT` with the ID `js-voucher-code-text` within the `FORM` with the ID `applyVoucherForm` is submitted, and the code is applied successfully (parent element of the element with the `class js-voucher-validation-container` does not have the class `has-error`).

`Promo code` is taken from the voucher element itself (input text with the ID **js-voucher-code-text**).

</details>

<details>
<summary><strong>Search</strong></summary>

This event is fired every time a visitor runs a free-style keyword search.

The event is triggered when the `FORM` with the `NAME` attribute `search_form_SearchBox` is submitted.

Search text is taken from the element with the ID `js-site-search-input`.

</details>

### Exported product properties

The following properties are included by default for each product in the product export job. The item is of type `DynamicYieldExportProperty`.

* **sku:** The product's unique identifier.
* **name:** The product's name.
* **url:** The URL to the product details page.
* **group\_id:** Identifies a group of products that differ in some product attributes.
* **price:** The product price.
* **in\_stock:** Indicates that the product is in stock.
* **categories:** The categories associated with the product, from general to specific.
* **image\_url:** The URL to the product image.
* **keywords:** Any additional information describing the product, separated by pipes.

You can include additional properties by creating them in ProductExportJob.properties and filling in the value. If the value provider must be used, it should be written in the same way the current providers are and referenced within the spring configuration.

The following attributes are included within each of the listed product properties:

* **Product Property name:** Represents the property name from the product. This name is relevant only if the mapping of the property Product - Dynamic Yield is done 1:1. This means that the value of this product property will be mapped directly to the Dynamic Yield property. In all other cases, this attribute is irrelevant.
* **DY Property name:** Represents the Dynamic Yield property name.
* **Export activated:** This determines if the property will be included in the export.
* **Is Multi-Language:** This determines if the property is multi-language. If it is, it will be exported for every language in the system that is Active (both in the header and the value row of the export CSV file).
* **Is Mandatory:** This determines if the property is mandatory for the export. If the value is true, product will not be exported if this property is empty (null or ““).
* **Value Provider bean ID:** This contains the ID of the value provider bean that provides the custom logic for exporting the property. If this field is not empty, the specified value provider bean will be used. Since all properties have to be represented in the CSV report as either Strings or Integers, value provider beans are necessary if we want to map our custom property and logic and present it in the report. There are examples of some of the current properties that can be analyzed.

### Export process

The export process is run automatically, with no action required on your part. The export process is run by the Product Export Job.

If the job finishes successfully, **productfeed.csv** is created and uploaded to your AWS S3 folder (using the Access Key and Secret Access Key you provided). The bucket name and location are determined automatically, based on other Dynamic Yield Integration parameters (Site ID, Use European Scripts). Additionally, productfeed.csv will be saved on the server in **hybris/data/dynamicyieldintegration/export**. In both cases, only the latest exported file will be saved.

If something goes wrong in the export process, it will be logged in the console log with the complete message. If the product is not exported because of some empty field, it will be logged in the console log in the form `PRODUCT NOT EXPORTED! Product code: %productCode, empty attribute: %propertyName`. Only the first empty mandatory property is logged, for performance reasons.

If the file limit is exceeded, the export will finish without error and log the message `Builder limit exceeded! Number of appended products %numberOfProducts`.

There is also a possible scenario that java heap memory runs out. This happened in a test environment when the product count was over 2200000. In this case, the process will fail, and the log message will be written in the console log. The recommended **tomcat.generaloptions** setting in the server for stable work should be at least\
**-Xmx8G**.

The period and trigger of the cronjob execution is set automatically, based on the Sync Rate setting in Dynamic Yield Integration. The default is 1 day (every 24h).

If you do not want the cronjob to run automatically, the Sync Rate should be set to n/a (empty value).