Search engine
When configured with Magento2, Front-Commerce provides search capabilities for your website using different technologies. This guide shows you the different options available to you.
You can configure search and product lists with filters using the following platforms:
- Native Magento feature (using its GraphQL API)
- ElasticSearch - direct access (using ElasticSuite)
- Algolia connected to Magento
- Algolia standalone
- Attraqt
- Attraqt Recommendations
Native search
Since version 2.15
Front-Commerce supports the native Magento API for search and category listing pages. It means that any Magento search module compatible with its GraphQL API will be used in your Front-Commerce project without any specific work.
If you're using ElasticSuite as search engine in Magento, you MUST ensure that you have a version greater than 2.10.6.
See "I have an error Cannot read property 'label' of null with Magento 2 native categories listing" troubleshooting section for details.
This section is being written. Please contact us if you want to ask any question!
Elasticsearch
Requirements
On Magento2 side, Front-Commerce requires Elasticsuite and its CMS Page search plugin to be installed.
The Elasticsuite installation and configuration procedure can be found in a dedicated page on the project wiki while for the CMS Page search plugin, the setup is detailed in its readme document.
Front-Commerce configuration
First, you need to make sure the Elasticsearch search client is installed with a version that matches your Elasticsearch server version (6 or 7):
npm i @elastic/elasticsearch@7
On Front-Commerce side, you need to enable the Elasticsearch datasource by
making changes in your .front-commerce.js
file similar to:
module.exports = {
modules: ["./node_modules/front-commerce/modules/datasource-elasticsearch"],
serverModules: [
{ name: "FrontCommerce", path: "server/modules/front-commerce" },
{
name: "Magento2Elasticsearch",
path: "datasource-elasticsearch/server/modules/magento2-elasticsearch",
},
{ name: "Magento2", path: "server/modules/magento2" },
],
};
the Elasticsearch server module needs to be enabled before the Magento's module.
Then, in your .env
file, you need to define
the variables.
FRONT_COMMERCE_ES_HOST=<es_host>
FRONT_COMMERCE_ES_ALIAS=<es_alias>
FRONT_COMMERCE_ES_ELASTICSUITE_VERSION=<es_elasticsuite_version>
The prefix value can be found in the admin interface under Stores >
Elasticsuite > Base Settings > Indices Settings in the field Indices Alias
Name (the default value is magento2
).
After restarting Front-Commerce, you should be able run a GraphQL query to search for products, categories and/or pages, for instance:
query Search {
search(query: "whatever you want to search for") {
query
products {
total
products {
sku
name
}
}
categories {
name
}
pages {
identifier
title
}
}
}
If you are using the default theme or the Chocolatine theme, the search bar should now be visible.
Alternative facet filtering
Front-Commerce ElasticSearch module provides an alternative way of filtering with facets. By default, each active facet will "refine" (i.e. substract) results from the search and from the selectable facets. With this alternative way, active facets for one attribute will become additive instead.
In order to activate this feature, set search.refinementFacetsOnly
to false
in your website.js
:
themeColor: "#666699",
search: {
dynamicFacetSize: 10,
ignoredAttributeKeys: [],
attributeFacetMinimumDocumentCount: 1,
authorizedCategoriesFacet: [],
categoryFacetMinimumDocumentCount: 1,
- refinementFacetsOnly: true,
+ refinementFacetsOnly: false,
},
phoneNumber: "01 02 03 04 05",
email: "contact@example.com",
Algolia connected to Magento
Since version 2.13
Requirements
On Magento's side, you need to install and configure the Algolia module for Magento2.
In addition, the attribute category_ids
must be configured as both an indexed
attribute and as a facet:
- under Stores > Configuration > Algolia Search > Products, add
category_ids
as Searchable in the Attributes parameter - under Stores > Configuration > Algolia Search > Instant Search Result Page,
add
category_ids
in the Facets parameter
You can then run the indexer so that the products are indexed in Algolia's index.
category_ids
is the only required facets. Depending on your project, you can
configure any other attribute to be exposed as a facet by following the same
steps.
Front-Commerce configuration
First, you need to make sure the Algolia's search client is installed:
npm i algoliasearch@4.8
On Front-Commerce side, you need to enable the Algolia datasource by making the
changes in your .front-commerce.js
file similar to:
module.exports = {
modules: ["./node_modules/front-commerce/modules/datasource-algolia"],
serverModules: [
{ name: "FrontCommerce", path: "server/modules/front-commerce" },
{
name: "Magento2Algolia",
path: "datasource-algolia/server/modules/magento2-algolia",
},
{ name: "Magento2", path: "server/modules/magento2" },
],
};
the Algolia server module needs to be enabled before the Magento's module.
Front-Commerce retrieves the following parameters from Magento:
- the Application ID
- the search only API key
- the index name prefix
- the number of values per facet
- the configured facet attributes
On the configured facets, only the attribute name and the facet type are taken into account (Label, Searchable and Create Query rule are ignored for now).
Before version 2.21, the facet type was ignored and Front-Commerce behaved as if
the facet type was set to Conjunctive
.
For performance reason, the configuration retrieved from Magento is cached. As a result, after changing a parameter in the backoffice, the new parameter will be taken into account after at most one minute by Front-Commerce.
After restarting Front-Commerce, you should be able to run a GraphQL query to search for products, categories or pages, for instance:
query Search {
search(query: "whatever you want to search for") {
query
products(params: { from: 0, size: 5 }) {
total
products {
sku
name
}
}
categories(size: 5) {
name
}
pages(size: 5) {
title
}
}
}
If you are using the default theme or the Chocolatine theme, the search bar should now be visible.
Algolia not connected to Magento
Since version 2.23
As of the version 2.23, it's possible to configure Front-Commerce to use Algolia without having to install the Algolia module for Magento2.
Requirements
In that kind of setup, you need to implement your own indexing mechanism to replace the one provided by the Algolia module for Magento2. To help you in that task, we provide a script to check that the indices are compatible with Front-Commerce. This script can be run with the following command:
FRONT_COMMERCE_ALGOLIA_APPLICATION_ID=APPID \
FRONT_COMMERCE_ALGOLIA_API_KEY=ADMIN_API_KEY \
FRONT_COMMERCE_ALGOLIA_INDEX_NAME_PREFIX=INDEX_NAME_PREFIX \
npx front-commerce-algolia-check
The application ID and the admin API can be found in your Algolia account. The index name prefix is a prefix of the indices that Front-Commerce will use. The value on the command line should be the same as the one used to configure the Algolia module.
By default, Front-Commerce is able to search for products, categories and CMS pages, the corresponding indices need to follow some requirements.
For product indices:
- the indices name must be named after the following pattern:
{index_name_prefix}{store_code}_products
. For instance, in a setup where the index name ismyproject_
and Front-Commerce is configured to expose 2 stores which codes aremystore
andmystore2
, two indices namedmyproject_mystore_products
andmyproject_mystore2_products
must be created; - to be able to sort results by a field, some extra indices must be created by
following the same naming convention and by adding a suffix using the pattern
_{sort_field}_asc
or_{sort_field}_desc
. For instance, to allow sorting by created date (fieldcreated_at
) ascending and descending, the indicesmyproject_mystore_products_created_at_asc
andmyproject_mystore_products_created_at_desc
must exist; - all documents must have a field
sku
and it must be retrievablesku
. The field must contain the productsku
as a string and for configurable product it should be an array of the SKUs of each configuration with the first one being thesku
of the configurable product; - all documents must have a field
category_ids
, this field must be searchable and configured as an attribute for facets. It must contain the category ids in which the product is positioned; - all documents must have a field
price
where the price is represented as an object like
{ "EUR": { "default": 42 }, "USD": { "default": 40 } }
category_ids
is the only required facets. Depending on your project, you can
configure others facets in the index. For those facets to be taken into,
you also have to configure the Algolia module.
For categories indices:
- the indices name must be named after the following pattern:
{index_name_prefix}{store_code}_categories
. For instance, in a setup where the index name ismyproject_
and Front-Commerce is configured to expose 2 stores which codes aremystore
andmystore2
, two indices namedmyproject_mystore_categories
andmyproject_mystore2_categories
must be created; - the
objectID
field of each document must be the category id as a string.
For CMS page indices:
- the indices name must be named after the following pattern:
{index_name_prefix}{store_code}_pages
. For instance, in a setup where the index name ismyproject_
and Front-Commerce is configured to expose 2 stores which codes aremystore
andmystore2
, two indices namedmyproject_mystore_pages
andmyproject_mystore2_pages
must be created. - all documents must have a
slug
field identifying the corresponding CMS page. This field must be set as retrievable.
Front-Commerce configuration
First, you need to make sure the Algolia's search client is installed:
npm i algoliasearch@4.8
On Front-Commerce side, you need to enable the Algolia datasource by making the
changes in your .front-commerce.js
file similar to:
module.exports = {
modules: ["./node_modules/front-commerce/modules/datasource-algolia"],
serverModules: [
{ name: "FrontCommerce", path: "server/modules/front-commerce" },
{
name: "StandaloneAlgolia",
path: "datasource-algolia/server/modules/algolia",
},
{ name: "Magento2", path: "server/modules/magento2" },
],
};
the Algolia server module needs to be enabled before the Magento's module.
In the .env, you need to define the following environment variables:
FRONT_COMMERCE_ALGOLIA_APPLICATION_ID=APP_ID
FRONT_COMMERCE_ALGOLIA_SEARCH_ONLY_API_KEY=SEARCH_ONLY_API_KEY
FRONT_COMMERCE_ALGOLIA_INDEX_NAME_PREFIX=myproject_
To further configure the Algolia module for instance to define facets, you have
to create a configuration provider to override
the algoliaConfigProvider
.
After restarting Front-Commerce, you should be able to run a GraphQL query to search for products, categories or pages, for instance:
query Search {
search(query: "whatever you want to search for") {
query
products(params: { from: 0, size: 5 }) {
total
products {
sku
name
}
}
categories(size: 5) {
name
}
pages(size: 5) {
title
}
}
}
If you are using the default theme or the Chocolatine theme, the search bar should now be visible.
Attraqt
Since version 2.19
Requirements
Due to the way Attraqt works, you will have to ensure your Attraqt index is Front-Commerce-ready before hand. In order to check this, we have added a simple script that check the basics for you, and tells what's missing from your current index.
Using your Attraqt's search API key, you can execute this command from your Front-Commerce repository:
FRONT_COMMERCE_ATTRAQT_SEARCH_API_KEY=your_api_key npx front-commerce-attraqt-check
You can find your search API key by logging in in into
the XO console, and navigating to:
Search > API Keys
The script should be very quick to execute, and will let you now what needs your attention in your Attraqt index. If you have any doubt on how to change this, do not hesitate to ask your Attraqt CSM.
When you get the ✔️ as a response from the script, you are ready to use Attraqt with Front-Commerce.
Facets
Due to facet IDs not being editable in Attraqt, facets created in your Attraqt console must be based on your Magento attributes exact names.
By example, if you have an attribute fashion_colour
in your product and you
want to add a facet for it, the facet in attraqt must be based on an attribute
named fashion_colour
as well, which will create a facet with ID
facet-fashion_colour
.
Front-Commerce configuration
First, you need to make sure the Attraqt's search client is installed:
npm i @attraqt/xo-js@1.6.0
On Front-Commerce side, you need to enable the Attraqt datasource by making the following changes in your .front-commerce.js file:
module.exports = {
modules: ["./node_modules/front-commerce/modules/datasource-attraqt"],
serverModules: [
{ name: "FrontCommerce", path: "server/modules/front-commerce" },
{
name: "Magento2Attraqt",
path: "datasource-attraqt/server/modules/magento2-attraqt",
},
{ name: "Magento2", path: "server/modules/magento2" },
],
};
The Attraqt server module needs to be enabled before the Magento module.
Then, in your .env
file, you need to define the
FRONT_COMMERCE_ATTRAQT_SEARCH_API_KEY
environment variable:
FRONT_COMMERCE_ATTRAQT_SEARCH_API_KEY=yourapikeyvalue
After restarting Front-Commerce, you should be able run a GraphQL query to search for products, categories and/or pages, for instance:
query Search {
search(query: "whatever you want to search for") {
query
products(params: { from: 0, size: 5 }) {
total
products {
sku
name
}
}
categories(size: 5) {
name
}
pages(size: 5) {
title
}
}
}
If you are using the default theme or the Chocolatine theme, the search bar should now be visible.
In case of emergency, Front-Commerce provides
a configuration to quickly deactivate Attraqt's search feature.
Use the FRONT_COMMERCE_ATTRAQT_DISABLED=true
and restart your application to
temporarily deactivate the module.
Add contextual information to your queries
Since version 2.23
Front-Commerce allows you to leverage Attraqt's Context feature in your application. This is a great way to add contextual information to your queries, so that you can get results adapted to your users needs.
Contexts can be provided at different levels, from the most generic to the most specific. Context values will be used as Attraqt context variables. Here's how to do it in your application.
Global context
The simplest way to add context variables to all your queries is to use a global
context. Front-Commerce's Attraqt module has a configuration for it:
config.attraqt.globalContext
. It is defined in the Attraqt
configuration provider, so you can
use any extension mechanism at your disposal to customize this value.
Example: an app-wide context for every users and queries
import configService from "server/core/config/configService";
const myAppConfigProvider = {
name: "myAppConfig",
values: Promise.resolve({
attraqt: {
globalContext: {
source: "storefront",
version: "1.0.0",
},
},
}),
};
configService.insertAfter("Attraqt", myAppConfigProvider);
Example: a global context dynamically determined per request
import mem from "mem";
import configService from "server/core/config/configService";
const getContextFromShopId = mem((shopId) => {
return {
attraqt: {
globalContext: {
source: `storefront_${shopId}`,
// […] more compute intensive variables here
}
},
};
});
const myAppConfigProvider = {
name: "myAppConfig",
slowValuesOnEachRequest: (_req, config) => {
return getContextFromShopId(config.currentShopId);
};
};
configService.insertAfter("Attraqt", myAppConfigProvider);
You can also use remote values or per user values using other configuration providers features.
Layer-specific context
Contexts can also be provided at the layer level. It allows to add context variables only for search queries restricted to a single item kind (e.g: categories).
To do so, you must use the context
option of datasource.buildLayer()
function in your application. Example:
const layer = searchDatasource.buildLayer({
type: "categories",
// your context variables here
context: {
priority: "online_sales",
foo: "bar",
},
executeQuery: executeCategoryQuery,
formatHit: searchDatasource.formatters.category,
fetchErrorFallback: () => () => {
return Promise.reject();
},
});
Layer-specific context replace the global context.
Query-specific context
Finally, you can also implement advanced use cases by adding contextual
information directly in the SearchQuery
. It means that any scope, pagination
or facet can update a query context.
To do so, you must use the addContext
method of SearchQuery
. Example: a
context based implementation of random sorting could be implemented like this
const randomizable =
() =>
({ random = false }) => {
return (searchQuery) => {
if (random) {
searchQuery.addContext({ randomSort: true });
}
return searchQuery;
};
};
export default randomizable;
Query-specific context is merged with global/layer-specific context variables. It can override specific variables while keeping others unchanged.
Attraqt recommendations
Since version 2.19
Front-Commerce provides a loader to retrieve recommendations from Attraqt's Widgets.
Front-Commerce configuration
To enable the Attraqt recommendation module, you need to add it to your
.front-commerce.js
config:
module.exports = {
modules: ["./node_modules/front-commerce/modules/recommendations-attraqt"],
serverModules: [
{ name: "FrontCommerce", path: "server/modules/front-commerce" },
{
name: "AttraqtRecommendations",
path: "recommendations-attraqt/server/modules/attraqt-recommendations",
},
{ name: "Magento2", path: "server/modules/magento2" },
],
webModules: [
{ name: "FrontCommerce", path: "./src/web" },
{
name: "AttraqtRecommendation",
path: "front-commerce/modules/recommendations-attraqt/web",
},
],
};
Then, you need to define the API url in your environment variables:
FRONT_COMMERCE_ATTRAQT_RECOMMENDATION_API_URL=http://api.early-birds.io/widget
Attraqt Recommendations usage example
In this example, we'll make a module SuggestedProduct
that fetches a
recommendation from Attraqt via Front-Commerce's loader.
See Extend the GraphQL schema for instructions on how to add your own GraphQL module.
Front-Commerce exposes a GraphQL interface to simplify the process of fetching recommendations. You will first need to update your GraphQL schema to implement this interface and use it in a query:
type ProductRecommendation implements AttraqtRecommendationResult {
id: ID!
products: [Product]
}
input ProductRecommendationInput {
profileId: String
}
extend type Query {
productRecommendation(
input: ProductRecommendationInput
): ProductRecommendation
}
Add a resolver for this query:
export default {
Query: {
productRecommendation: async (_, { profileId }, { loaders }) => {
return loaders.AttraqtRecommendations.loadRecommendationsForWidget(
"my-widget-id",
null,
profileId // Available since 2.28
);
},
},
ProductRecommendation: {
products: async (recommendation, _, { loaders }) => {
// Note: the shape of recommendation.recommendations will vary
// depending on your data indexed in Attraqt. Adapt this example to your use case.
const skus = recommendation.recommendations
.map(({ id }) => id)
.filter(Boolean);
return loaders.Product.loadBySkus(skus);
},
},
};
On the front-end side, retrieve the results from this query using the GraphQL fragment provided by Front-Commerce:
#import "theme/modules/AttraqtRecommendations/AttraqtRecommendationResultFragment.gql"
#import "theme/pages/Product/ProductFragment.gql"
query SuggestedProductsQuery($input: ProductRecommendationInput) {
productRecommendation(input: $input) {
...AttraqtRecommendationResultFragment
products {
...ProductFragment
}
}
}
You can now use it in a component:
import React from "react";
import { graphql } from "react-apollo";
import SuggestedProductsQuery from "./SuggestedProductsQuery.gql";
const SuggestedProducts = ({ recommendation }) => {
return <>{/* ... Display products */}</>;
};
export default graphql(SuggestedProductsQuery, {
options: (props) => {
/*
* `profileId` is only used of Personalised Recommendations.
* See: https://attraqt.gitbook.io/developer-documentation/xo-recommendations/using-the-recommendations-api#personalised-recommendation
*
* The best way to retrieve the customer's profileId might vary depending on your use case.
* See with your Attraqt representative the best way to retrieve it for your use case.
*/
const profileId = getAttraqtProfileId();
return {
variables: {
input: {
profileId,
},
},
};
},
props: ({ data }) => {
return {
recommendation: data.loading ? null : data.productRecommendation,
};
},
})(SuggestedProducts);
If you are using XO Recommendations API with Attraqt Activity pipeline, the profileId will be must be prefixed with "sessionid/", like so:
const prefixedProfileId = "sessionid/" + profileId;
Please note that this example is only one way of retrieving recommendations from Attraqt Recommendations API. A better solution could be implemented depending on your use case.
Using Attraqt Orchestrator Chrome extension
In order to use the Attraqt Orchestrator extension for Google Chrome, Front-Commerce provides a front-end component which does the needed setup. Given the example above, you will need to update your front-end component, and use it to initialize Attraqt Orchestrator:
import React from "react";
import AttraqtRecommendationChromeExtensionRegisterer from "theme/modules/AttraqtRecommendations/attraqtRecommendationChromeExtensionRegisterer.js";
import { graphql } from "react-apollo";
import SuggestedProductsQuery from "./SuggestedProductsQuery.gql";
const SuggestedProducts = ({ recommendation }) => {
return (
<>
<AttraqtRecommendationChromeExtensionRegisterer
recommendation={recommendation}
/>
{/* ... Display products */}
</>
);
};
// ...
With this change, Attraqt's Chrome extension should be initialized correctly
when accessing the page were SuggestedProducts
is used.
Fallback Search
Since version 2.15
If no search module is configured Front-Commerce will default to using the native Magento search API to do the search.
native Magento search API uses the price without tax value to achieve its price
filtering capabilities. This is not what customers typically expect. To overcome
this you need to set FRONT_COMMERCE_MAGENTO_SEARCH_TAX_RATE
to the expected
tax rate on your site. Please note this may not work for all scenarios as you
may have different tax rates depending on country. So we recommend you use the
tax rate that most applies to your customers.