Note: If you do not use SAP Commerce as your eCommerce platform, use the generic implementation guidelines.
The Dynamic Yield SAP Commerce extension is a quick and seamless way to implement Dynamic Yield. The extension takes care of the basic implementation of Dynamic Yield on the site (script, page context, eCommerce events, and product feed). Part of the setup requires technical knowledge of SAP Commerce.
Prerequisites
- SAP Commerce version 1905 or higher.
- Standard Spring MVC/JSP/JS SAP Commerce application (Spartacus and Angular are not supported).
Implementing Dynamic Yield on SAP Commerce
1. Create a Dynamic Yield Site
- Click the dropdown arrow on your site name at the top left of the screen and click Create.
- Choose a name for your site
- Select Website as the platform type.
- Enter the URL of your site.
- Select SAP Hybris as the eCommerce platform.
- In the Localization section, select the currency which will be used in all Dynamic Yield revenue-based reports.
- Click Create. You will receive an email with your site ID, access key, and secret access key. These are needed later in the implementation process.
2. Install the Dynamic Yield Extension
- Download the Extension.
- 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.
- Include the addonsupport extension in your localextensions.xml
<extension name="addonsupport"/>
- Include the extension in your localextensions.xml
<extension name="dynamicyieldaddon"/>
- Install the extension by using the following command:
Storefront1 is the name of your storefront, and storefrontTemplateName is the template name you are using.ant addoninstall -Daddonnames="dynamicyieldaddon" -DaddonStorefront.<storefrontTemplateName>="Storefront1"
- Rebuild the SAP system by running ant clean all from the hybris/bin/platform directory.
3. Enter the Basic Settings
- Restart your SAP Commerce server and update the platform.
- In SAP Commerce, go to Backoffice › Administration Cockpit › System and open Dynamic Yield Integration.
- Create a new item in Dynamic Yield Integration by clicking +.
- Enter the Site ID of your Dynamic Yield site.
- If you are connecting to Dynamic Yield through our EU data center, select Europe as the CDN location and Product Feed Upload location.
- Edit the item you just created and add the following attributes:
- The Product Feed’s S3 Access Key ID and Secret Access Key.
- Define the Sync rate of the Product Feed (default is 1 day).
- If you are using a custom CDN, specify the CDN Location and CDN Location Custom URL.
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:
- Open the file that contains your main <head> tags in your storefront extension. By default, this is master.tag.
- Include taglib reference
<%@ taglib prefix="dynamicYieldIntegration" tagdir="/WEB-INF/tags/addons/dynamicyieldaddon/responsive" %>
- Add main Dynamic Yield tag file as the first element within <head> tag
<dynamicYieldIntegration:dynamicyieldintegration />
5. Define the Product Feed Export Job
Define values for the properties that define your product catalog, base store, base site, and properties.
- Go to Backoffice › Administration Cockpit › System › Dynamic Yield Integration › Product Export Job.
- 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.
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
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.
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 Commerce and need to customize the extension.
Page Context
The extension automatically adds the Page Context API to each of your pages by the extension’s dynamicyieldcontextapi.tag file. SAP Commerce 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 commerce, only on Product Detail Pages. By default, this is done in ProductPageController.java.
- Other Page API: Placed on all pages that do not match any of the conditions for the other page types.
Events
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 types of events.
This event is fired when the customer 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 in the page.
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 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 frontend element with the class js-qty-selector-input.
The data binding on other pages is done from the frontend elements.
- For productCode, INPUT with the attribute name ="productCodePost" is used.
- For productPrice, input with the attribute input[name ="productPostPrice" is used.
- For productCurrency, MAIN element is used with the attribute data-currency-iso-code.
The Event is fired upon visitor registration to the site as defined in the following scenario:
- User successfully registers and FORM with the id #registerForm is submitted.
- User is automatically logged in.
The data (hashed user email) is taken from DynamicYieldControllerAdvice.java.
This Event is fired every time the visitor logs into the account. This is defined as 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.
This Event is fired every time the visitor signs up to a newsletter. Technically this is defined as when a LABEL that has a FOR attribute with the value MARKETING_NEWSLETTER and a class toggle-button__switch is turned on.
In Commerce, by default, this occurs in the example Consent Page (My Account › Consent Management), when the customer turns the example context element to true.
The data (hashed user email) is taken from DynamicYieldControllerAdvice.java.
This Event is fired every time a visitor removes an item from cart.
The data binding is done on the Cart page.
The event is triggered when the user clicks on the LI element with class js-execute-entry-action-button on a Cart page (remove from cart button).
- Product ID is taken from data-entry-product-code element within the mentioned LI element.
- Quantity is taken from data-entry-initial-quantity element within the mentioned LI element.
- For productCurrency, MAIN element is used with the attribute data-currency-iso-code.
- The other values are taken from cartData attribute from the model.
This Event is fired every time the visitor starts a new session. For this, sessionStorage is used with custom attribute.
Data binding is done from cartData attribute from the model.
This Event is fired every time the visitor changes the sorting options on a product listing page (category page).
The event is triggered when the form with 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 if the item in its code contains -asc or -desc, the sorting will be done in ascending or descending order. This logic is as well checked in the event, and based on that the sortOrder will be filled.
sortBy is taken from the value of the selected option within the form (select box).
This Event is fired every time the 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 triggered.
Data is bind from the searchPageData attribute within the model, filled in AbstractSearchPageController (searchPageData.facets).
facetElement is the element closest do the triggered checkbox, that has a class js-facet. Then, filterType is taken based on this element and all facet codes.
filterStringValue/filterNumericValue are taken from the element with the class facet__list__text.
This Event is fired every time the visitor changes a product attribute on a Product page. By default, this can occur in two scenarios:
- Customer clicks on the picture icon of different variant (for example - style). The event for this case is triggered when user clicks on LI element within DIV that has class variant-selector.
- Customer chooses different variant in the select box (for example - size). The event for this case is triggered when the select box with the class variant-select is changed.
The data binding is done from the product attribute within the model (product.baseOptions).
This Event is fired every time the 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).
This Event is fired every time the 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.
Exported Product Properties
The following properties are included about each product in the Product Export Job by default. The item is of type DynamicYieldExportProperty
- sku: the product unique identifier
- name: the product 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: is the product 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 inside each of the product properties above:
- 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 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 will be 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 more than 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).