# Create a Custom Recommendations Component for B2C Stores Using Commerce Einstein APIs

Creating a custom B2C Commerce Einstein recommendations component includes implementing the Activity Tracking API and connecting the component to the Product Recommendation API.

For B2C storefronts, you connect the component to the Product Recommendation API through a wire adapter. Your component must incorporate calls to the Activity Tracking API. When configuring the Activity Tracking API, keep these considerations in mind.

- Implement both the viewReco and clickReco activities.
- If you build custom components that show product details without including the Product Detail Purchase Options component, make sure to implement the viewProduct activity.
- If you add custom add-to-cart functionality, also implement the addToCart activity.

You can also introduce custom JavaScript, HTML, and CSS to make front-end modifications. For more information, see the [Lightning Web Components Dev Guide](https://lwc.dev/guide/introduction).

:::note
This example shows a custom similar-products Commerce Einstein recommendation component using the PRODUCT anchor type. All steps refer to files created for a sample Lightning web component. For more information, see [Create a Sample Lightning Web Component](/docs/commerce/salesforce-commerce/guide/b2b-b2c-comm-create-sample-lwc.md).
:::

1. In the component’s JavaScript file, define a custom component class (for example, `RecommendationsSample`). Implement the ProductRecommendationsAdapter to return Einstein product recommendations.

   For example, in `force-app/main/default/<Component Name>.js`, import this wire adapter from the `recommendationsApi` module within the commerce namespace (`commerce/recommendationsApi`). Declare its required parameters with the `@wire` decorator.

   ```apex

   import { LightningElement, api, track, wire } from 'lwc';
   import { ProductRecommendationsAdapter, ANCHOR_TYPES } from 'commerce/recommendationsApi';
   import { navigate, NavigationContext } from 'lightning/navigation';
   import { trackClickReco, trackViewReco } from 'commerce/activitiesApi';

   export default class RecommendationsSample extends LightningElement {

       @api products = [];
       @api productId;

       recommenderName = 'similar-products';
       anchorType = ANCHOR_TYPES.PRODUCT;
       get anchorValue() {
           return [this.productId];
       };

       @wire(ProductRecommendationsAdapter, {
           recommenderName: '$recommenderName',
           anchorType: '$anchorType',
           anchorValue: '$anchorValue',
       })
       async loadRecommendation(response) {
           let { data, error } = response;

           if (data && data.recoUUID && data.products && data.products.length > 0) {
               this.products = data.products;
               this.recoUUID = data.recoUUID;

               if (this.canDisplayRecommendations) {
                   this.sendViewReco();
               }
           } else if (error) {
               // unable to load recommendation, handle accordingly
               this.products = { data: [] };
               console.error('Unable to load product recommendations');
           }
       }

       get canDisplayRecommendations() {
           return this.products.length > 0;
       }

       // NavigationContext allows us to click a link to get to new Product page
       @wire(NavigationContext)
       navContext;

       handleClickProduct(event) {
           const pid = event.currentTarget.getAttribute('pid');
           const product = this.products.filter(p => p.id === pid)[0];

           trackClickReco(this.recommenderName, this.recoUUID, {
               id: product.id,
               sku: product.sku,
           });

           // go to the Product Detail Page for the product clicked
           navigate(this.navContext, {
               type: 'standard__recordPage',
               attributes: {
                   objectApiName: 'Product2',
                   recordName: product.fields.Name.replace(' ', '-'),
                   name: 'recordId',
                   recordId: pid,
               },
           });
       }

       sendViewReco() {
           trackViewReco(
               this.recommenderName,
               this.recoUUID,
               this.products.map((product) => {
                   return {
                       id: product.id,
                       sku: product.sku,
                   };
               })
           );
       }
   }

   ```

2. Update the component’s HTML file (for example, `force-app/main/default/<Component Name>.html`).

   ```html

   <template>
       <section class="component-wrapper" if:true={canDisplayRecommendations}>
           <h1>Product Recommendations</h1>
           <table>
               <tr>
                   <th>Image</th>
                   <th>Name</th>
                   <th>List Price</th>
                   <th>Unit Price</th>
               </tr>
               <template for:each={products} for:item="product">
                   <tr key={product.id}>
                       <td><img src={product.defaultImage.url}></img></td>
                       <td>
                           <a key={product.id} class="product-line" onclick={handleClickProduct} pid={product.id}>
                               {product.fields.Name}
                           </a>
                       </td>
                       <td>{product.prices.listPrice} {product.prices.currencyIsoCode}</td>
                       <td>{product.prices.unitPrice} {product.prices.currencyIsoCode}</td>
                   </tr>
               </template>
           </table>
       </section>
   </template>

   ```

3. Update the metadata in the component’s XML file (for example, `force-app/main/default/<Component Name>.js-meta.xml`).

   :::note
   Ensure that the `<apiVersion>` tag references the latest API version.
   :::

   ```xml

   <?xml version="1.0" encoding="UTF-8"?>
   <LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
       <apiVersion>55.0</apiVersion>
       <isExposed>true</isExposed>
       <targets>
           <target>lightningCommunity__Page</target>
           <target>lightningCommunity__Default</target>
       </targets>

       <targetConfigs>
           <targetConfig targets="lightningCommunity__Default">
               <property label="Product Id" name="productId" type="String" default="{!recordId}" />
           </targetConfig>
       </targetConfigs>
   </LightningComponentBundle>

   ```

4. In your lwc directory, create a CSS file with the same name as your project. In this example, the CSS file is named `recommendationsSample.css`.

   ![Screenshot showing the location for the new CSS file. The cursor is hovering over "New File" in the recommendationsSample folder.](https://a.sfdcstatic.com/developer-website/sfdocs/commerce-cloud/media/d2c-commerce/RecsNewFile.png)

5. In the CSS file, add custom CSS to style your component. The sample code provided includes modifications to the component’s image size and headings.

   ```css
   h1 {
     font-size: 1.5em;
     font-weight: 800;
   }
   img {
     width: 150px;
   }
   th {
     font-weight: 800;
   }
   ```

6. After you create the custom Einstein Recommendations component, deploy the component from Visual Studio Code and place it in your store with Experience Builder.

7. Before publishing your site from Experience Builder, click **Preview** to see how the custom component looks in a desktop browser window or on a mobile device.

**See Also**

- [Commerce Einstein APIs](https://developer.salesforce.com/docs/atlas.en-us.b2b_b2c_comm_dev.meta/b2b_b2c_comm_dev/b2b_b2c_comm_einstein_apis.htm)
- [Prepare Commerce Einstein to Use Custom Components](https://developer.salesforce.com/docs/atlas.en-us.b2b_b2c_comm_dev.meta/b2b_b2c_comm_dev/b2b_b2c_comm_prepare_einstein_custom_comps.htm)
- [Commerce Einstein Activity Tracking API](https://developer.salesforce.com/docs/atlas.en-us.b2b_b2c_comm_dev.meta/b2b_b2c_comm_dev/b2b_b2c_comm_activity_tracking_api.htm)
- [B2C Commerce Einstein Product Recommendations API](https://developer.salesforce.com/docs/atlas.en-us.b2b_b2c_comm_dev.meta/b2b_b2c_comm_dev/b2b_b2c_comm_einstein_b2c_reco_api_ref.htm)
- [Customize Sites with Experience Builder](https://help.salesforce.com/s/articleView?id=commerce.community_designer_overview.htm)
