Vue Storefront is now Alokai! Learn More
Integrating Algolia Search

Integrating Algolia Search

Replace the default product search in your Alokai Storefront project with Algolia

CommerceIs Algolia integration supported?
BigCommerce
Commercetools✅ (added in @vsf-enterprise/unified-api-commercetools@2.2.0)
Adobe Commerce (Magento)
SAPCC✅ (added in @vsf-enterprise/unified-api-sapcc@0.17.0)
SFCC✅ (added in @vsf-enterprise/unified-api-sfcc@0.13.0)

Algolia is an extremely fast search solution popular among eCommerce stores. This guide covers integrating Algolia Search for the Product Listing and Search pages.

To integrate Algolia Search, you must override the Unified Data Layer to replace the implementation for the product search (SearchProducts) with a dedicated one based on the Algolia API. This introduces two separate normalizers responsible for transforming data from the format returned by Algolia into Unified Data Layer format.

If you want to use other Algolia features, such as autocomplete, infinite search, or search suggestions, you need to implement them yourself. The integration we provide doesn't introduce any additional features on the Storefront side.

Algolia Setup

The starting point is to feed Algolia with data from your eCommerce instance. A place where Algolia stores the data is called an index, and a single index can contain multiple records. The data structure in Algolia largely depends on the data import option you chose. If you used a ready-made data import plugin, the data structure will be pre-determined based on the existing solution. To fully control the data structure, you can create a .json file yourself, which you will use to feed the Algolia index. Learn more about this in the Algolia documentation.

Data Import

To integrate Algolia with Commercetools, we recommend using the Algolia Commercetools Integration. This integration will handle the data import and index creation for you, and it will also reindex the data automatically when changes are made in Commercetools.

As a result you should have an index in Algolia, you can call it for instance commercetools_products. It should match the default schema.

Algolia Setup for Commercetools

Sorting

Once the data from your eCommerce is in Algolia, create additional indexes that will contain sorted data. First, decide how many and what sorting options you want to provide to your storefront users, then create a Replica Index for each of these options. Algolia itself recommends this approach to sorting - see more in the documentation. As a result you could have:

  • products - a default index with products sorted by relevance
  • products_price_asc - a replica index with products sorted by price ascending
  • products_price_desc - a replica index with products sorted by price descending

Alokai Algolia Integration

After you have your data in Algolia, you can start integrating Algolia with your Alokai Storefront project. The integration consists of several steps:

1

Install Algolia api package

Make sure to navigate in your terminal to apps/storefront-middleware/ and run the command:

yarn add @vsf-enterprise/algolia-api

2

Configure Algolia Integration

First, you need to create the config file itself:

apps/storefront-middleware/integrations/algolia/config.ts
import type { MiddlewareConfig } from "@vsf-enterprise/algolia-api";
import type { Integration } from "@vue-storefront/middleware";

const { ALGOLIA_API_KEY, ALGOLIA_APP_ID } = process.env;

if (!ALGOLIA_API_KEY) throw new Error("Missing env var: ALGOLIA_API_KEY");
if (!ALGOLIA_APP_ID) throw new Error("Missing env var: ALGOLIA_APP_ID");

export const config = {
  location: "@vsf-enterprise/algolia-api/server",
  configuration: {
    apiKey: ALGOLIA_API_KEY,
    appId: ALGOLIA_APP_ID,
    /**
     * Default index and default facets are required by the integration,
     * but they will be overwritten in the runtime anyway, so we can keep them empty
     */
    defaultIndex: "default",
    defaultFacets: [],
  },
} satisfies Integration<MiddlewareConfig>;

And then the index.ts re-exporting your configuration for further usage:

apps/storefront-middleware/integrations/algolia/index.ts
export * from "./config";

3

Update middleware.config.ts

Then, check your middleware.config.ts file to be sure that algolia integration is added to the config. Here is what the reference file should look like:

apps/storefront-middleware/middleware.config.ts
import dotenv from "dotenv";
dotenv.config();

// ...
import { config as algoliaConfig } from "./integrations/algolia"; 
export const config = {
  integrations: {
    algolia: algoliaConfig,    },
};

4

Configure Unified Extension for Algolia

Update the Unified extension, to include the Unified Methods implementation for Algolia and the Algolia configuration.

apps/storefront-middleware/integrations/commercetools/extensions/unified.ts
import { createUnifiedExtension } from "@vsf-enterprise/unified-api-commercetools";
import { methods as algoliaMethods } from "@vsf-enterprise/unified-api-commercetools/algolia"; 
export const unifiedApiExtension = createUnifiedExtension({
  normalizers: {
    addCustomFields: [{}],
  },
  methods: {
    override: {
      ...algoliaMethods,
    },
  },
  config: {
    currencies: ["USD", "EUR"],
    defaultCurrency: "USD",
    algolia: {
      integrationName: "algolia",
      facets: ["*"],
      getFacetLabel({ name }) {
        return name.replace(/^attributes\./, "").replace(/\.key$/, "");
      },
      indexName: ({ sortBy }) => {
        switch (sortBy) {
          case "price-low-to-high": {
            return "products_commercetools_price_asc";
          }
          case "price-high-to-low": {
            return "products_commercetools_price_desc";
          }
          default: {
            return "products_commercetools_price_asc";
          }
        }
      },
    },
    getFacetType: (facet) => (facet.name.startsWith("categories.") ? "CATEGORY" : "MULTI_SELECT"),
  },
  isNamespaced: true,
});

And that's it. Now you should be able to use Algolia in your storefront on Product Listing Page and Search Page.

Configuration Options

Next, you can set up the Algolia configuration in your Unified Extension.

The available configuration options are:

  • facets - string[]
  • getFacetLabel - (facet: AlgoliaFacet) => string
    • The function receives the facet and should return the label for the facet.
  • indexName - string | (args: SearchProductArgs) => string
    • String name of the Algolia index or a function that returns the name of the Algolia index based on the arguments. A function can be used to return different indexes based on the request, for example, to return a different index based on sorting.
  • integrationName - string
    • The name of the integration registered in middleware.config.ts file that will be used to get the Algolia client.
  • categoryFacet - string (only for SAPCC and SFCC)
    • The name of the category facet. The facet should contain ids of categories. It is used to populate the category names during the normalization, so if the value is provided, the normalized category SfFacet will include the category id and name.
  • normalizeAlgoliaProductCatalogItem - (context: Context, algoliaRecord: AlgoliaRecord) => SfProductCatalogItem
    • A function that normalizes the Algolia record into the Unified Data Layer format. If not provided, the default normalization will be used.
  • normalizeAlgoliaFacet - (context, algoliaFacet: AlgoliaFacet) => SfFacet
    • A function that normalizes the Algolia facet into the Unified Data Layer format. If not provided, the default normalization will be used.
  • normalizeAlgoliaPagination - (algoliaResponse: AlgoliaResponse) => SfPagination
    • A function that normalizes the Algolia response into the Unified Data Layer format. If not provided, the default normalization will be used.

To specify the facets, you can use the attributes.* syntax, which will return all attributes from the Algolia record. You can also use the * syntax, which will return all fields from the Algolia record. Please remember also that the facets you specify here must be configured in the Algolia index. Example of the Algolia attributes for faceting configuration:

Example configuration for Algolia facets

Normalization

Algolia gives you the flexibility to define the data structure you want to store in the index. If you decide to customize the data structure, or if you use an integration that doesn't provide a ready-made data import plugin (like SAPCC), you will need to provide a custom normalizer.

An example .json structure of the Algolia record may looks as follows:

[
  {
    "productID": "30404",
    "sku": "30404",
    "slug": {
      "en": "30404-shades-von-zipper-papa-g-black-gloss-black-gloss-grey",
      "de": "30404"
    },
    "name": {
      "en": "Shades Von Zipper Papa G black gloss black gloss/grey"
    },
    "categories": [
      {
        "name": "Clothes",
        "id": "clothes"
      },
      {
        "name": "Sunglasses",
        "id": "sunglasses"
      }
    ],
    "attributes": {
      "size": {},
      "color": {},
      "ean": "299052695"
    },
    "images": "/medias/?context=bWFzdGVyfGltYWdlc3wxMzUyNXxpbWFnZS9qcGVnfGFHSXlMMmcxWXk4NE56azJOalF3TnpNNU16VTR8ODkzYTA5NjRlMGQ2ZjZjNDE5OTBlZGRhYTUwZjM5YTU5NGNjZDVlNGI2NDI4MTdlMzRkMWMwOTI0MTdiNzlhMQ",
    "prices": {
      "EUR": 7788,
      "USD": 10533
    },
    "gender": ["FEMALE"],
    "stores": ["Cambridge University", "Edinburgh University"]
  }
]

The normalizer should transform given Algolia record into the Unified Data Layer format. The SfProductCatalogItem interface looks as follows:

export interface SfProductCatalogItem {
  id: SfId;
  sku: Maybe<string>;
  name: Maybe<string>;
  slug: string;
  price: Maybe<SfDiscountablePrice>;
  primaryImage: Maybe<SfImage>;
  rating: Maybe<{
    average: number;
    count: number;
  }>;
  quantityLimit: Maybe<number>;
}

To override the built-in normalization, provide the normalizeAlgoliaProductCatalogItem function in the Unified Extension for Algolia:

apps/storefront-middleware/integrations/<ecommerce>/extensions/unified.ts
export const unifiedApiExtension = {
  //...
  algolia: {
    normalizeAlgoliaProductCatalogItem(context, algoliaRecord) {
      // Custom normalization logic. You should return the object matching SfProductCatalogItem interface.
    }
  }
};

You can also override the normalizeAlgoliaFacet and normalizeAlgoliaPagination.