Search App
The application provides integration with Algolia search engine. It allows you to index your products, categories, and pages — then search them using Algolia's API.
Features​
- Synchronize products, categories, and pages with Algolia
- Update Algolia indices on product, category, and page changes
- Selective page indexing — choose which page types to sync
Assumptions & limitations​
- Initial synchronization has to be done manually in the App
- The application creates a separate record for each product variant
- A single record size is limited due to Algolia record size constraint. That means the data attached to your records such as the number of attributes or wrong field filtering configuration in the app settings can lead to exceeding that limitation. In that case, the app cannot store your record.
- Each of the channels is indexed separately
- At this moment translations are not supported
- The exact state of the product quantity is not indexed, only the boolean value (in stock / out of stock)
- Page indexing is selective — you choose which page types to sync. You can disable specific page fields globally to keep records within the size limit.
- The app will synchronize data on the following events:
PRODUCT_CREATEDPRODUCT_UPDATEDPRODUCT_DELETEDPRODUCT_VARIANT_CREATEDPRODUCT_VARIANT_UPDATEDPRODUCT_VARIANT_DELETEDPRODUCT_VARIANT_OUT_OF_STOCKPRODUCT_VARIANT_BACK_IN_STOCKCATEGORY_CREATEDCATEGORY_UPDATEDCATEGORY_DELETEDPAGE_CREATEDPAGE_UPDATEDPAGE_DELETED
Glossary​
- Algolia record: single entry in the Algolia index. Each product variant, category, and page is a separate record.
- Index: a collection of Algolia records. Separate indices are created for products, categories, and pages within each channel. Each products channel creates separate index, but pages and categories have their own single indices.
Permissions required by the app​
MANAGE_PRODUCTSMANAGE_PRODUCT_TYPES_AND_ATTRIBUTESMANAGE_PAGES
Application flow​
Pre-requisites​
- Algolia account. The free account will be sufficient, but has additional limitations, like maximum record size.
- Saleor user with
MANAGE_APPS,MANAGE_PRODUCTS,MANAGE_PRODUCT_TYPES_AND_ATTRIBUTESandMANAGE_PAGESpermissions.
If you have installed the app before indexing pages and categories have been introduced, you need to reinstall the app to grant new permissions
Configuration​
- Go to API Keys section in the Algolia dashboard to obtain API credentials
- Go to the Search App dashboard and fill required fields:
- Application ID
- Admin API Key
- Index name prefix is optional, but recommended if you want to use the same Algolia account for multiple Saleor instances
- Click
Save
The application is now connected to your Algolia account. You can start synchronizing your data:
- Click on the
Start importingbutton to bulk-import products, categories, and pages - Wait for the synchronization to finish.
- After the process is finished, apply recommended settings to the indices using the
Update indices configurationbutton in theSet indices settingssection
Synchronization works on the frontend side, which means the App must remain open during this operation. In large shops, this operation can take a few seconds.
The application should now be configured and synchronized. You can start making queries using the Algolia API or browse the data in the Algolia dashboard. Changes to products, categories, and pages will be automatically synchronized via webhooks.
Page type selection​
Not every page belongs in search results. In the App configuration, you can select which page types should be indexed. Only pages of the selected types will be synced to Algolia.
To keep records lean, you can disable the attributes, metadata, seoDescription, or contentPlaintext fields globally for page records in the Algolia fields filtering section.
Fields configuration​
Due to performance reasons, Algolia enforces a limit on the maximum size of the record. This means that not all data can be indexed. The application allows you to configure which fields should be used.
The configuration is done in the Algolia fields filtering section of the App dashboard. By default, all are enabled. You can disable fields that you don't need in your search (for example product metadata or descriptions).
Data model​
Indices​
Each channel creates separate indices for products, categories, and pages. The index names are formatted as follows:
- Products:
OPTIONAL_PREFIX.CHANNEL_SLUG.CURRENCY_CODE.products— e.g.dev.default-channel.USD.products - Categories:
OPTIONAL_PREFIX.categories— e.g.dev.categories - Pages:
OPTIONAL_PREFIX.pages— e.g.dev.pages
The OPTIONAL_PREFIX is used to distinguish between different Saleor instances, so you can use the same Algolia account for multiple data sources (e.g. staging and production).
Values for the price and availability in the product index are chosen according to the chosen channel.
Product record fields​
objectID: Unique ID of the record, used by Algolia. It's a concatenation of theproductIdandvariantIdfields, separated by_productId: Product IDvariantId: Product Variant IDproductTypeId: Product Type ID. The field is used for facetingcategoryId: Category ID. The field is used for facetingcategorySlug: Category slug. The field is used for search and facetingname: Joined product and variant name (format:Product Name - Variant Name). The field is used for the searchproductName: Product name. The field is used for the searchvariantName: Variant name. The field is used for the searchsku: Variant SKUattributes: List of product and variant attributes with their values. The field is used for search and facetingmedia: List of product mediaurl: URL of the media filetype: Type of the media file. Possible values:IMAGE,VIDEO
description: Product description in the EditorJS formatdescriptionPlaintext: Product description in the plaintext. The field is used for the searchslug: Product slugthumbnail: URL for the Product thumbnailgrossPrice: Base price of the product in the channel's currency. The field is used for facetingpricing: Detailed pricing object with the following nested fields, all used for faceting:pricing.price.net,pricing.price.gross: Current pricepricing.discount.net,pricing.discount.gross: Discount amountpricing.priceUndiscounted.net,pricing.priceUndiscounted.gross: Price before discountpricing.onSale: Boolean indicating if the variant is on sale
inStock: Boolean value indicating if the product is in stock. The field is used for facetingcategories: Hierarchical list of product categories, formatted according to the Algolia guidelines. The field is used for facetingcollections: List of collection names the product belongs to. The field is used for facetingmetadata: Key-value pairs of product metadatavariantMetadata: Key-value pairs of variant metadataotherVariants: List of other variant IDs of the product
Category record fields​
Categories are stored in a dedicated index with the following fields:
objectID: Category ID, used by Algolianame: Category name. The field is used for searchslug: Category slug. The field is used for searchlevel: Depth in the category tree. The field is used for facetingancestors: Flat array of parent categories, each containingid,name, andslug— useful for breadcrumb rendering. The field is used for search and facetingmetadata: Key-value pairs of category metadata. The field is used for faceting_type: Always"category". Useful for distinguishing record types in unified search results
Page records​
Pages are stored in a dedicated index. You choose which page types to sync in the App configuration — only pages of the selected types will be indexed.
To keep records within the Algolia size limit, you can disable the attributes, metadata, seoDescription, or contentPlaintext fields globally for page records in the Algolia fields filtering section. The exact set of indexed fields depends on your configuration.
Every page record includes a _type field set to "page" and a pageTypeId field (used for faceting), so you can distinguish page results and filter by page type in your storefront.
Making queries​
The Search App is responsible only for indexing the data. To make queries you need to use the Algolia API directly. You can use the Algolia JavaScript client. The example below shows how to make a simple search query using it:
const algoliasearch = require("algoliasearch");
// Replace with your own values
const APP_ID = "APP_ID";
const API_KEY = "API_KEY";
const INDEX_NAME = "dev.default-channel.USD.products";
// Initialize the client
const client = algoliasearch(APP_ID, API_KEY);
const index = client.initIndex(INDEX_NAME);
// Example search query
index.search("squeezed juice").then(({ hits }) => {
console.log(hits);
});
Running the example above will return the following results:
[
{
"objectID": "UHJvZHVjdDoxNTU=_UHJvZHVjdFZhcmlhbnQ6Mzg3",
"productId": "UHJvZHVjdDoxNTU=",
"variantId": "UHJvZHVjdFZhcmlhbnQ6Mzg3",
"productTypeId": "UHJvZHVjdFR5cGU6OQ==",
"categoryId": "Q2F0ZWdvcnk6MTQ=",
"categorySlug": "juices",
"name": "Carrot Juice - UHJvZHVjdFZhcmlhbnQ6Mzg3",
"productName": "Carrot Juice",
"variantName": "UHJvZHVjdFZhcmlhbnQ6Mzg3",
"sku": "CJ-001",
"attributes": {
"Flavor": "Carrot"
},
"media": [
{
"url": "https://example.saleor.cloud/media/thumbnails/products/saleor-carrot-drink_thumbnail_4096.png",
"type": "IMAGE"
}
],
"description": {
"time": 1652790989820,
"blocks": [
{
"id": "VWVrSI_Cza",
"data": {
"text": "Improve your eyesight the natural way with <b>100% pure, squeezed carrot juice</b>. The sweet, orange nectar of <i>Mother Earth</i>."
},
"type": "paragraph"
}
],
"version": "2.22.2"
},
"descriptionPlaintext": "Improve your eyesight the natural way with 100% pure, squeezed carrot juice. The sweet, orange nectar of Mother Earth.",
"slug": "carrot-juice",
"thumbnail": "https://example.saleor.cloud/media/thumbnails/products/saleor-carrot-drink_thumbnail_256.png",
"grossPrice": 1.99,
"pricing": {
"price": { "net": 1.99, "gross": 2.45 },
"discount": { "net": 0, "gross": 0 },
"priceUndiscounted": { "net": 1.99, "gross": 2.45 },
"onSale": false
},
"inStock": true,
"categories": {
"lvl0": "Groceries",
"lvl1": "Groceries > Juices"
},
"collections": [],
"metadata": {},
"variantMetadata": {},
"otherVariants": [],
"_highlightResult": {
"name": {
"value": "Carrot <em>Juice</em> - UHJvZHVjdFZhcmlhbnQ6Mzg3",
"matchLevel": "partial",
"fullyHighlighted": false,
"matchedWords": ["juice"]
},
"productName": {
"value": "Carrot <em>Juice</em>",
"matchLevel": "partial",
"fullyHighlighted": false,
"matchedWords": ["juice"]
},
"variantName": {
"value": "UHJvZHVjdFZhcmlhbnQ6Mzg3",
"matchLevel": "none",
"matchedWords": []
},
"descriptionPlaintext": {
"value": "Improve your eyesight the natural way with 100% pure, <em>squeezed</em> carrot <em>juice</em>. The sweet, orange nectar of Mother Earth.",
"matchLevel": "full",
"fullyHighlighted": false,
"matchedWords": ["squeezed", "juice"]
}
}
}
]
Grouping results​
Since each variant is a separate record in the Algolia index, our recommended settings apply grouping to the results. This means that the results are grouped by the Product ID, and the variant with the highest score is returned as the main result.
Read more about grouping in the Algolia recordation.
Custom faceting​
The application pre-configures faceting settings for indexes. You can modify their visibility and other settings in the Algolia dashboard. Read more about faceting in the Algolia recordation.
Examples of building interfaces with faceting can be found in the Inspiration Library.
Troubleshooting​
Record size limit exceeded​
If you see an error like this in your Saleor Dashboard webhook deliveries:
Product variant UHJvZHVjdFZhcmlhbnQ6MTIz exceeds Algolia's record size limit (10KB).
Current size: 15000 bytes, limit: 10000 bytes.
Cause: Algolia enforces a maximum record size of 10KB (or more depending on your plan). Products with large descriptions, many attributes, or extensive metadata can exceed this limit. Pages with heavy content blocks can also hit this limit.
Solution: Go to Search App settings in Saleor Dashboard and disable fields you don't need in the "Algolia fields filtering" section:
description/descriptionPlaintext- often the largest fields, especially for products with rich HTML contentmetadata/variantMetadata- can contain large amounts of custom datamedia- if you don't need media URLs in search results
For pages, you can disable the attributes, metadata, seoDescription, or contentPlaintext fields globally in the same Algolia fields filtering section.
Alternative: If you still need a searchable description, create a shorter product attribute (e.g., algoliaDescription) with a condensed version of your description. Product attributes are automatically synced to Algolia and can be used for search.
Development​
To run the application locally, follow the Running Saleor Apps locally article.