{"id":58115,"date":"2023-08-26T17:09:20","date_gmt":"2023-08-26T11:39:20","guid":{"rendered":"https:\/\/www.tothenew.com\/blog\/?p=58115"},"modified":"2024-06-10T15:34:38","modified_gmt":"2024-06-10T10:04:38","slug":"extending-cifcommerce-integration-framework-core-component","status":"publish","type":"post","link":"https:\/\/www.tothenew.com\/blog\/extending-cifcommerce-integration-framework-core-component\/","title":{"rendered":"Extending CIF(Commerce Integration Framework) Core Component"},"content":{"rendered":"<p>In continuation with our last\u00a0<a class=\"external-link\" href=\"https:\/\/www.tothenew.com\/blog\/install-and-configure-the-cif-add-on-in-aem-to-connect-venia-store\/\" rel=\"nofollow\">blog<\/a>\u00a0on setting up the Venia store, we will customize AEM CIF core components as per our needs.<\/p>\n<p>Adobe Experience Manager (AEM) is a powerful content management solution that enables businesses to deliver exceptional digital experiences. One of its key strengths lies in its Commerce Integration Framework (CIF) Core Components, which facilitates seamless integration of AEM with various commerce platforms. However, to truly stand out from the competition, businesses must go beyond the out-of-the-box features and embrace the art of customization. This blog will explore the benefits of customizing AEM CIF Core Components and guide you through unlocking their full potential.<\/p>\n<p>So far, we have installed and configured the CIF add-on to our local AEM instance and connected it to the Venia store.<\/p>\n<p>Prerequisite:-<\/p>\n<ul>\n<li>AEM instance with CIF add-on<\/li>\n<li>Magento Commerce setup with Venia store<\/li>\n<li>Clone AEM CIF Venia Project: The Venia project can be cloned from Adobe\u2019s official\u00a0<a class=\"external-link\" href=\"https:\/\/github.com\/adobe\/aem-cif-guides-venia\" rel=\"nofollow\">GitHub repo<\/a>.<\/li>\n<\/ul>\n<h3>Use case<\/h3>\n<p>In this blog, we will be focusing on the Product Carousel component to show an \u201con-sale\u201d icon based on a custom attribute in Magento products. Currently, the Product Carousel component looks like this, and we will add an on-sale icon next to the carousel heading.<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone wp-image-58415 size-large\" src=\"\/blog\/wp-ttn-blog\/uploads\/2023\/08\/5-1-1-1024x309.png\" alt=\"\" width=\"625\" height=\"189\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2023\/08\/5-1-1-1024x309.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2023\/08\/5-1-1-300x91.png 300w, \/blog\/wp-ttn-blog\/uploads\/2023\/08\/5-1-1-768x232.png 768w, \/blog\/wp-ttn-blog\/uploads\/2023\/08\/5-1-1-1536x464.png 1536w, \/blog\/wp-ttn-blog\/uploads\/2023\/08\/5-1-1-2048x619.png 2048w, \/blog\/wp-ttn-blog\/uploads\/2023\/08\/5-1-1-624x188.png 624w\" sizes=\"(max-width: 625px) 100vw, 625px\" \/><\/p>\n<p>After the changes to the core component, the Product Carousel component will show an on-sale icon if any of the products contain the on-sale attribute; this is how it would look.<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone wp-image-58416 size-large\" src=\"\/blog\/wp-ttn-blog\/uploads\/2023\/08\/4-1-1-1024x285.png\" alt=\"\" width=\"625\" height=\"174\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2023\/08\/4-1-1-1024x285.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2023\/08\/4-1-1-300x84.png 300w, \/blog\/wp-ttn-blog\/uploads\/2023\/08\/4-1-1-768x214.png 768w, \/blog\/wp-ttn-blog\/uploads\/2023\/08\/4-1-1-1536x428.png 1536w, \/blog\/wp-ttn-blog\/uploads\/2023\/08\/4-1-1-2048x571.png 2048w, \/blog\/wp-ttn-blog\/uploads\/2023\/08\/4-1-1-624x174.png 624w\" sizes=\"(max-width: 625px) 100vw, 625px\" \/><\/p>\n<h3>Why Customize AEM CIF Core Components?<\/h3>\n<ol>\n<li><strong>Tailored User Experience<\/strong>: Customization allows you to create unique and personalized user experiences that align with your brand identity and customer preferences. Tailoring the components to specific target audiences can significantly improve engagement and conversion rates.<\/li>\n<li><strong>Enhanced Functionality<\/strong>: The out-of-the-box CIF Core Components provide a solid foundation, but every business has unique requirements. Customization empowers you to add new features, modify existing functionalities, or integrate third-party tools seamlessly.<\/li>\n<li><strong>Performance Optimization<\/strong>: By stripping away unnecessary code and functionalities, you can optimize the performance of CIF Core Components to deliver faster-loading pages, ensuring a smooth user experience.<\/li>\n<li><strong>Scalability and Future-Proofing<\/strong>: Customizing CIF Core Components allows you to future-proof your digital ecosystem. As your business evolves, you can quickly adapt the components to match new requirements without starting from scratch.<\/li>\n<\/ol>\n<h3>Steps to Customize AEM CIF Core Components<\/h3>\n<p><strong>1.<\/strong> First, we will add a custom attribute to the products in Adobe Commerce. The following are the steps to add a custom attribute &#8220;on_sale&#8221; to a product.<\/p>\n<p><strong>a.<\/strong> Navigate to Magento Admin Console &gt; Catalog &gt; Products.<br \/>\n<strong>b.<\/strong> Search for the product and edit it to add the custom attribute e.g., product code: VA24<br \/>\n<strong>c.<\/strong> Check the Graphql response using a\u00a0<a class=\"external-link\" href=\"https:\/\/studio.apollographql.com\/sandbox\/explorer\" rel=\"nofollow\">Graphql IDE<\/a>. eg.<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone wp-image-58417 size-large\" src=\"\/blog\/wp-ttn-blog\/uploads\/2023\/08\/3-1-1-1024x456.png\" alt=\"\" width=\"625\" height=\"278\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2023\/08\/3-1-1-1024x456.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2023\/08\/3-1-1-300x134.png 300w, \/blog\/wp-ttn-blog\/uploads\/2023\/08\/3-1-1-768x342.png 768w, \/blog\/wp-ttn-blog\/uploads\/2023\/08\/3-1-1-1536x684.png 1536w, \/blog\/wp-ttn-blog\/uploads\/2023\/08\/3-1-1-2048x912.png 2048w, \/blog\/wp-ttn-blog\/uploads\/2023\/08\/3-1-1-624x278.png 624w\" sizes=\"(max-width: 625px) 100vw, 625px\" \/><\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone wp-image-58418 size-large\" src=\"\/blog\/wp-ttn-blog\/uploads\/2023\/08\/2-1-1-1024x262.png\" alt=\"\" width=\"625\" height=\"160\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2023\/08\/2-1-1-1024x262.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2023\/08\/2-1-1-300x77.png 300w, \/blog\/wp-ttn-blog\/uploads\/2023\/08\/2-1-1-768x197.png 768w, \/blog\/wp-ttn-blog\/uploads\/2023\/08\/2-1-1-1536x394.png 1536w, \/blog\/wp-ttn-blog\/uploads\/2023\/08\/2-1-1-2048x525.png 2048w, \/blog\/wp-ttn-blog\/uploads\/2023\/08\/2-1-1-624x160.png 624w\" sizes=\"(max-width: 625px) 100vw, 625px\" \/><\/p>\n<pre>query Products($filter: ProductAttributeFilterInput) {\r\nproducts(filter: { sku: { eq: \"VA24\" } ) {\r\nitems {\r\nname\r\nsku\r\non_sale\r\n}\r\n}\r\n}<\/pre>\n<p>The response should be like this:-<\/p>\n<pre>{\r\n\"data\": {\r\n\"products\": {\r\n\"items\": [\r\n{\r\n\"name\": \"Night Out Collection\",\r\n\"sku\": \"VA24\",\r\n\"on_sale\": 1\r\n}\r\n]\r\n}\r\n}\r\n}<\/pre>\n<p><strong>2.<\/strong> Create a Custom Component: To avoid modifying the core code directly, create a custom AEM component that inherits from the CIF Core Component you wish to customize. This approach ensures that your changes are isolated and maintainable.<\/p>\n<p><span class=\"confluence-embedded-file-wrapper confluence-embedded-manual-size\"><img decoding=\"async\" class=\"confluence-embedded-image\" src=\"https:\/\/confluence.tothenew.com\/download\/attachments\/94459204\/image-2023-8-11_10-54-40-1.png?version=1&amp;modificationDate=1691731482000&amp;api=v2\" alt=\"\" height=\"250\" data-image-src=\"\/download\/attachments\/94459204\/image-2023-8-11_10-54-40-1.png?version=1&amp;modificationDate=1691731482000&amp;api=v2\" data-unresolved-comment-count=\"0\" data-linked-resource-id=\"94459208\" data-linked-resource-version=\"1\" data-linked-resource-type=\"attachment\" data-linked-resource-default-alias=\"image-2023-8-11_10-54-40-1.png\" data-base-url=\"https:\/\/confluence.tothenew.com\" data-linked-resource-content-type=\"image\/png\" data-linked-resource-container-id=\"94459204\" data-linked-resource-container-version=\"5\" \/><img decoding=\"async\" loading=\"lazy\" class=\"alignnone wp-image-58419 size-full\" src=\"\/blog\/wp-ttn-blog\/uploads\/2023\/08\/1-1-1.png\" alt=\"\" width=\"534\" height=\"180\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2023\/08\/1-1-1.png 534w, \/blog\/wp-ttn-blog\/uploads\/2023\/08\/1-1-1-300x101.png 300w\" sizes=\"(max-width: 534px) 100vw, 534px\" \/><\/span><\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone wp-image-58414 size-full\" src=\"\/blog\/wp-ttn-blog\/uploads\/2023\/08\/6-2.png\" alt=\"\" width=\"2274\" height=\"360\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2023\/08\/6-2.png 2274w, \/blog\/wp-ttn-blog\/uploads\/2023\/08\/6-2-300x47.png 300w, \/blog\/wp-ttn-blog\/uploads\/2023\/08\/6-2-1024x162.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2023\/08\/6-2-768x122.png 768w, \/blog\/wp-ttn-blog\/uploads\/2023\/08\/6-2-1536x243.png 1536w, \/blog\/wp-ttn-blog\/uploads\/2023\/08\/6-2-2048x324.png 2048w, \/blog\/wp-ttn-blog\/uploads\/2023\/08\/6-2-624x99.png 624w\" sizes=\"(max-width: 2274px) 100vw, 2274px\" \/><\/p>\n<p><strong>3<\/strong>. Now, we will extend the current sling model of the core component Product Carousel by following the <a class=\"external-link\" href=\"https:\/\/github.com\/adobe\/aem-core-wcm-components\/wiki\/Delegation-Pattern-for-Sling-Models\" rel=\"nofollow\">delegation pattern for Sling Models<\/a>. First, we will create a ProviderType interface that extends the ConsumerType interface of the core component with the additional functionality we want to add in our case, it would be the onSale method.<\/p>\n<div class=\"code panel pdl conf-macro output-block\" data-hasbody=\"true\" data-macro-name=\"code\">\n<div class=\"codeHeader panelHeader pdl\"><b>CustomProductCarousel<\/b><\/div>\n<div><\/div>\n<pre class=\"syntaxhighlighter sh-confluence nogutter java\">@ProviderType\r\npublic\u00a0interface\u00a0CustomProductCarousel\u00a0extends\u00a0ProductCarousel {\r\n\u00a0\u00a0\u00a0\u00a0public\u00a0boolean\u00a0onSale();\r\n}<\/pre>\n<\/div>\n<div class=\"code panel pdl conf-macro output-block\" data-hasbody=\"true\" data-macro-name=\"code\">\n<div><\/div>\n<div class=\"codeHeader panelHeader pdl\"><b>CustomProductCarouselImpl<\/b><\/div>\n<div><\/div>\n<\/div>\n<pre>@Model(adaptables = SlingHttpServletRequest.class, adapters = CustomProductCarousel.class, resourceType = CustomProductCarouselImpl.RESOURCE_TYPE)\r\npublic class CustomProductCarouselImpl implements CustomProductCarousel {\r\n\r\n\u00a0\u00a0\u00a0\u00a0private\u00a0static\u00a0final\u00a0Logger LOGGER = LoggerFactory.getLogger(CustomProductCarouselImpl.class);\r\n\u00a0\u00a0 \u00a0private\u00a0static\u00a0final\u00a0String RESOURCE_TYPE =\u00a0\"venia\/components\/commerce\/productcarousel\";\r\n \u00a0\u00a0\u00a0private static final String ON_SALE_ATTRIBUTE = \"on_sale\";\r\n\u00a0\u00a0\u00a0\u00a0@Self\r\n\u00a0\u00a0\u00a0\u00a0@Via(type = ResourceSuperType.class)\r\n \u00a0\u00a0\u00a0private\u00a0ProductCarousel productCarousel;\r\n \u00a0\u00a0\u00a0private\u00a0AbstractProductsRetriever productsRetriever;\r\n\u00a0\u00a0\u00a0\u00a0@PostConstruct\r\n\u00a0\u00a0\u00a0\u00a0public\u00a0void\u00a0initModel() {\r\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0productsRetriever = productCarousel.getProductsRetriever();\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if\u00a0(productsRetriever !=\u00a0null) {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ Pass your custom partial query to the ProductRetriever. This class will\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ automatically take care of executing your query as soon\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ as you try to access any product property.\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0productsRetriever.extendProductQueryWith(productInterfaceQuery -&gt; productInterfaceQuery.addCustomSimpleField(ON_SALE_ATTRIBUTE));\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\r\n \u00a0\u00a0\u00a0}\r\n\u00a0\u00a0\u00a0\u00a0@Override\r\n\u00a0\u00a0\u00a0\u00a0public\u00a0boolean\u00a0onSale() {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return\u00a0productsRetriever.fetchProducts().stream().anyMatch(productInterface -&gt; {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0try\u00a0{\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return\u00a0productInterface.getAsInteger(ON_SALE_ATTRIBUTE) ==\u00a01;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\u00a0catch\u00a0(SchemaViolationError e) {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0LOGGER.error(\"Error retrieving on sale attribute\");\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return\u00a0false;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0});\r\n \u00a0\u00a0\u00a0}\r\n\u00a0\u00a0\u00a0\u00a0@Override\r\n\u00a0\u00a0\u00a0\u00a0public\u00a0List&lt;ProductListItem&gt; getProducts() {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return\u00a0productCarousel.getProducts();\r\n \u00a0\u00a0\u00a0}\r\n\u00a0\u00a0\u00a0\u00a0@Override\r\n\u00a0\u00a0\u00a0\u00a0public\u00a0List&lt;ProductListItem&gt; getProductIdentifiers() {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return\u00a0productCarousel.getProductIdentifiers();\r\n \u00a0\u00a0\u00a0}\r\n\u00a0\u00a0\u00a0\u00a0@Override\r\n\u00a0\u00a0\u00a0\u00a0public\u00a0AbstractProductsRetriever getProductsRetriever() {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return\u00a0productsRetriever;\r\n \u00a0\u00a0\u00a0}\r\n\u00a0\u00a0\u00a0\u00a0@Override\r\n\u00a0\u00a0\u00a0\u00a0public\u00a0boolean\u00a0isConfigured() {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return\u00a0productCarousel.isConfigured();\r\n \u00a0\u00a0\u00a0}\r\n\u00a0\u00a0\u00a0\u00a0@Override\r\n\u00a0\u00a0\u00a0\u00a0public\u00a0String getTitleType() {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return\u00a0productCarousel.getTitleType();\r\n\u00a0\u00a0\u00a0\u00a0}\r\n}<\/pre>\n<p class=\"auto-cursor-target\">In the above code, the delegation pattern in Sling Models enables MyProductTeaserImpl to use the ProductTeaser model by utilizing the sling:resourceSuperType attribute. For functions you wish to keep as-is without modifications, you can mirror the output of the corresponding ProductCarousel method. In the PostConstruct method, we get the AbstractProductsRetriever object in our model and then extend\u00a0the Products query with the custom attribute\u00a0<strong>&#8220;on_sale.&#8221;<\/strong> This way, when the query is executed, it will fetch the on_sale attribute of those products with the other data from graphQL. We have also created a method called \u201conSale,\u201d which will retrieve attribute values from the products and check if any products have enabled it.<\/p>\n<p class=\"auto-cursor-target\"><strong>4.<\/strong> Next, we will customize the markup and styles of the component to show the on-sale icon. First, we will modify the HTML to show the on-sale icon next to the Product Carousel heading.<br \/>\nAs per the current structure, we will modify two HTML files as follows:-<\/p>\n<p class=\"auto-cursor-target\"><strong>a<\/strong>. apps\/venia\/components\/commerce\/productcarousel\/productcarousel.html<\/p>\n<div class=\"code panel pdl conf-macro output-block\" data-hasbody=\"true\" data-macro-name=\"code\">\n<div class=\"codeHeader panelHeader pdl\"><b>productcarousel<\/b><\/div>\n<div><\/div>\n<\/div>\n<pre>&lt;sly\u00a0data-sly-use.carousel=\"${'com.venia.core.models.commerce.CustomProductCarouselImpl' @product=properties.product}\"\r\n\u00a0\u00a0\u00a0\u00a0\u00a0data-sly-use.templates=\"core\/wcm\/components\/commons\/v1\/templates.html\"\r\n\u00a0\u00a0\u00a0\u00a0\u00a0data-sly-use.carouselTpl=\"carousel.html\"\u00a0\/&gt;\r\n\r\n\r\n&lt;sly\u00a0data-sly-test.hasProducts=\"${carousel.isConfigured &amp;&amp; carousel.products}\"\r\n\u00a0\u00a0\u00a0\u00a0\u00a0data-sly-call=\"${carouselTpl.carousel @ carousel = carousel, items = carousel.products, componentType='productcarousel'}\"&gt;&lt;\/sly&gt;\r\n\r\n\r\n&lt;sly\u00a0data-sly-call=\"${templates.placeholder @ isEmpty = !carousel.isConfigured}\"\u00a0\/&gt;\r\n&lt;sly\u00a0data-sly-call=\"${templates.placeholder @\u00a0isEmpty\u00a0=\u00a0carousel.isConfigured\r\n&amp;&amp; !hasProducts,\u00a0emptyTextAppend\u00a0=\u00a0'Configured, but no products to display'}\" \/&gt;<\/pre>\n<p class=\"auto-cursor-target\"><strong>b.<\/strong> apps\/venia\/components\/commerce\/productcarousel\/carousel.html<\/p>\n<div class=\"code panel pdl conf-macro output-block\" data-hasbody=\"true\" data-macro-name=\"code\"><\/div>\n<div class=\"code panel pdl conf-macro output-block\" data-hasbody=\"true\" data-macro-name=\"code\">\n<div class=\"codeContent panelContent pdl\">\n<div>\n<div id=\"highlighter_733225\" class=\"syntaxhighlighter sh-confluence nogutter xml\"><b>carousel<\/b><\/div>\n<\/div>\n<\/div>\n<\/div>\n<pre>&lt;template\u00a0data-sly-template.carousel=\"${@ carousel, items, componentType}\"\u00a0data-sly-use.cardTpl=\"card.html\"&gt;\r\n\u00a0\u00a0\u00a0\u00a0&lt;sly\u00a0data-sly-test.type=\"${componentType ? componentType : 'carousel'}\"\u00a0\/&gt;\r\n\u00a0\u00a0\u00a0\u00a0&lt;div\u00a0id=\"${carousel.id}\"\u00a0data-comp-is=\"${type}\"\u00a0class=\"${type}__container\"\u00a0data-cmp-data-layer=\"${carousel.data.json}\"&gt;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;div\u00a0class=\"${type}__titlecontainer\"&gt;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;h2\u00a0data-sly-element=\"${carousel.titleType}\"\u00a0data-sly-test=\"${properties.jcr:title}\"\u00a0class=\"${type}__title\"&gt;${properties.jcr:title}&lt;\/h2&gt;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;!-- This is the span tag added for the on-sale icon.--&gt;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;span\u00a0data-sly-test=\"${carousel.onSale}\"\u00a0class=\"${type}__sale\"&gt;sale&lt;\/span&gt;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;\/div&gt;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;button\u00a0data-carousel-action='prev'\u00a0class=\"${type}__btn ${type}__btn--prev\"\u00a0type=\"button\"\u00a0title=\"${'Show previous' @ i18n}\"\u00a0aria-label=\"${'Show previous' @ i18n}\"\u00a0style=\"display: none;\"&gt;&lt;\/button&gt;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;button\u00a0data-carousel-action='next'\u00a0class=\"${type}__btn ${type}__btn--next\"\u00a0type=\"button\"\u00a0title=\"${'Show next' @ i18n}\"\u00a0aria-label=\"${'Show next' @ i18n}\"\u00a0style=\"display: none;\"&gt;&lt;\/button&gt;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;div\u00a0class=\"${type == 'carousel' ? '{0}__cardsroot' : '{0}__root' @ format=[type]}\"&gt;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;div\u00a0class=\"${type}__parent\"&gt;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;div\u00a0class=\"${type}__cardscontainer\"\u00a0data-sly-list.item=\"${items ? items : carousel.items}\"&gt;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;sly\u00a0data-sly-call=\"${cardTpl.card @ item=item, carousel=carousel}\"\/&gt;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;\/div&gt;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;\/div&gt;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;\/div&gt;\r\n\u00a0\u00a0\u00a0\u00a0&lt;\/div&gt;\r\n&lt;\/template&gt;<\/pre>\n<p class=\"auto-cursor-target\">Now, Accordingly, make the changes in the scss file of the component to show the on-sale icon next to the heading of the carousel. The changes can be made to the following file in the ui.frontend module src\/main\/styles\/commerce\/_productcarousel.scss<\/p>\n<p>Finally, we can see the on-sale icon in the product carousel component.<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone wp-image-58416 size-large\" src=\"\/blog\/wp-ttn-blog\/uploads\/2023\/08\/4-1-1-1024x285.png\" alt=\"\" width=\"625\" height=\"174\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2023\/08\/4-1-1-1024x285.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2023\/08\/4-1-1-300x84.png 300w, \/blog\/wp-ttn-blog\/uploads\/2023\/08\/4-1-1-768x214.png 768w, \/blog\/wp-ttn-blog\/uploads\/2023\/08\/4-1-1-1536x428.png 1536w, \/blog\/wp-ttn-blog\/uploads\/2023\/08\/4-1-1-2048x571.png 2048w, \/blog\/wp-ttn-blog\/uploads\/2023\/08\/4-1-1-624x174.png 624w\" sizes=\"(max-width: 625px) 100vw, 625px\" \/><\/p>\n<h3>Conclusion<\/h3>\n<p>Customizing AEM CIF Core Components gives businesses a competitive edge in delivering personalized and exceptional digital experiences. You can optimize performance, enhance functionality, and future-proof your digital ecosystem by tailoring components to match your unique requirements. Remember to follow best practices, test thoroughly, and document your customizations to ensure a smooth development process. Embrace the power of personalization and elevate your digital presence with AEM CIF Core Components customization.<\/p>\n<p>Stay tuned for our blogs on various other topics.<\/p>\n<p><strong>References:<\/strong><\/p>\n<p><a class=\"external-link\" href=\"https:\/\/experienceleague.adobe.com\/docs\/experience-manager-cloud-service\/content\/content-and-commerce\/storefront\/developing\/customize-cif-components.html\" rel=\"nofollow\">https:\/\/experienceleague.adobe.com\/docs\/experience-manager-cloud-service\/content\/content-and-commerce\/storefront\/developing\/customize-cif-components.html<\/a><\/p>\n<div class=\"ap-custom-wrapper\"><\/div><!--ap-custom-wrapper-->","protected":false},"excerpt":{"rendered":"<p>In continuation with our last\u00a0blog\u00a0on setting up the Venia store, we will customize AEM CIF core components as per our needs. Adobe Experience Manager (AEM) is a powerful content management solution that enables businesses to deliver exceptional digital experiences. One of its key strengths lies in its Commerce Integration Framework (CIF) Core Components, which facilitates [&hellip;]<\/p>\n","protected":false},"author":1626,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"iawp_total_views":73},"categories":[5868],"tags":[5059,4847,5008,5557,5555,5556,912],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/58115"}],"collection":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/users\/1626"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/comments?post=58115"}],"version-history":[{"count":5,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/58115\/revisions"}],"predecessor-version":[{"id":59433,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/58115\/revisions\/59433"}],"wp:attachment":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/media?parent=58115"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/categories?post=58115"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/tags?post=58115"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}