Search engine
When configured with Magento1 , 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 search
Front-Commerce supports browsing products using the native Magento API for category listing pages. Please contact us if your store uses a custom Magento search implementation to see how to make it work in your Front-Commerce project.
Elasticsearch
Requirements
On Magento's side, you need to install
the front-commerce-oss/magento1-elasticsuite-indexer
module.
You can install it with composer:
composer require front-commerce-oss/magento1-elasticsuite-indexer
After the installation, you need to configure it, at least:
- in System > Catalog > Catalog in the Catalog Search section, make sure the search engine is set on Smile Searchandising Suite
- in the same section, set the server host and port
- take note of the alias (
magento
by default)
You can then run the indexer so that the products, categories and cms pages are indexed in Elasticsearch.
Front-Commerce configuration
First, you need to make sure the Elasticsearch search client is installed with a version that matches your ElasticSearch server:
npm i @elastic/elasticsearch@6
On Front-Commerce side, you need to enable the Elasticsearch datasource by
making the changes in your .front-commerce.js
file similar to:
- modules: [],
+ modules: ["./node_modules/front-commerce/modules/datasource-elasticsearch"],
serverModules: [
{ name: "FrontCommerce", path: "server/modules/front-commerce" },
+ {
+ name: "Magento1Elasticsearch",
+ path: "datasource-elasticsearch/server/modules/magento1-elasticsearch",
+ },
{ name: "Magento1", path: "server/modules/magento1" },
]
Tthe Elasticsearch server module needs to be enabled before the Magento's module.
Then, in your .env
file, you need to define
the FRONT_COMMERCE_ES_HOST
and FRONT_COMMERCE_ES_ALIAS
variables.
After restarting Front-Commerce, you should be able run a GraphQL query to search for products, for instance:
query Search {
search(query: "whatever you want to search for") {
query
products(params: { from: 0, size: 5 }) {
total
products {
sku
name
}
}
}
}
If you are using the default theme or the theme Chocolatine, 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
Requirements
On Magento's side, you need to install
the algolia/algoliasearch-magento
module.
You can install it with modman:
modman clone https://github.com/algolia/algoliasearch-magento.git
After the installation, you need to configure it, at least:
- in System > Algolia Search > Configuration in the Credentials & Setup section, set the Enable Indexing option
- in the same section, fill the credentials you can find on the Algolia Dashboard
- The attribute
category_ids
must be listed in both the facets configuration and in the indexed product attributes (and there it must be set as Searchable) as Front-Commerce relies on it to list the products in categories.
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
On Front-Commerce side, you need to enable the Algolia datasource by making the
changes in your .front-commerce.js
file similar to:
- modules: [],
+ modules: ["./node_modules/front-commerce/modules/datasource-algolia"],
serverModules: [
{ name: "FrontCommerce", path: "server/modules/front-commerce" },
+ {
+ name: "Magento1Algolia",
+ path: "datasource-algolia/server/modules/magento1-algolia",
+ },
{ name: "Magento1", path: "server/modules/magento1" },
]
The Algolia server module needs to be enabled before the Magento's module.
As of Front-Commerce 2.6, Algolia's module is automatically configured. If you
are using Front-Commerce 2.5, you need to define
all the Algolia related environment variables
in your .env
file.
Front-Commerce 2.6 takes 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 is taken into account (Facet type, Label, Searchable and Create Query rule are ignored for now).
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
}
}
}
Support for category or page search with Algolia has been added in Front-Commerce 2.13.
If you are using the default theme or the Chocolatine theme, the search bar should now be visible.
Attraqt
Since version 2.27
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: "Magento1Attraqt",
path: "datasource-attraqt/server/modules/magento1-attraqt",
},
{ name: "Magento1", path: "server/modules/magento1" },
],
};
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
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: "Magento1", path: "server/modules/magento1" },
],
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.