Manage out-of-stock products
Since December 31, 2023, apps can’t modify the code of Shopify themes. For more information, see The Asset API resource in the Shopify documentation. As an alternative, the Algolia AI Search and Discovery app comes with Shopify App Embed and App Blocks to integrate Autocomplete and InstantSearch. To get started, see Quickstart and Algolia configuration.
The Algolia AI Search & Discovery app lets you choose if you want to keep or remove out-of-stock products from the search results.
Out-of-stock policies
Out-of-stock product variants are removed from the search results based on filters.
Filtering relies on the inventory_quantity
and inventory_policy
attributes of the
product variants resource.
A product variant is out-of-stock if the inventory_quantity
attribute is 0.
The inventory_policy
attribute can be allow
if you explicitly decided to continue selling a product when it’s out of stock. Otherwise, this attribute is deny
.
For handling out-of-stock product variants in the search results, you can choose between these policies.
- Include all out-of-stock products in the search results. No filter is applied. All products are included in the search results.
- Remove all out-of-stock products from the search results. A filter
inventory_quantity>0
is applied when searching Only in-stock items are included in the search results. - Remove out-of-stock products, except those marked explicitly as available. A filter
inventory_available:true
is applied when searching. Theinventory_available
attribute is true, when theinventory_quantity
attribute is greater than 0, or when theinventory_policy
attribute is set toallow
for that product.
Select your out-of-stock policy
To select your policy for handling out-of-stock items in the search results:
- In your Shopify admin, open the Algolia AI Search & Discovery app.
-
On the Search options tab, go to the Additional settings > Out of stock items section.
-
Select your policy for handling out-of-stock items:
-
Show all out of stock items in search results. Out-of-stock items are included in the search results. This is the default.
-
Hide all out of stock items in search results. Out-of-stock items are removed from search results.
-
Hide out of stock items - except those marked as available. Out-of-stock items are removed from search results, except products with the Continue selling when out of stock option. After selecting this option, you might need to reindex your product catalog.
-
Continue selling out-of-stock products
To select which products are included in the search results when they’re out of stock:
- Go to the Products page in your Shopify admin.
- Select a product you want to show in the search result when it’s out of stock.
- In the Inventory section, select Track quantity and Continue selling when out of stock.
The selected products are now included in the search results, even when they’re out of stock.
UI updates
The UI widgets of the Algolia AI Search & Discovery app have been updated to support this feature. You can find the Autocomplete and InstantSearch widgets in these files:
Autocomplete updates
In Autocomplete v1, filters are located in the algolia_autocomplete_product_plugin.js.liquid
file:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
+ // Filters for stock policy
+ let stockPolicyFilter = '';
+
+ if (algolia.config.stock_policy === 'deny') {
+ // For 'deny', filter out all items based on inventory quantity
+ stockPolicyFilter = 'inventory_quantity > 0';
+ } else if (algolia.config.stock_policy === 'continue') {
+ /**
+ * For 'continue', filter on an `inventory_available` attribute with a
+ * value dependent on:
+ * `inventory_quantity > 0 OR inventory_policy == 'continue'`
+ */
+ stockPolicyFilter = 'inventory_available:true';
+ }
algolia.productsPlugin = {
getSources({ query, setContext }) {
return [
{
sourceId: 'products',
getItems() {
return getAlgoliaResults({
searchClient: algolia.searchClient,
queries: [
{
indexName: config.index_prefix + 'products',
params: {
query,
hitsPerPage: config.products_autocomplete_hits_per_page,
clickAnalytics: config.analytics_enabled,
+ filters: stockPolicyFilter,
distinct: algolia.config.show_products
},
},
],
In older versions of the Autocomplete widget, the algolia_autocomplete.js.liquid
file includes the following changes:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
+ // Filters for stock policy
+ var stockPolicyFilter = null;
+
+ /**
+ * Filters for stock policy are valid only if:
+ * - stock policy has been defined, AND
+ * - we are targeting products search index
+ */
+ if (algolia.config.stock_policy && section === 'products') {
+ if (algolia.config.stock_policy === 'allow') {
+ /**
+ * For 'allow', we don't need to add any filter as we want to continue
+ * displaying all out of stock items.
+ */
+ } else if (algolia.config.stock_policy === 'deny') {
+ // For 'deny' we will filter out all items based on inventory quantity
+ stockPolicyFilter = 'inventory_quantity > 0';
+ } else if (algolia.config.stock_policy === 'continue') {
+ /**
+ * For 'continue' we will filter on `inventory_available` attribute whose
+ * value is dependent on:
+ * `inventory_quantity > 0 OR inventory_policy == 'continue'`
+ */
+ stockPolicyFilter = 'inventory_available:true';
+ }
+ }
+
return {
name: section,
source: function(query, callback) {
@@ -61,6 +88,12 @@
if (params.distinct) {
searchOpts.distinct = true;
}
+
+ // Add the stock policy filter if applicable
+ if (stockPolicyFilter) {
+ searchOpts.filters = stockPolicyFilter;
+ }
+
index(section)
.search(query, searchOpts)
.then(function(answer) {
InstantSearch updates
The algolia_instant_search.js.liquid
file includes the following changes:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
@@ -25,6 +25,12 @@
return;
}
+ /**
+ * Array which will contain all filters to be applied while initiating the
+ * search API call.
+ */
+ var searchFilters = [];
+
var collectionFacetFilter = null;
var collectionRulesContextValue = null;
if (collectionPage) {
@@ -39,11 +45,40 @@
collectionFacetFilter = 'collections:"' + handle + '"';
}
+ // Add the collection filter to the list of search filters
+ searchFilters.push(collectionFacetFilter);
+
collectionRulesContextValue = algolia.config.collection_id_query_rules
? algolia.current_collection_id
: handle;
}
+ // Filters for stock policy
+ var stockPolicyFilter = null;
+ if (algolia.config.stock_policy) {
+ if (algolia.config.stock_policy === 'allow') {
+ /**
+ * For 'allow', we don't need to add any filter as we want to continue
+ * displaying all out of stock items.
+ */
+ } else if (algolia.config.stock_policy === 'deny') {
+ // For 'deny' we will filter out all items based on inventory quantity
+ stockPolicyFilter = 'inventory_quantity > 0';
+ } else if (algolia.config.stock_policy === 'continue') {
+ /**
+ * For 'continue' we will filter on `inventory_available` attribute whose
+ * value is dependent on:
+ * `inventory_quantity > 0 OR inventory_policy == 'continue'`
+ */
+ stockPolicyFilter = 'inventory_available:true';
+ }
+
+ // Add the stock policy filter to the list of search filters
+ if (stockPolicyFilter) {
+ searchFilters.push(stockPolicyFilter);
+ }
+ }
+
var results_selector = collectionPage
? algolia.config.collection_css_selector
: algolia.config.results_selector;
@@ -130,18 +165,18 @@
searchFunctionHelper.setQueryParameter('distinct', true);
}
- // Collection page features
- if (collectionPage) {
- // Collection page filtering
- if (collectionFacetFilter) {
+ // Assign any required filters
+ if (searchFilters.length) {
searchFunctionHelper.setQueryParameter(
'filters',
- collectionFacetFilter
+ searchFilters.join(' AND ')
);
}
+ // Assign any required `ruleContexts` which are required for query rules
+ // targeting collection pages
+ if (collectionPage) {
// Collection page merchandising:
-
// send rulesContext for promoted results only if no filters active
if (
!hasRefinements(searchFunctionHelper, instant.facets.list) &&