Collection Search Page Migration
Introduction
Algolia Search - Instant Search (1.57.0) brings improvements to the Collection page feature:
- Improved indexing stability
- Preparation for upcoming collection customisations and merchandising
The migration doesn’t apply to you if you installed Algolia Search - Instant Search after July 30th, 2019 or if you do not use the Collection page feature.
Depending on your implementation of the plugin, you should either do this migration:
- Automatically via the plugin admin panel. This applies if you have enabled autocomplete, InstantSearch and other front-end features through the plugin.
- Manually, if you have a custom implementation.
Automatic migration from the admin
To automatically upgrade your shop to Algolia Search - Instant Search (1.57.0), please follow the steps from the upgrade wizard.
Clicking on Upgrade shop triggers the following actions:
- Full reindex of your products and collections: this update changes the way we index products to bring more reliability and better indexing performances.
- Update of your front-end Algolia widgets: changing the way we index products requires an update of the installed Algolia widgets.
If you have changed or customized your theme by manually editing the scripts of the plugin, you must perform the migration manually. Otherwise, you will lose your changes.
If the upgrade wizard doesn’t show up, please contact us.
Manual migration
If your shop has a custom front-end implementation, you have to manually update your theme.
Algolia Search - Instant Search (1.17.0) changes the way collection page products are indexed to Algolia, and brings customization of Collections page (Facets, Sort Orders).
This requires changing the following part in your front-end implementation:
- Products filtering
- Query Rules
- CSS selector logic
- Facets and Sort Orders logic
This section provides you all the steps to migrate depending on your implementation:
- You are using the InstantSearch widget, which you customized.
- You have a custom implementation, using an InstantSearch library on your own.
Before updating the code, open the Algolia Search - Instant Search application and click on the Update shop button. This will reindex your products and collections with the proper attributes needed for the code update.
If the upgrade wizard doesn’t show up, please contact us.
Migrate InstantSearch Widget customizations
You’ve installed Algolia through the widgets provided by the plug-in, but you brought some changes to these files that are now custom.
1. Create the algolia_current_collection_id.liquid
file
The InstantSearch widget needs the current collection’s ID from the current collection page to query the proper products.
To do so, we need to communicate the value of the current collection’s ID to the algolia_instant_search.js
file.
Current collection information is only accessible from Liquid files, which are evaluated by the Shopify back end before rendering the page.
For this reason, we need to create the algolia_current_collection_id.liquid
snippet file.
1. Open the theme code editor.
2. Create a new snippet file named algolia_current_collection_id.liquid
.
3. Add the following content and save the file:
1
2
3
{
"currentCollectionID": {{collection.id}}
}
4. Open the layout/theme.liquid
file.
5. Add the following line before the template_algolia_money_format
script tag:
1
<script type="text/template" id="template_algolia_current_collection_id">{% include 'algolia_current_collection_id' %}</script>
6. Save changes to the layout/theme.liquid
file.
2. Update the algolia_init.js
file
You now have the current collection’s ID in the <template id="template_algolia_current_collection_id">
,
you need to store this current collection’s ID in a JavaScript variable in order to be able to use it with InstantSearch.
Right before this line (around line 81):
1
return '$' + val;
Add the following snippet:
1
2
3
4
5
6
7
8
9
10
// Current collection page ID
const current_collection_id_string = algolia
.getTemplate("current_collection_id")
.replace(/^\s+|\s+$/g, "");
if (!!current_collection_id_string) {
const current_collection_id_object = JSON.parse(current_collection_id_string);
algolia.current_collection_id =
current_collection_id_object.currentCollectionID;
}
3. Update the algolia_facets.js
file
The plugin now lets you configure Facets for collections page.
To enable it, you need to update the algolia_facets.js
file.
Right before this line (around line 119):
1
}(algoliaShopify));
Add the following snippet:
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
// Try to fetch facets for current collection or fallback to collections default
const collection_facets =
algolia.current_collection_id &&
algolia.config.collection_facets[algolia.current_collection_id]
? algolia.config.collection_facets[algolia.current_collection_id]
: algolia.config.collection_facets &&
algolia.config.collection_facets.default;
if (collection_facets) {
var enabledCollectionFacets = _.filter(collection_facets, function(facet) {
return facet.enabled || parseInt(facet.enabled);
});
algolia.collectionFacets = _.map(enabledCollectionFacets, function(facet) {
return Object.assign({}, facet, {
escapedName: encodeURIComponent(facet.name)
});
});
algolia.collectionShownFacets = _.filter(algolia.collectionFacets, function(
facet
) {
return facet.type !== "hidden";
});
algolia.collectionHiddenFacets = _.filter(collection_facets, function(facet) {
return facet.type === "hidden";
});
algolia.collectionFacetsWidgets = _.map(
algolia.collectionShownFacets,
facetToWidget
);
}
4. Update the algolia_sort_orders.js
file
The plugin now lets you configure Sort Orders for collections page.
To enable it, you need to update the algolia_sort_orders.js
file.
Right before this line (around line 18):
1
}(algoliaShopify));
Add the following snippet:
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
// Try to fetch sort orders for current collection or fallback to collections default
const collection_sort_orders =
algolia.current_collection_id &&
algolia.config.collection_sort_orders[algolia.current_collection_id]
? algolia.config.collection_sort_orders[algolia.current_collection_id]
: algolia.config.collection_sort_orders &&
algolia.config.collection_sort_orders.default;
if (collection_sort_orders) {
algolia.collectionSortOrders = [
{ name: sort_order_base, label: "" + algolia.translations.relevance }
];
_.forEach(collection_sort_orders, function(sort_order) {
if (
!_.isUndefined(sort_order.asc) &&
!_.isNull(sort_order.asc) &&
(sort_order.asc.active === true || sort_order.asc.active === "1")
) {
algolia.collectionSortOrders.push({
name: sort_order_base + "_" + sort_order.key + "_asc",
label: sort_order.asc.title
});
}
if (
!_.isUndefined(sort_order.desc) &&
!_.isNull(sort_order.desc) &&
(sort_order.desc.active === true || sort_order.desc.active === "1")
) {
algolia.collectionSortOrders.push({
name: sort_order_base + "_" + sort_order.key + "_desc",
label: sort_order.desc.title
});
}
});
}
5. Update the algolia_instant_search.js
file
Rename the collection page flag variable
Replace the following line:
1
2
3
var collectionFacetConstraint =
!!algolia.is_collection_results_page &&
!!algolia.config.instant_search_enabled_on_collection;
With the following snippet:
1
2
3
var collectionPage =
!!algolia.is_collection_results_page &&
!!algolia.config.instant_search_enabled_on_collection;
Store the current collection’s ID in a variable
The current collection’s ID is now stored in a algolia.current_collection_id
variable. We must expose all necessary variables to properly filter products and activate Query Rules.
After this line:
1
2
3
4
5
6
if (
(!algolia.full_results && !collectionPage) ||
!algolia.config.instant_search_enabled
) {
return;
}
Add the following snippet:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var collectionFacetFilter = null;
var collectionRulesContextValue = null;
if (collectionPage) {
var matches = window.location.pathname.match(/\/collections\/([^/]+)/i);
const handle = !!matches && matches.length === 2 ? matches[1] : null;
collectionFacetFilter = algolia.config.collection_id_indexing
? algolia.current_collection_id
? 'collection_ids:"' + algolia.current_collection_id + '"'
: null
: 'collections:"' + handle + '"';
collectionRulesContextValue = algolia.config.collection_id_query_rules
? algolia.current_collection_id
: handle;
}
Update the CSS Selector logic
Replace the following lines (around line 24):
1
2
3
4
5
6
algolia.config.results_selector += ", .algolia-shopify-instantsearch";
var $hiding = $(
"<style>" +
algolia.config.results_selector +
" { visibility: hidden }</style>"
);
With the following snippet:
1
2
3
4
5
6
7
8
9
10
11
var results_selector = collectionPage
? algolia.config.collection_css_selector
: algolia.config.results_selector;
var activeSortOrders =
collectionPage && algolia.collectionSortOrders
? algolia.collectionSortOrders
: algolia.sortOrders;
results_selector += ", .algolia-shopify-instantsearch";
var $hiding = $(
"<style>" + results_selector + " { visibility: hidden }</style>"
);
Update the Sort Orders logic
Replace the occurrences of algolia.sortOrders
with activeSortOrders
at the following lines:
- around line 66:
sortOrders: algolia.sortOrders,
- around line 121:
multipleSortOrders: algolia.sortOrders.length > 1
- around line 201:
if (algolia.sortOrders.length > 1) {
Update the Facets logic
Replace the following lines (around line 33):
1
2
3
4
5
6
7
facets: {
hidden: algolia.hiddenFacets,
shown: algolia.shownFacets,
list: algolia.facets,
widgets: algolia.facetsWidgets
},
hitsPerPage: algolia.config.products_full_results_hits_per_page,
With the following:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
facets: {
hidden:
collectionPage && algolia.collectionHiddenFacets
? algolia.collectionHiddenFacets
: algolia.hiddenFacets,
shown:
collectionPage && algolia.collectionShownFacets
? algolia.collectionShownFacets
: algolia.shownFacets,
list:
collectionPage && algolia.collectionFacets
? algolia.collectionFacets
: algolia.facets,
widgets:
collectionPage && algolia.collectionFacetsWidgets
? algolia.collectionFacetsWidgets
: algolia.facetsWidgets
},
hitsPerPage:
collectionPage && algolia.config.collections_full_results_hits_per_page
? algolia.config.collections_full_results_hits_per_page
: algolia.config.products_full_results_hits_per_page,
Update products filtering logic
Look for the for the following line:
1
2
3
4
5
6
if (!!collectionFacetConstraint && !!collectionFacetValue) {
helper.setQueryParameter(
'filters',
'collections:"' + collectionFacetValue + '"'
);
}
And replace it by the following snippet:
1
2
3
if (!!collectionFacetFilter) {
helper.setQueryParameter('filters', collectionFacetFilter);
}
Update Query Rules activation logic
Look for for the following lines:
1
2
3
4
// if we are on a collection page, `collectionFacetValue` is defined
if (!!collectionFacetValue) {
helper.setQueryParameter('ruleContexts', [ collectionFacetValue ]);
}
And replace them with the following snippet:
1
2
3
4
// if we are on a collection page, `collectionRulesContextValue` is defined
if (!!collectionRulesContextValue) {
helper.setQueryParameter('ruleContexts', [collectionRulesContextValue.toString()]);
}
Your customizations are now migrated.
Migrate a custom front-end search UI implementation
Your shop front-end search UI is built without using the provided widgets.
When browsing a collection page, the front-end search implementation needs the current collection ID to filter products and activate Query Rules. To do so, we need to communicate the value of this current collection’s ID to the JavaScript files that’s responsible of the search implementation.
1. Create the algolia_current_collection_id.liquid
file
Current collection information is only accessible from Liquid files, which are evaluated by the Shopify back end before rendering the page.
For this reason we need to create the algolia_current_collection_id.liquid
snippet file.
1. Open the theme code editor.
2. Create a new snippet file named algolia_current_collection_id.liquid
3. Add the following content and save the file:
1
2
3
{
"currentCollectionID": {{collection.id}}
}
4. Open the layout/theme.liquid
file.
5. Add the following line before the template_algolia_money_format
script tag:
1
<script type="text/template" id="template_algolia_current_collection_id">{% include 'algolia_current_collection_id' %}</script>
6. Save changes to the layout/theme.liquid
file.
2. Update your custom front-end implementation code
First, we need to store the current collection’s ID in a JavaScript variable.
Make sure to add the following snippet to the JavaScript file that contains the InstantSearch logic:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var collectionFacetFilter = null;
var collectionRulesContextValue = null;
if (collectionPage) {
const current_collection_id_string = algolia
.getTemplate('current_collection_id')
.replace(/^\s+|\s+$/g, '');
let current_collection_id = null;
if (!!current_collection_id_string) {
const current_collection_id_object = JSON.parse(
current_collection_id_string
);
current_collection_id = current_collection_id_object.currentCollectionID;
}
collectionFacetFilter = current_collection_id
? 'collection_ids:"' + current_collection_id + '"'
: null;
collectionRulesContextValue = current_collection_id;
}
The above snippet exposes all necessary variables to do proper products filtering and Query Rules activation.
Update products filtering logic
On Collection pages, InstantSearch should automatically filter on products that belongs to the given collection.
Your implementation should contain some logic to filter on a collections
attribute.
You should update this logic to filter on the collection_ids
property.
You can now use the collectionFacetFilter
variable which contains the proper filter value (e.g., collection_ids:132342342
).
The collectionFacetFilter
variable can be null
if the script is loaded on a collection page that does not exist, or a different type of page (e.g., a search results page).
Update Query Rules activation logic
If your front-end search implementation contains merchandising logic using Algolia Query Rules, you must change the ruleContexts
sent by InstantSearch to Algolia.
1. Look for for the line which manipulates ruleContexts
.
You should update the logic to use the collectionRulesContextValue
variable, which contains the proper value to use, as follows:
1
2
3
4
// if we are on a collection page, `collectionRulesContextValue` is defined
if (!!collectionRulesContextValue) {
helper.setQueryParameter('ruleContexts', [collectionRulesContextValue.toString()]);
}
To enable merchandising on your front-end search implementation, add the following snippet into the part that handles search parameters (searchFunction
):
1
2
3
4
// if we are on a collection page, `collectionRulesContextValue` is defined
if (!!collectionRulesContextValue) {
helper.setQueryParameter('ruleContexts', [collectionRulesContextValue.toString()]);
}
The collectionRulesContextValue
variable can be null
if the script is loaded on a collection page that does not exist, or a different type of page (e.g., a search results page).
Your front-end search implementation is now migrated.