Integrations / Platforms / Salesforce Commerce Cloud B2C / Connecting to Headless Salesforce Commerce Cloud Using a React Front End

Connecting to Headless Salesforce Commerce Cloud Using a React Front End

By nature, headless architectures allow for more agility and flexibility. Therefore, various, very different approaches are labeled “headless.” This guide describes how the Algolia SFCC Integration can fit in headless architecture and support its intended flexibility.

There are multiples ways to spin up a headless architecture with Salesforce Commerce Cloud B2C. There are three main steps to integrating Algolia with SFCC Headless:

  1. Install the Algolia Link Integration.
  2. Index your catalogs to Algolia.
  3. Connect to a headless storefront.

In this guide, we connect Algolia to a headless SFCC storefront using React. If you prefer to use the official boilerplate published by Salesforce, please refer to our guide on connecting a headless Salesforce Commerce Cloud using official boilerplate. Regardless of which method you use, the first two steps (installing the Algolia link Integration and indexing your catalogs to Algolia) are the same.

The Algolia Link is composed of four cartridges that work together to fit in various uses cases.

Unlike SiteGenesis or SFRA architectures, headless architectures only use the “server-side” cartridges, namely: int_algolia and bm_algolia.

int_algolia Handles the import of your product information from Salesforce Commerce Cloud to Algolia
bm_algolia Allows you to monitor and configure Algolia indexing from your Business Manager

To complete the installation, please follow the instructions in Set Up the Algolia Cartridge.

Index your catalogs

To index your catalogs, please follow the instructions in Index Your Catalogs to Algolia .

After successfully running the indexing jobs, navigate to the Indices section of the Algolia dashboard to ensure your catalogs are properly indexed.

Connect to a headless storefront

You can connect Algolia to a headless SFCC storefront using React in few steps:

  1. Set up a React based project.
  2. Use our Unified UI package or React InstantSearch library to build out your search experience.

Unfied UI E-Commerce with Salesforce Commerce Cloud Headless

Set up a React based project

This guide uses Next.js but you can transpose the instructions to any React-based project.

Create a React/Next.js project using create-next-app.

1
2
3
npx create-next-app my-react-storefront
cd my-react-storefront
yarn dev

This create the project in the directory my-react-storefront and starts a server on http://localhost:3000/.

Build your search experience

To create our search experience, you can either:

  1. Use the out-the-box Unified InstantSearch E-Commerce package.
  2. Build a tailor-made experience with our React InstantSearch library.

In this guide, we’ll explore using the Unified InstantSearch E-Commerce package.

Download and run the project

Clone the project’s Github repository.

1
2
3
4
git clone --depth=1 --branch=master https://github.com/algolia/unified-instantsearch-ecommerce 
rm -rf unified-instantsearch-ecommerce/.git
cd unified-instantsearch-ecommerce
yarn && yarn start

Configure the package to work with your data

Open unified-instantsearch-ecommerce/src/config/settings.js and make the following changes:

Set you Application ID, search API key and index
1
2
3
4
5
6
7
8
9
10
- export const appId = 'latency';
- export const searchApiKey = '6be0576ff61c053d5f9a3225e2a90f76';
+ export const appId = '<Your Algolia Application ID>';
+ export const searchApiKey = '<Your Algolia Search-only API Key>';

  export const index = {
-    indexName: 'instant_search',
+    indexName: 'zzgk_001_sandbox_us01_dx__RefArch__products__en_US',
     ...
 }
Set your “Price ascending” and “Price descending” index replicas
1
2
3
4
5
6
7
8
9
10
11
12
 export const sorts = [
    {
        label: 'Price ascending',
-       value: 'instant_search_price_asc',
+       value: `zzgk_001_sandbox_us01_dx__RefArch__products__en_US__price_USD_asc`,
    },
    {
        label: 'Price descending',
-       value: `instant_search_price_desc`,
+       value: `zzgk_001_sandbox_us01_dx__RefArch__products__en_US__price_USD_desc`,
    },
 ]
Set your category attributes

The Algolia Integration by default indexes the primary category on the attributes __primary_category.*:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  {
    type: 'hierarchical',
    header: 'Categories',
    label: 'Category',
    options: {
      attributes: [
-       'hierarchicalCategories.lvl0',
-       'hierarchicalCategories.lvl1',
+       '__primary_category.0',
+       '__primary_category.1',
+       '__primary_category.2',
      ],
      limit: 6,
      showMore: true,
    },
  },
Set your price attribute

The Algolia Integration, by default, indexes prices on on the attributes price.${currency}:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  {
    type: 'slider',
    header: 'Price',
    label: 'Price',
    options: {
-     attribute: `price`,
+     attribute: `price.USD`,
      transformValue: (value) => (
        <>
          <span className="uni-Hit-currency">$</span>
          {value}
        </>
      ),
    },
  },

Remove suggestions configuration

This part of the configuration creates a Query Suggestions UI. Unless you have set this feature up, you shouldn’t include it.

1
2
3
4
5
6
- export const suggestionsIndex = {
-   indexName: 'instant_search_demo_query_suggestions',
-   searchParameters: {
-     hitsPerPage: 6,
-   },
- };
Customize the Hit component
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
  export function Hit({ hit, insights, view }) {
+   const image = hit.image_groups[1].images[0];
    return (
      <article
        className="uni-Hit"
        onClick={() =>
          insights('clickedObjectIDsAfterSearch', {
            eventName: 'Product Clicked',
          })
        }
      >
        <a href={hit.url} className="uni-Hit-inner">
          <div className="uni-Hit-image">
-           <img src={hit.image} alt={hit.name} loading="lazy" />
+           <img src={image.dis_base_link} alt={image.alt} loading="lazy" />
          </div>
  
          <div className="uni-Hit-Body">
            <header className="uni-Hit-header">
              <h2 className="uni-Hit-category">{hit.categories[0]}</h2>
  
              <h1 className="uni-Hit-title">
                <Highlight attribute="name" tagName="mark" hit={hit} />
              </h1>
            </header>
  
            {view === 'list' && (
              <p className="uni-Hit-description">
-               <Snippet attribute="description" tagName="mark" hit={hit} />
+               <Snippet attribute="short_description" tagName="mark" hit={hit} />
              </p>
            )}
  
            <footer>
              <span className="uni-Hit-currency">$</span>
-             <span className="uni-Hit-price">{hit.price.toLocaleString()}</span>
+             <span className="uni-Hit-price">{hit.price.USD.toLocaleString()}</span>
            </footer>
          </div>
  
          ...
        </a>
      </article>
    );
  }


Compile and export the project

Once you’ve finished customizing your front end, you need to export it so it can be used in your storefront.

1
yarn export

This produces a directory unified-instantsearch-ecommerce/export containing all the assets needed to power a complete e-commerce search experience.

Copy this directory to the public directory of our storefront project.

1
cp -r unified-instantsearch-ecommerce/export my-react-storefront/public/

Use the exported assets

Create a new Search component
1
2
mkdir -p my-react-storefront/components/Search
touch my-react-storefront/components/Search.js

Fill your newly created Search.js file with the following contents:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// in my-react-storefront/components/Search.js
import React from 'react';
import Head from "next/head";


export default function Search() {
    React.useEffect(() => {
        // remove the script if already exists
        let script = document.querySelector(`script[src="${src}"]`);

        if (script) {
            script.remove();
        }

        // add script to DOM
        script = document.createElement("script");
        script.src = src;
        document.body.appendChild(script);

        return () => {
            // remove the script on unmount
            document.querySelector(`script[src="${src}"]`).remove();
        };
    });

    return (
        <>
            <Head>
                <link rel="stylesheet" async href="/export/search.css" />
            </Head>
            <div id="search-button" />
        </>
    );
}
Use your Search component in your UI

Finally, open your Home component, located in the file: pages/index.js, and mount the newly created <Search /> component in it.

Did you find this page helpful?