Autocomplete, InstantSearch, and Recommend in the Algolia app blocks now support version 5 of the Algolia API client.
Most stores only need to switch the search client version setting to Version 5.
If you use custom storefront JavaScript, follow the version 5 upgrade guide.
Support for version 4 ends on August 14, 2026.
- Variant-level. One Algolia record per Shopify variant. The default.
- Product-level. One record per Shopify product, with its variants nested inside the record.
PREFIX_products.
The mode changes the shape of the records in it, which attributes you can facet and sort on,
and how your storefront renders results.
How to get access
This is a beta feature according to Algolia’s Terms of Service (“Beta Services”).
Choose an indexing mode
Choose product-level indexing if you want:- One card per product
- Built-in color swatches
- A lower record count
- Click and conversion events consolidated on product IDs
- Algolia features that read per-product signals, such as Recommend, Dynamic Re-Ranking, and NeuralSearch. Algolia’s ecommerce record guidance recommends the product-level model for them
- Shoppers need to land on a specific variant from search results
- You facet or sort on per-variant attributes, such as SKU or weight
- Your shoppers filter on two or more facets at once, such as color and size. See Facet combinations across variants
Facet combinations across variants
If your shoppers filter across two or more facets, use variant-level indexing with Display one result per product. That returns one card per product while filters still apply per variant, so combinations stay accurate. Product-level indexing turns that setting off, so the two approaches are mutually exclusive. Product-level records don’t fit this case because a product record carries the option values of all its variants in one place. Algolia treats each nested attribute as multi-valued, so two refinements combine at the product level, never within a single variant. Take a product with two variants, Black/128GB and White/256GB. The record holdsBlack, White, 128GB, and 256GB.
Filtering on Color Black and Size 256GB returns that product, even though no such variant exists.
The same applies to any pair of per-variant attributes:
- Option against option. Color and size, or color and material.
- Option against price. If Black costs 300 and White costs 150, filtering on Color
Blackand a 100 to 200 price bucket returns the product. - Option against stock.
inventory_availableandvariants_inventory_countdescribe the whole product, so ColorBlackplus in-stock means the product has a Black variant and has stock somewhere, not that Black is in stock.
Limits to check before you switch
- High variant counts. A product record holds every variant, so a product that fit as many small variant records can exceed Algolia’s record size limit as one product record. Algolia rejects the oversized record, and that product goes missing from search results. Selecting more optional fields makes this more likely.
- SKU and barcode search. These don’t work until you adjust your searchable attributes. See Searchable attributes.
- Discount and weight sorts. Neither has a product-level equivalent. See Sort orders.
Turn on product-level indexing
- In your Shopify admin, open the Algolia AI Search & Discovery app.
- Go to Indexing.
- In the Indexing section, make sure Index my Catalog is selected.
- Under Indexing mode, read the Review required before changing indexing mode banner. Select the checkbox to confirm you’ve reviewed it, then select Confirm. The mode options, the field checklist, and Save stay locked until you do.
- Select Product.
- Optional: to add per-variant data to your records, select the fields you want in the checklist under Product. See Product record fields.
- Select Save, then select Continue to confirm the reindex.
- The acknowledgement is stored in your browser, per store and per browser. It isn’t saved to your account. In a private window, or in a browser that blocks site data, you confirm again each time you open the app.
- The reindex is queued, not immediate. The reindex indicator appears on the next status refresh rather than on save, so a short delay isn’t a failed save.
Product record schema
Algolia stores your products in the following format:JavaScript
market_pricing_CURRENCY object.
In product-level mode, that object holds the product-level price fields, such as variants_min_price and variants_max_price,
instead of the variant-level variant_min_price and variant_max_price.
Product records don’t include created_at or updated_at.
The field checklist doesn’t have an entry for either, so theme code that reads them at the top level of a product record finds nothing.
published_at is unaffected and always present.
Variant sub-records
Each product record holds avariants array with one entry per variant, excluding variants whose title contains [hidden].
Publication status, the algolia-ignore tag, and [hidden] in the product title all apply to the whole product rather than to single variants.
Variant sub-records keep the per-variant data that a product record can’t hold at the top level:
price, inventory, option values, and variant metafields.
variantID isn’t an objectID.
Algolia ranks, facets, and counts the product record, not its variant entries.
A query that matches one variant returns the whole product.
Metafields appear at both levels.
Product metafields land in the record’s meta, and variant metafields in variants[].meta.
Product record fields
By default, product records stay small and carry only what search, faceting, and the product card need. Per-variant fields are opt-in. The checklist sits under the Product option in the Indexing section, and only in product-level mode. Select the fields you want, then select Save and confirm the reindex.variants[].options, variants[].price, variants[].compare_at_price, variants[].price_ratio,
and variants[].inventory_available are always included.
Clearing Variant options removes only the flat option1, option2, and option3 fields.
Option data stays in variants[].options and option_names.
If you enabled locations inventory, the app adds variants[].locations_inventory for you.
Selecting more fields makes each record larger.
On a catalog with many variants per product, that raises the risk of exceeding Algolia’s record size limit.
See Limits to check before you switch.
Older per-attribute settings for weight, requires shipping, and inventory locations combine with this checklist rather than replacing it.
If your store has one turned on, that field stays in your records even when you clear the checkbox here.
Product-level mode also hides those older toggles, so contact
Algolia support to check or turn them off.
Swatches
Product-level records index Shopify’s option value swatches. For every product option whose values carry a swatch, the app adds an entry toswatches with the option name and its values,
each with a hex color, an image, or both.
The app skips options without swatch data, so a product with no swatches in Shopify has no swatches attribute.
The app also skips a custom option with plain text values, such as a Color option with “Red” and “Blue” and no swatches set.
There’s no setting to turn swatches on or off.
Swatch colors and images live on Shopify metaobjects rather than on the product, and the app’s real-time
updates follow product changes.
Editing a swatch’s color or image therefore doesn’t reach your records on its own, and the swatches
attribute keeps its last indexed value.
Other edits to the product reach your records as usual.
To pick up a swatch edit, update the product or trigger a
full reindex
from the Indexing tab.
If a product card doesn’t show a swatch row, check that the product’s option values have swatches assigned in
the Shopify admin, then update the product or reindex.
For how swatch chips render on search results, see Product cards.
Preselected swatches
A card doesn’t always show the product’s default option value. The app blocks preselect a swatch chip, swap the card image to that value’s photo, and point the card at that value’s variant when either of these happens:- The shopper refines a swatch option. Refining Color to “Blue” preselects Blue on every card that has it. When the shopper refines several values, the first of the card’s own swatch values wins. That order is the one
beforeInstantSearchSwatchOptionResolverproduces, so a hook that reorders chips changes which refined value wins. - The query matches a swatch name. Searching “blue” preselects the Blue chip, because the app adds
swatches.values.nameto your searchable attributes.
swatches.values.name.
The app marks the chip on first render and doesn’t fire the afterInstantSearchSwatchClick hook.
To override which chip is marked, or to sort matched chips first, use beforeInstantSearchTransformItems
and edit _matched on the swatch option.
Product cards
Product-level cards describe a product, so they differ from variant-level cards:
Selecting a swatch chip swaps the image, marks the chip selected, and updates the card link.
It doesn’t navigate.
Availability comes from the variants that match the chip, so sold-out values render crossed out and faded.
Sold-out chips stay selectable, and the chips aren’t reachable by keyboard.
Autocomplete rows show the product’s hero image, the same price range, and a plain product link.
They don’t have a swatch row.
Custom code that reads record attributes needs to know the mode.
Use
hit._productLevel inside template and transform hooks, because it describes the record being rendered.
Use window.algoliaShopify.config.indexing_mode, which returns "product" or "variant", only when building query parameters.
The two can disagree during a reindex, and the per-hit value is the reliable one.
Facets
The app rewrites the facets you configure in the Search options tab onto the product record shape, for search and for collection pages:
The app always keeps these facets on:
tags, option_names, variants.options,
filterOnly(inventory_available), and filterOnly(variants_inventory_count).
Named tags add named_tags_names and named_tags, and collection indexing adds searchable(collections) and collection_ids.
Your saved configuration keeps the variant-level names, and the app translates them on each write.
The Algolia dashboard therefore shows variants.options.color in your index settings while the app shows options.color.
That mismatch is deliberate.
If your store’s stock policy is deny, the app blocks filter on variants_inventory_count > 0
instead of inventory_quantity > 0.
Filters in your own theme code have the same problem.
If you filter on inventory_quantity > 0, as the
out-of-stock products page describes,
switch to inventory_available or variants_inventory_count.
Facet panels with no values
A facet panel on your storefront can render its header without returning any values. Three causes:- Price bucket facets. The app blocks query
price_rangewhile your index is faceted onprice_ranges. Use a price range facet only if you configure the attribute by hand in the Algolia dashboard. - Hierarchical facets. A hierarchical facet on an option or on price sends a variant-level attribute path for each level of the hierarchy, so it doesn’t match the remapped attributes. Use a standard facet instead.
- A stale storefront configuration. The remapping runs from the app’s configuration in your theme. If that configuration is missing or predates the mode change, the storefront queries variant-level attribute names against product records. Cards still render correctly, which makes this hard to spot. Saving in the app rewrites it.
Sort orders
Each sort order is backed by a replica index that ranks on one attribute. Product-level mode re-points the sort orders whose attribute moved, and turns off the ones with no product-level equivalent.
These are the default labels. You can rename any sort order, so your list can differ.
The app deactivates Highest discount first and Heaviest first on save and hides them from the
Sort orders list, so you can’t activate them.
Selecting Weight in the field checklist still adds weight data to your records, but the app doesn’t provide a product-level weight sort.
Deactivating a sort order deletes its replica index.
The search analytics attached to that replica go with it.
Switching back to variant-level mode lists both sort orders again, still deactivated, and re-enabling them builds new replicas.
Product-level records don’t need Display one result per product, described on the
index schema page,
so the app turns it off, hides the control, and stops applying
distinct on search results.
A stale attributeForDistinct value can remain in your
index settings, where it’s visible in the Algolia dashboard but doesn’t have any effect.
After any full reindex, including a mode change, recently_ordered_count restarts from nothing and
rebuilds as orders come in, so Most popular ranks on an empty attribute until orders accumulate.
Searchable attributes
When you switch to product-level mode, the app addsunordered(swatches.values.name) to your
searchable attributes so shoppers can search on swatch names,
and disables typo tolerance on that attribute.
It leaves the rest of the list alone, and the default list targets variant-level records:
unordered(vendor)unordered(title)unordered(variant_title)product_typeunordered(tags)unordered(handle)skubarcodeunordered(body_html_safe)
variant_title, sku, and barcode don’t exist at the top level of the record,
so those three entries match nothing and shoppers can’t find products by SKU or barcode.
To restore them, edit Searchable attributes in the Algolia dashboard, under
Search > Configuration > Relevance Essentials > Searchable attributes, and replace those entries with their nested paths:
unordered(variants.variant_title)variants.skuvariants.barcode
variants[].sku and variants[].barcode only exist if you selected SKU and Barcode in
Product record fields, so select those first.
Switching back to variant-level mode doesn’t remove the swatch entry.
It matches nothing on variant records, so it’s safe to leave in place.
Custom ranking
The default custom ranking the app applies to a new index referencesrecently_ordered_count, updated_at, and the flat variant option fields.
On product-level records, updated_at is absent and option1, option2, and option3 exist only if you select Variant options.
Review your custom ranking in the Algolia dashboard after you switch, and replace any criterion
that points at an attribute your product records don’t carry.
Migrate from variant-level indexing
The app changes indexing mode in place and runs a full reindex. The app doesn’t move the work you did in the Algolia dashboard. Your rules, pins, and synonyms reference variantobjectIDs and variant-level attributes, and every variant record disappears at the swap.
Plan the migration in the order below.
Understand what changes in your records
Every attribute that describes a single variant moves undervariants.
Everything that describes the product stays where it is.
These stay unchanged:
title, handle, vendor, product_type, tags, named_tags_names, body_html_safe,
option_names, variants_min_price, variants_max_price, variants_compare_at_price_min, variants_compare_at_price_max,
variants_inventory_count, inventory_available, collections, collection_ids,
category, recently_ordered_count, and _tags.
The table above doesn’t capture these:
variants_inventory_count and recently_ordered_count are unretrievable by default on new indices.
They’re on the record and available for filtering and sorting, but your theme can’t read them unless you change that setting.
Know what you lose
- Variant-level search results. A query for “red” returns the whole product, not its red variant. Product cards link to the product detail page, where the shopper picks the variant. Selecting a swatch chip points the card at that value’s variant, so shoppers can still reach one from search results.
- Accurate facet combinations. See Facet combinations across variants.
- Per-variant pricing on cards. Cards show a price range built from
variants_min_priceandvariants_max_price, with no compare-at price and no sale badge. - Discount and weight sort orders. Their replica indices, and the analytics on them, go too. See Sort orders.
- Recommend widget rendering. See the warning in Product cards.
- Click and conversion history. Your Algolia analytics, Recommend models, Dynamic Re-Ranking, and Personalization profiles are keyed on variant
objectIDs. Those IDs stop existing. Recommend results stay degraded until the models retrain against the product records. Historical analytics don’t carry over. - Rules, pins, and synonyms that reference variants. A pin on a variant
objectIDnever matches a record again.
Know what the app updates for you
When you change indexing mode, the app:- Re-points its indexing pipeline to build product records, and reindexes the catalog.
- Remaps the facets you configured in the app onto the product record shape, for search and for collection pages.
- Rebuilds sort-order replicas on the product-level ranking attributes, and deactivates the two with no equivalent.
- Turns off Display one result per product.
- Adds
swatchesto your records. - Adds
swatches.values.nameto your searchable attributes. - Sends product
objectIDs from the Shopify web pixel, so add-to-cart and purchase events attribute to your product records. - Keeps your saved configuration, so switching back to variant-level mode restores the facets and sort orders the app remapped.
- Collection facet ordering rules. They keep their variant-level attribute names. Re-save the facets on each collection after the switch.
- Index settings you changed by hand. The reindex preserves them rather than rewriting them for the new record shape, and saving settings in the app can overwrite them.
Update your configuration and theme
Before you change the mode:-
Audit your facets. Any facet on a per-variant attribute needs a
variants.prefix. See the warning in Facets. - Audit your searchable attributes. SKU and barcode search stops working until you re-point them. See Searchable attributes.
-
Audit your theme code and custom hooks. Search for
hit.id,hit.price,hit.sku,hit.variant_title,hit.inventory_quantity,hit.options, andhit.image. Each one moved.hit.objectIDreplaceshit.id. -
Check any code that reads dates.
hit.published_atchanges from an ISO-8601 string to an integer Unix timestamp, so date parsing and formatting on it needs updating.hit.created_atandhit.updated_atdisappear from product records. -
Consolidate variant metafields you facet or filter on. Copy the value to a product metafield in the Shopify admin so it lands in the product record’s
meta. -
Export your rules, pins, and synonyms. Record which ones reference variant
objectIDs. You re-create those as productobjectIDs after the switch. - Select your Product record fields. Adding a field later triggers another full reindex.
- Check your largest products. Count the variants on the products with the most of them, and test those in a development store. See Limits to check before you switch.
-
Re-create pins and rules against product
objectIDs. - Re-save the facets on each collection.
- Review your custom ranking. See Custom ranking.
- Check that each sort order returns the expected order. Replicas re-rank after the records land, so give them a few minutes on a large catalog.
- Expect degraded Recommend results until the models retrain on the product index.
Verify the switch
Check the search requests your storefront sends, not how the cards look. Product cards read the record they’re given, so they render correctly even when your storefront still queries variant-level attribute names. Faceting and stock filtering fail silently in that state. For each of these, confirm the request and the response rather than the page:- Facet panels return values, and the counts change as you refine.
- The stock policy filter names
variants_inventory_countorinventory_available. - Price faceting names
price_ranges. - A search for a SKU returns the product, if you re-pointed your searchable attributes.