Live Search CIF 구성 요소 live-search-cif-component

Adobe Commerce 라이브 검색은 추가 비용 없이 빠르고, 관련성이 높고, 직관적인 검색 경험을 제공합니다. Adobe Sensei에서 제공하는 라이브 검색은 인공 지능과 머신 러닝 알고리즘을 사용하여 집계된 방문자 데이터를 심층 분석합니다. 이 데이터를 Adobe Commerce 카탈로그와 결합하면 연관성 있고 개인화된 쇼핑 경험이 구축됩니다.

이 항목에서는 AEM CIF 구성 요소를 사용하여 AEM 사이트에 Live Search PLP(제품 목록 페이지) 위젯을 구현하는 방법에 대해 설명합니다.

사전 요구 사항 prerequisites

이 항목에서는 사용자가 로컬 AEM 환경을 설정했다고 가정합니다.

PLP 구성 요소를 설치하려면 Live Search Popover CIF 구성 요소가 설치되어 있어야 합니다. PLP 위젯을 사용하려면 팝오버에 의해 생성된 브라우저 세션 변수가 필요합니다.

작성기 업데이트 update-composer

이벤트 모듈을 ui.frontend/package.json에 추가합니다.

27번 행에서 다음을 변경합니다.

...
  },

  "devDependencies": {

    "@babel/core": "^7.3.4",
...

끝:

...
  },
  "type": "module",
  "devDependencies": {
    "@adobe/magento-storefront-event-collector": "^1.5.4",
    "@adobe/magento-storefront-events-sdk": "^1.5.4",
    "@babel/core": "^7.3.4",
...

파일 변경 사항 files-changes

Live Search 기능을 사용하려면 여러 파일을 업데이트해야 합니다. 다음 파일을 편집합니다. 줄 번호는 여기에 표시된 것과 약간 다를 수 있습니다.

  • ui.apps/src/main/content/jcr_root/apps/venia/clientlibs/clientlib-cif/.content.xml

    embed 줄에 core.cif.productlist.v1을(를) 추가합니다.

    code language-none
    embed="[core.cif.components.common,core.cif.components.product.v3,core.cif.components.productcarousel.v1,core.cif.components.productcollection.v2,core.cif.components.productteaser.v1,core.cif.components.searchbar.v2,core.cif.components.header.v1,core.cif.components.carousel.v1,core.cif.components.categorycarousel.v1,core.cif.components.featuredcategorylist.v1,core.cif.components.storefront-events.v1,core.cif.components.extensions.product-recs.storefront-events-collector.v1,core.wcm.components.commons.site.link,core.cif.productlist.v1]"
    
  • ui.apps/src/main/content/jcr_root/apps/venia/components/commerce/productlist/clientlibs/.content.xml

    .content.xml 파일 만들기:

    code language-xml
    <?xml version="1.0" encoding="UTF-8"?>
    <jcr:root xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0"
      jcr:primaryType="cq:ClientLibraryFolder"
      allowProxy="{Boolean}true"
      categories="[core.cif.productlist.v1]"
      jsProcessor="[default:none,min:none]"/>
    
  • ui.apps/src/main/content/jcr_root/apps/venia/components/commerce/productlist/clientlibs/css.txt

    css.txt 파일 만들기:

    code language-text
    #base=css
    
    productlist.css
    
  • ui.apps/src/main/content/jcr_root/apps/venia/components/commerce/productlist/clientlibs/css/productlist.css

    productlist.css 파일 만들기

    code language-css
      /* #search-plp-root */
    
    html {
      font-size: 62.5% !important;
    }
    
    body {
      font-size: 1.6rem;
    }
    
    .root.container {
      max-width: inherit;
    }
    
    .container {
      margin-left: auto;
      margin-right: auto;
    }
    
    div.ds-sdk-sort-dropdown {
      z-index: 9;
    }
    
  • ui.apps/src/main/content/jcr_root/apps/venia/components/commerce/productlist/clientlibs/js.txt

    js.txt 파일 만들기:

    code language-text
    js/productlist.js
    
  • ui.apps/src/main/content/jcr_root/apps/venia/components/commerce/productlist/clientlibs/js/productlist.js

    productlist.js 파일 만들기:

    code language-javascript
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ~ Copyright 2023 Adobe
    ~
    ~ Licensed under the Apache License, Version 2.0 (the "License");
    ~ you may not use this file except in compliance with the License.
    ~ You may obtain a copy of the License at
    ~
    ~     http://www.apache.org/licenses/LICENSE-2.0
    ~
    ~ Unless required by applicable law or agreed to in writing, software
    ~ distributed under the License is distributed on an "AS IS" BASIS,
    ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    ~ See the License for the specific language governing permissions and
    ~ limitations under the License.
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    "use strict";
    
    class ProductList {
      constructor() {
        const stateObject = {
          categoryName: null,
          currentCategoryUrlPath: null,
        };
        this._state = stateObject;
        this._init();
      }
    
      _init() {
        this._initWidgetPLP();
      }
    
      _injectStoreScript(src) {
        const script = document.createElement("script");
        script.type = "text/javascript";
        script.src = src;
    
        document.head.appendChild(script);
      }
    
      async _getStoreData() {
        // get from session storage
        const sessionData = sessionStorage.getItem(
          "WIDGET_STOREFRONT_INSTANCE_CONTEXT"
        );
        // WIDGET_STOREFRONT_INSTANCE_CONTEXT is set from searchbar/clientlibs/js/searchbar.js
        // if not, we will need to retrieve from graphql separately here.
    
        if (sessionData) {
          this._state.dataServicesSessionContext = JSON.parse(sessionData);
          return;
        }
      }
    
      getStoreConfigMetadata() {
        const storeConfig = JSON.parse(
          document
            .querySelector("meta[name='store-config']")
            .getAttribute("content")
        );
    
        const { storeRootUrl } = storeConfig;
        const redirectUrl = storeRootUrl.split(".html")[0];
        return { storeConfig, redirectUrl };
      }
    
      async _initWidgetPLP() {
        if (!window.LiveSearchPLP) {
          const liveSearchPlpSrc =
            "https://plp-widgets-ui.magento-ds.com/v1/search.js";
          this._injectStoreScript(liveSearchPlpSrc);
          // wait until script is loaded
          await new Promise((resolve) => {
            const interval = setInterval(() => {
              if (window.LiveSearchPLP && window.LiveSearchAutocomplete) {
                // Widget expects LiveSearchAutocomplete already loaded to rely on data-service-graphql
                clearInterval(interval);
                resolve();
              }
            }, 200);
          });
        }
        await this._getStoreData();
        const { dataServicesSessionContext } = this._state;
        if (!dataServicesSessionContext) {
          console.log("no dataServicesSessionContext");
          return;
        }
    
        const root = document.getElementById("search-plp-root");
        if (!root) {
          console.log("plp root not found.");
          return;
        }
        // get dataset from root
        const categoryUrlPath = root.getAttribute("data-plp-urlPath") || "";
        const categoryName = root.getAttribute("data-plp-title") || "";
        const storeDetails = {
          environmentId: dataServicesSessionContext.environment_id,
          environmentType: dataServicesSessionContext.environment,
          apiKey: dataServicesSessionContext.api_key,
          websiteCode: dataServicesSessionContext.website_code,
          storeCode: dataServicesSessionContext.store_code,
          storeViewCode: dataServicesSessionContext.store_view_code,
          config: {
            pageSize: dataServicesSessionContext.page_size,
            perPageConfig: {
              pageSizeOptions: dataServicesSessionContext.page_size_options,
              defaultPageSizeOption:
                dataServicesSessionContext.default_page_size_option,
            },
            minQueryLength: dataServicesSessionContext.min_query_length,
            currencySymbol: dataServicesSessionContext.currency_symbol,
            currencyRate: dataServicesSessionContext.currency_rate,
            displayOutOfStock: dataServicesSessionContext.display_out_of_stock,
            allowAllProducts: dataServicesSessionContext.allow_all_products,
            locale: dataServicesSessionContext.locale,
            currentCategoryUrlPath: categoryUrlPath,
            categoryName,
            displayMode: "", // "" for plp || "PAGE" for category/catalog
          },
          context: {
            customerGroup: dataServicesSessionContext.customer_group,
          },
          route: ({ sku }) => {
            return `${
              this.getStoreConfigMetadata().redirectUrl
            }.cifproductredirect.html/${sku}`;
          },
          searchQuery: "search_query",
        };
        setTimeout(() => {
          console.log("init PLP");
          window.LiveSearchPLP({ storeDetails, root });
        }, 0);
      }
    }
    
    (function () {
      function onDocumentReady() {
        new ProductList({});
      }
    
      if (document.readyState !== "loading") {
        onDocumentReady();
      } else {
        document.addEventListener("DOMContentLoaded", onDocumentReady);
      }
    })();
    
  • ui.apps/src/main/content/jcr_root/apps/venia/components/commerce/productlist/productlist.html

    productlist.html 파일 만들기:

    code language-html
    <div
    data-sly-use.productList="com.adobe.cq.commerce.core.components.models.productlist.ProductList"
    id="search-plp-root"
    class="productlist__root"
    data-plp-urlPath="${productList.storefrontContext.urlPath}"
    data-plp-title="${productList.title}">
    </div>
    
  • ui.apps/src/main/content/jcr_root/apps/venia/components/commerce/searchresults/.content.xml

    줄 6에서 .content.xml 편집:

    code language-xml
    sling:resourceSuperType="venia/components/commerce/productlist"
    
  • ui.content/src/main/content/jcr_root/content/venia/language-masters/en/search/.content.xml

    .content.xml을(를) 21-22줄에서 편집합니다.

    code language-xml
    sling:resourceType="venia/components/commerce/productlist"
    
  • ui.content/src/main/content/jcr_root/content/venia/us/en/search/.content.xml

    26행에서 .content.xml 편집:

    code language-xml
    sling:resourceType="venia/components/commerce/productlist"
    
  • ui.frontend/src/main/components/App/App.js

    ../../site/main.scss 바로 위의 47행에서 App.js을(를) 편집합니다.

    code language-javascript
    import '@adobe/magento-storefront-event-collector';
    
  • ui.tests/test-module/specs/venia/productlist-dialog.js

    productlist-dialog.js을(를) 편집하고 describe을(를) 20행 describe.skip(으)로 변경합니다.

    code language-javascript
    describe.skip('Product List Component Dialog', function () {
    

비 PLP 페이지 non-plp-pages

PLP 위젯을 사용하는 것보다, 디폴트 카테고리 또는 카탈로그 페이지가 원하는 몇몇 카테고리들이 있을 수 있다. AEM에서 이러한 범주 페이지는 수동으로 구성해야 합니다.

  1. 작성자 페이지에서 카테고리 페이지 템플릿을 선택합니다. Venia Store - Home > 카탈로그 페이지 > Venia Store - 카테고리 페이지 ​를 선택하고 "모양 찾기"를 선택하거나 새 페이지 템플릿을 만듭니다.

템플릿 선택

  1. 속성 섹션을 클릭하고 Commerce 탭을 선택합니다.

속성 선택

  1. 선택한 카테고리 페이지 템플릿과 함께 표시할 카테고리를 선택합니다.

범주 선택

recommendation-more-help
fbcff2a9-b6fe-4574-b04a-21e75df764ab