Managing Out of Stock Products
Shop owners can easily manage how to deal with out of stock items, and decide whether they should or shouldn’t appear in search results.
This feature is available from the Standard plan.
Available options
You can access this setting from the Search options tab. There are three options:
- Show all out of stock items in search results
All out of stock items remain in search results. - Hide all out of stock items in search results
All out of stock items are removed from search results. - Hide out of stock items - but show those which are marked as available
All out of stock items are removed from search results, except for those with the Continue selling when out of stock setting enabled.
The Continue selling when out of stock is accessible in the product details page of the Shopify Admin interface.
When selecting the Hide out of stock items - but show those which are marked as available option, a reindex might be necessary to ensure we have all the necessary data.
How does it work?
This feature relies on the inventory_quantity
and inventory_policy
properties on the product variants, as provided by Shopify.
Under the hood, we use filters to show or hide out of stock products:
- Show all out of stock items in search results
We don’t apply any filters, as we don’t want to exclude anything. - Hide all out of stock items in search results
We apply theinventory_quantity > 0
filter. - Hide out of stock items - but show those which are marked as available
We apply theinventory_available:true
filter.
The inventory_available
attribute is true
for records when their inventory_quantity
is greater than 0, or if they have the Continue selling when out of stock setting enabled.
Widget changes
We have updated our frontend widgets to support this new feature.
The final versions of the changed widgets can be found in algolia_autocomplete.js.liquid
and algolia_instant_search.js.liquid
.
Autocomplete
The new algolia_autocomplete.js.liquid
file contains 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
@@ -49,6 +49,33 @@
};
}
+ // 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
The new algolia_instant_search.js.liquid
file contains 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) &&