Integrations / Shopify

From December 31, 2023, Algolia’s Search and Discovery application can’t modify the coding of Shopify themes. For more information, refer to Shopify’s Asset API documentation. As an alternative, Algolia offers Shopify’s App Embed and App Blocks features for Autocomplete and InstantSearch interfaces. For more information, refer to the Quick start and Shopify Algolia configuration documentation.

How hooks works

Adjust the logic of the Autocomplete and InstantSearch integration by registering a custom method in your JavaScript file.

The extension provides hooks to help you add or change parameters for the implementation. The algoliaShopify window variable is an object that handles the setting and firing of events in the Autocomplete and InstantSearch frontend implementation. To view the available events, visit your Shopify store and type algoliaShopify.hooks.allowedHooks into your browser’s API console:

An example of allowed hooks

Customizing

Five kinds of hooks are available. Each hook requires a different return value.

  • Options expects an object
  • Templates expects a Tagged Template Literal wrapped around html.
    • example: html`<h1>Algolia</h1>`
  • Array expects an array of objects or strings
  • String expects a string
  • Number expects a number
  • Action expects a function

Autocomplete hooks

  • beforeAutocompleteOptions(options)
  • beforeAutocompleteFiltersString(defaultFilter)
  • beforeAutocompleteRedirectUrlOptions(options)
    • Used to modify the default parameter options of the createRedirectUrlPlugin
    • the hook must return an options value
  • beforeAutocompleteMainTemplate(defaultTemplate, templateOptions, elements, displaySuggestions)
    • Used to modify the HTML template that renders the Autocomplete panel.
    • Renders an Autocomplete multi-panel layout
    • The element object contains the following properties:
      • querySuggestionsPlugin
      • collections
      • articles
      • pages
      • redirectUrlPlugin
      • products
  • beforeAutocompleteMainProductsTemplate(defaultTemplate, templateOptions, elements)
    • Renders the Autocomplete menu’s product section
  • beforeAutocompleteNoResultsTemplate(defaultTemplate, templateOptions)
    • Renders a no results section when there are no hits
  • beforeAutocompleteHeaderTemplate(defaultTemplate, templateOptions, resource)
    • Renders a header section at the top of the Autocomplete panel
  • beforeAutocompleteFooterTemplate(defaultTemplate, templateOptions)
    • The ‘Show See All products’ checkbox in the Shopify Algolia Dashboard must be enabled
    • Renders a footer section at the bottom of the Autocomplete panel
  • beforeAutocompleteProductTemplate(defaultTemplate, templateOptions, distinct, itemLink)
    • Renders the Autocomplete menu’s product section
  • beforeAutocompleteArticlesTemplate(defaultTemplate, templateOptions, itemLink)
    • Renders the Autocomplete menu’s articles section
  • beforeAutocompleteCollectionsTemplate(defaultTemplate, templateOptions, itemLink)
    • Renders the Autocomplete menu’s collections section
  • beforeAutocompletePagesTemplate(defaultTemplate, templateOptions, itemLink)
    • Renders the Autocomplete menu’s pages section
  • beforeAutocompleteSuggestionsTemplate(defaultTemplate, templateOptions)
    • Renders the Autocomplete menu’s suggestions section
  • afterAutocompleteProductClickAction(undefined, line_item)
    • Used to execute a function after a product is clicked

Examples of Autocomplete hooks

Example of beforeAutocompleteOptions(options) hook:

1
2
3
4
5
6
7
8
9
// Modify default `options`
document.addEventListener('algolia.hooks.initialize', function() {
  algoliaShopify.hooks.registerHook('beforeAutocompleteOptions', function(options) {
    // Modify default options, then return them
    options.placeholder = "Search Our Products";
    return options;
  });
});

Example of beforeAutocompleteFiltersString(defaultFilter) hook:

1
2
3
4
5
6
7
// Omit `_defaultFilter` and return a custom filter
document.addEventListener('algolia.hooks.initialize', function() {
  algoliaShopify.hooks.registerHook('beforeAutocompleteFiltersString', function(_defaultFilter) {
    // Modify or replace the default string, then return a string
    return 'price > 17';
  });
});

beforeAutocompleteMainTemplate(defaultTemplate, templateOptions, elements, displaySuggestions)

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
document.addEventListener('algolia.hooks.initialize', function() {
  algoliaShopify.hooks.registerHook('beforeAutocompleteMainTemplate', function(_defaultTemplate, templateOptions, elements, displaySuggestions) {
    const { html } = templateOptions;
    return html`
      <div class="aa-PanelLayout aa-Panel--scrollable">
        <div class="aa-PanelSections">
          <div class="aa-PanelSection--left">
            ${displaySuggestions &&
              html`
                <div class="aa-SourceHeader">
                  <span class="aa-SourceHeaderTitle"
                    >${algoliaShopify.translations.suggestions}</span
                  >
                  <div class="aa-SourceHeaderLine" />
                </div>
                ${elements.querySuggestionsPlugin}
              `}
            ${elements.collections} ${elements.articles} ${elements.pages}
            ${elements.redirectUrlPlugin}
          </div>
          <div class="aa-PanelSection--right">
            ${elements.products}
          </div>
        </div>
      </div>
    `;
  });
});

beforeAutocompleteMainProductsTemplate(defaultTemplate, templateOptions, elements)

1
2
3
4
5
6
7
8
9
10
11
12
document.addEventListener('algolia.hooks.initialize', function() {
  algoliaShopify.hooks.registerHook('beforeAutocompleteMainProductsTemplate', function(_defaultTemplate, templateOptions, elements) {
    const { html } = templateOptions;
    return html`
      <div class="aa-PanelLayout aa-Panel--scrollable">
        <div class="aa-PanelSection">
          ${elements.products}
        </div>
      </div>
    `;
  });
});

beforeAutocompleteNoResultsTemplate(defaultTemplate, templateOptions)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
document.addEventListener('algolia.hooks.initialize', function() {
  algoliaShopify.hooks.registerHook('beforeAutocompleteNoResultsTemplate', function(_defaultTemplate, templateOptions) {
    const { html, state } = templateOptions;
    return html`
      <div class="aa-PanelLayout aa-Panel--scrollable">
        <p class="aa-NoResultsHeader">
          ${algoliaShopify.translation_helpers.no_result_for(state.query)}
        </p>
        <a class="aa-NoResultsLink" href="${window.Shopify.routes.root}search?q=">
          ${algoliaShopify.translations.allProducts}
        </a>
      </div>
    `;
  });
});

####beforeAutocompleteHeaderTemplate(defaultTemplate, templateOptions, resource)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
document.addEventListener('algolia.hooks.initialize', function() {
  algoliaShopify.hooks.registerHook('beforeAutocompleteHeaderTemplate', function(_defaultTemplate, templateOptions, resource) {
    const { html, state } = templateOptions;
    return html`
      <div class="aa-SourceHeader">
        <span class="aa-SourceHeaderTitle">
          ${algoliaShopify.translation_helpers.render_title(
            resource,
            state.query
          )}
        </span>
        <div class="aa-SourceHeaderLine" />
      </div>
    `;
  });
});

beforeAutocompleteFooterTemplate(defaultTemplate, templateOptions)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
document.addEventListener('algolia.hooks.initialize', function() {
  algoliaShopify.hooks.registerHook('beforeAutocompleteFooterTemplate', function(_defaultTemplate, templateOptions) {
    const { html, state } = templateOptions;
    return html`
      <div class="aa-footer">
        <a
          class="aa-SeeAllBtn"
          href="${window.Shopify.routes.root}search?q=${state.query}"
        >
          ${algoliaShopify.translations.allProducts}
          (${algoliaShopify.helpers.formatNumber(state.context.nbProducts)})
        </a>
      </div>
    `;
  });
});
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
const handleItemClick = (e, line_item) => {
  const afterClick = new Event("algoliaShopify.autocomplete.hitClickAction");
  document.dispatchEvent(afterClick);

  if (algoliaShopify.config.analytics_enabled) {
    const clickData = {
      index: line_item.__autocomplete_indexName,
      eventName: "Added to cart",
      queryID: line_item.__autocomplete_queryID,
      objectIDs: [line_item.objectID],
    };
    algoliaShopify.saveForConversionTracking(clickData);
  }

  const customerCustomAction = algoliaShopify.hooks.triggerHooks(
    "afterAutocompleteProductClickAction",
    undefined,
    line_item
  );

  if (typeof customerCustomAction === "function") {
    customerCustomAction();
  }
};

document.addEventListener("algolia.hooks.initialize", function () {
  algoliaShopify.hooks.registerHook(
    "beforeAutocompleteProductTemplate",
    function (_defaultTemplate, templateOptions, distinct, itemLink) {
      // Modify default options, then return them
      const { html, item, components } = templateOptions;
      return html`
    <a
      href="${itemLink}"
      class="aa-ItemLink aa-ProductItem"
      onClick="${(event) => handleItemClick(event, item)}"
    >
      <div class="aa-ItemContent">
        <div class="aa-ItemPicture aa-ItemPicture--loaded">
          <img
            src="${algoliaShopify.helpers.compactImage(item)}"
            alt="${item.title}"
          />
        </div>
        <div class="aa-ItemContentBody">
          <div class="aa-ItemContentBrand">
            ${
              item.product_type &&
              components.Highlight({ hit: item, attribute: "product_type" })
            }
           removing vendor
          </div>
          <div class="aa-ItemContentTitleWrapper">
            <div class="aa-ItemContentTitle">
              ${components.Highlight({ hit: item, attribute: "title" })}
              <span class="algolia-variant">
                ${algoliaShopify.helpers.variantTitleAddition(item, distinct)}
              </span>
            </div>
          </div>
          <div class="aa-ItemContentPrice">
            <div class="aa-ItemContentPriceCurrent">
              ${algoliaShopify.helpers.displayPrice(item, distinct)}
            </div>
          </div>
        </div>
      </div>
    </a>
  `;
    }
  );
});
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
document.addEventListener('algolia.hooks.initialize', function() {
  algoliaShopify.hooks.registerHook('beforeAutocompleteArticlesTemplate', function(_defaultTemplate, templateOptions, itemLink) {
    const { html, item, components } = templateOptions;
    return html`
      <a href="${itemLink}" class="aa-ItemLink">
        <div class="aa-ItemWrapper">
          <div class="aa-ItemContent">
            <div class="aa-ItemIcon aa-ItemIcon--noBorder">
              <svg viewBox="0 0 24 24" fill="none" stroke="currentColor">
                <path
                  stroke-linecap="round"
                  stroke-linejoin="round"
                  stroke-width="2"
                  d="M7 7h.01M7 3h5c.512 0 1.024.195 1.414.586l7 7a2 2 0 010 2.828l-7 7a2 2 0 01-2.828 0l-7-7A1.994 1.994 0 013 12V7a4 4 0 014-4z"
                />
              </svg>
            </div>
            <div class="aa-ItemContentBody">
              <div class="aa-ItemContentTitle">
                ${components.Highlight({ hit: item, attribute: 'title' })}
              </div>
            </div>
          </div>
        </div>
      </a>
    `;
  });
});
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
document.addEventListener('algolia.hooks.initialize', function() {
  algoliaShopify.hooks.registerHook('beforeAutocompleteCollectionsTemplate', function(_defaultTemplate, templateOptions, itemLink) {
    const { html, item, components } = templateOptions;
    return  html`
      <a href="${itemLink}" class="aa-ItemLink">
        <div class="aa-ItemWrapper">
          <div class="aa-ItemContent">
            <div class="aa-ItemIcon aa-ItemIcon--noBorder">
              <svg viewBox="0 0 24 24" fill="none" stroke="currentColor">
                <path
                  stroke-linecap="round"
                  stroke-linejoin="round"
                  stroke-width="2"
                  d="M4 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2V6zM14 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2V6zM4 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2v-2zM14 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2v-2z"
                />
              </svg>
            </div>
            <div class="aa-ItemContentBody">
              <div class="aa-ItemContentTitle">
                ${components.Highlight({ hit: item, attribute: 'title' })}
              </div>
            </div>
          </div>
        </div>
      </a>
    `;
  });
});
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
document.addEventListener('algolia.hooks.initialize', function() {
  algoliaShopify.hooks.registerHook('beforeAutocompletePagesTemplate', function(_defaultTemplate, templateOptions, itemLink) {
    const { html, item, components } = templateOptions;
    return html`
      <a href="${itemLink}" class="aa-ItemLink aa-ProductItem">
        <div class="aa-ItemWrapper">
          <div class="aa-ItemContent">
            <div class="aa-ItemIcon aa-ItemIcon--noBorder">
              <svg viewBox="0 0 24 24" fill="none" stroke="currentColor">
                <path
                  stroke-linecap="round"
                  stroke-linejoin="round"
                  stroke-width="2"
                  d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
                />
              </svg>
            </div>
            <div class="aa-ItemContentBody">
              <div class="aa-ItemContentTitle">
                ${components.Highlight({ hit: item, attribute: 'title' })}
              </div>
            </div>
          </div>
        </div>
      </a>
    `;
  });
});

beforeAutocompleteSuggestionsTemplate(defaultTemplate, templateOptions)

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
document.addEventListener('algolia.hooks.initialize', function() {
  algoliaShopify.hooks.registerHook('beforeAutocompleteSuggestionsTemplate', function(_defaultTemplate, templateOptions) {
    const { html, state } = templateOptions;
    return html`
      <a
        class="aa-ItemLink aa-ItemWrapper"
        href="${window.Shopify.routes.root}search?q=${item.query}"
      >
        <div class="aa-ItemContent">
          <div class="aa-ItemIcon aa-ItemIcon--noBorder">
            <svg viewBox="0 0 24 24" fill="currentColor">
              <path d="M16.041 15.856c-0.034 0.026-0.067 0.055-0.099 0.087s-0.060 0.064-0.087 0.099c-1.258 1.213-2.969 1.958-4.855 1.958-1.933 0-3.682-0.782-4.95-2.050s-2.050-3.017-2.050-4.95 0.782-3.682 2.050-4.95 3.017-2.050 4.95-2.050 3.682 0.782 4.95 2.050 2.050 3.017 2.050 4.95c0 1.886-0.745 3.597-1.959 4.856zM21.707 20.293l-3.675-3.675c1.231-1.54 1.968-3.493 1.968-5.618 0-2.485-1.008-4.736-2.636-6.364s-3.879-2.636-6.364-2.636-4.736 1.008-6.364 2.636-2.636 3.879-2.636 6.364 1.008 4.736 2.636 6.364 3.879 2.636 6.364 2.636c2.125 0 4.078-0.737 5.618-1.968l3.675 3.675c0.391 0.391 1.024 0.391 1.414 0s0.391-1.024 0-1.414z" />
            </svg>
          </div>
          <div class="aa-ItemContentBody">
            <div class="aa-ItemContentTitle">
              ${components.Highlight({ hit: item, attribute: 'query' })}
            </div>
          </div>
        </div>
        <div class="aa-ItemActions">
          <button
            class="aa-ItemActionButton"
            title={"Fill query with ${item.query}"}
          >
            <svg viewBox="0 0 24 24" fill="currentColor">
              <path d="M8 17v-7.586l8.293 8.293c0.391 0.391 1.024 0.391 1.414 0s0.391-1.024 0-1.414l-8.293-8.293h7.586c0.552 0 1-0.448 1-1s-0.448-1-1-1h-10c-0.552 0-1 0.448-1 1v10c0 0.552 0.448 1 1 1s1-0.448 1-1z" />
            </svg>
          </button>
        </div>
      </a>
    `;
  });
});

Example of beforeAutocompleteHeaderTemplate(defaultTemplate, templateOptions) hook:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
document.addEventListener('algolia.hooks.initialize', function() {
  algoliaShopify.hooks.registerHook('beforeAutocompleteHeaderTemplate', function(_defaultTemplate, templateOptions, resource) {
    // Modify default options, then return them
    const { html, state } = templateOptions;
    const { query } = state;
    return html`
      <div class="aa-SourceHeader">
        <span class="aa-SourceHeaderTitle">
          ${`Results for "${query}"`}
        </span>
        <div class="aa-SourceHeaderLine" />
      </div>
    `;
  });
});

InstantSearch hooks

  • beforeInstantSearchConfigurationOptions(options)
  • beforeInstantSearchOptions(options)
    • Contains colors, distinct, facets, hitsPerPage, selector, and sortOrders
  • beforeInstantSearchAllowParamsArray(allowParamsArray)
    • Preserves the URL parameters when navigating through the search results
  • beforeInstantSearchFiltersString(defaultFilter)
  • beforeInstantSearchMainTemplate(defaultTemplate, data, html)
    • Renders the main template container
  • beforeInstantSearchProductTemplate(defaultTemplate, hit, html, components)
    • Renders the product template
  • beforeInstantSearchNoResultTemplate(defaultTemplate, html)
    • Renders the no results template
  • beforeInstantSearchFacetItemTemplate(defaultTemplate, item, html)
    • Renders the facet items
  • beforeInstantSearchShowMoreTemplate(defaultTemplate, data, html)
  • beforeInstantSearchStatsTemplate(defaultTemplate, data, html)
  • beforeISTransformItems(transformedItems, items)
    • Used to modify items before they’re rendered
  • beforeISStartAddWidgetArray
    • Used to add a widget to the InstantSearch page
    • Please be aware not all widgets are available
    • Return an array of widgets to add
  • afterISStartRemoveDefaultWidget(defaultWidgets)
    • Default widget.$$widgetType: ais.sortBy, ais.searchBox, ais.stats, ais.hits, and ais.pagination
    • Return an array of widgets to remove
  • afterInstantSearchHitClickAction(_, hit)
    • Used to execute a function after a hit is clicked
  • beforeInstantSearchFacetLimitNumber(limit)
  • beforeISFacetSearchablePlaceholderString(placeHolder, facet)
  • beforeISFacetSearchableNoResultsString(noResults, facet)
  • beforeInstantSearchFacetHeaderString(facetTitle, facet)
    • Used to modify the facet header string
  • beforeInstantSearchFacetTransformItemsOptions(transformedItems, items)
  • beforeISearchInitSortOrdersArray(transformedSortOrders, sortOrder)
  • beforeISInitCollectionSortOrdersArray(transformedSortOrders, sortOrder)
    • Used to modify the default sort orders.

Examples of InstantSearch hooks

Example of beforeInstantSearchConfigurationOptions(options) hook:

1
2
3
4
5
6
7
8
9
// Modify default `options`
document.addEventListener('algolia.hooks.initialize', function() {
  algoliaShopify.hooks.registerHook('beforeInstantSearchConfigurationOptions', function(options) {
    // Modify default options, then return them
    options.numberLocale: 'fr';
    options.stalledSearchDelay: 500;
    return options;
  });
});

Example of beforeInstantSearchAllowParamsArray(allowParamsArray) hook:

1
2
3
4
5
6
7
8
// Modify default `allowParamsArray`
document.addEventListener('algolia.hooks.initialize', function() {
  algoliaShopify.hooks.registerHook('beforeInstantSearchAllowParamsArray', function(allowParamsArray) {
    // Modify default array, then return an array
    allowParamsArray.push('ref');
    return allowParamsArray;
  });
});

Example of beforeInstantSearchFiltersString(defaultFilter) hook:

1
2
3
4
5
6
7
8
9
10
11
12
// Modify default `defaultFilter` if it exists
document.addEventListener('algolia.hooks.initialize', function() {
  algoliaShopify.hooks.registerHook('beforeInstantSearchFiltersString', function(defaultFilter) {
    // Modify or replace the default string, then return a string
    if(defaultFilter) {
      return defaultFilter + ' AND price > 5'
    }
    else {
      return 'price > 5'
    }
  });
});

beforeInstantSearchMainTemplate(defaultTemplate, data, html)

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
document.addEventListener('algolia.hooks.initialize', function() {
  algoliaShopify.hooks.registerHook('beforeInstantSearchMainTemplate', function(_defaultTemplate, data, html) {
    return html`
      <div class="ais-page">
        <h1 class="ais-h2">${algoliaShopify.translations.searchTitle}</h1>
        <div class="ais-input">
          <div class="ais-search-box-container"></div>
          <div class="ais-input-button">
            <div class="ais-clear-input-icon"></div>
          </div>
        </div>
        <div class="ais-facets-button">
          Show filters
        </div>
        <div class="ais-facets">
          <div class="ais-clear-refinements-container"></div>
          <div class="ais-current-refined-values-container"></div>
          ${data.facets.map(
            facet =>
              html`
                <div
                  class="ais-facet-dropdown-wrapper ais-facet-${facet.type} ais-facet-${facet.escapedName}"
                >
                  <label
                    for="${facet.escapedName}"
                    class="ais-range-slider--header ais-facet--header ais-header"
                    >${facet.title}</label
                  >
                  <input
                    class="ais-dropdown-checkbox"
                    type="checkbox"
                    id="${facet.escapedName}"
                    name="dropdown"
                  />
                  <div
                    class="ais-facet-${facet.escapedName}-container ais-facet-dropdown-container"
                  ></div>
                </div>
              `
          )}
        </div>
        <div class="ais-block">
          <div class="ais-search-header">
            <div class="ais-stats-container"></div>
            <div class="ais-change-display">
              <span class="ais-change-display-block ais-change-display-selected"
                ><i class="fa fa-th-large"></i
              ></span>
              <span class="ais-change-display-list"
                ><i class="fa fa-th-list"></i
              ></span>
            </div>
            <div class="ais-sort">
              ${data.multipleSortOrders
                ? html`
                    ${algoliaShopify.translations.sortBy}
                    <span class="ais-sort-orders-container"></span>
                  `
                : html`
                    ${algoliaShopify.translations.sortBy}
                    ${algoliaShopify.translations.relevance}
                  `}
            </div>
          </div>
          <div class="ais-hits-container ais-results-as-block"></div>
        </div>
        <div class="ais-pagination-container"></div>
      </div>
    `;
  });
});

beforeInstantSearchProductTemplate(defaultTemplate, hit, html, components)

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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
document.addEventListener('algolia.hooks.initialize', function() {
  algoliaShopify.hooks.registerHook('beforeInstantSearchProductTemplate', function(_defaultTemplate, hit, html, components) {
    return html`
      <div
        class="ais-hit ais-product"
        data-algolia-index="${hit.index}"
        data-algolia-position="${hit.productPosition}"
        data-algolia-queryid="${hit.queryID}"
        data-algolia-objectid="${hit.objectID}"
        data-handle="${hit.handle}"
        data-variant-id="${hit.objectID}"
        data-distinct="${hit._distinct}"
        data-product-id="${hit.id}"
      >
        <img
          class="ais-hit--picture"
          src="${algoliaShopify.helpers.mediumImage(hit)}"
          alt="${hit.title} - ${hit.variant_title}"
        />

        <div class="ais-hit--details">
          <p class="ais-hit--title">
            <a
              data-algolia-index="${hit.index}"
              data-algolia-position="${hit.productPosition}"
              data-algolia-queryid="${hit.queryID}"
              data-algolia-objectid="${hit.objectID}"
              href="${algoliaShopify.helpers.instantsearchLink(hit)}"
              onclick="void(0)"
              title="${algoliaShopify.helpers.fullTitle(
                hit.title,
                hit._distinct,
                hit.variant_title
              )}"
            >
              ${components.Highlight({ attribute: 'title', hit })}
              ${algoliaShopify.helpers.variantTitleAddition(hit, hit._distinct)}
            </a>
          </p>
          <p
            class="ais-hit--subtitle"
            title="${hit.product_type}${algoliaShopify.translation_helpers.by(
              hit.vendor
            )}"
          >
            ${components.Highlight({ attribute: 'product_type', hit })}
            ${hit.vendor &&
              html`
                <span> ${algoliaShopify.translations.by} </span>
              `}
            ${hit.vendor && components.Highlight({ attribute: 'vendor', hit })}
          </p>
          <p class="ais-hit--price">
            <b>${algoliaShopify.helpers.displayPrice(hit, hit._distinct)}</b>
            ${!hit._distinct &&
              html`
                <span class="ais-hit--price-striked"
                  ><span
                    >${algoliaShopify.helpers.displayStrikedPrice(
                      hit.price,
                      hit.compare_at_price
                    )}</span
                  ></span
                >
              `}
            ${!hit._distinct &&
              html`
                <span class="ais-hit--price-discount"
                  >${algoliaShopify.helpers.displayDiscount(
                    hit.price,
                    hit.compare_at_price,
                    hit.price_ratio
                  )}</span
                >
              `}
          </p>
          <!-- Extra info examples - Remove the display: none to show them -->
          <p class="ais-hit--info" style="display: none">
            ${hit.sku &&
              html`
                <span class="algolia-sku"
                  >${components.Highlight({ attribute: 'sku', hit })}</span
                >
              `}
            ${hit.barcode &&
              html`
                <span class="algolia-barcode"
                  >${components.Highlight({ attribute: 'barcode', hit })}</span
                >
              `}
            ${hit.weight &&
              html`
                <span class="algolia-weight">${hit.weight}</span>
              `}
            ${!hit.taxable &&
              html`
                <span class="algolia-taxable"
                  >${algoliaShopify.translations.taxFree}</span
                >
              `}
          </p>
          <!-- Tags example - Remove the display: none to show them -->
          <p class="ais-hit--tags" style="display: none">
            ${hit?._highlightResult.tags?.map(
              tag =>
                html`
                  <span class="ais-hit--tag">${tag.value}</span>
                `
            )}
          </p>
          ${!hit._distinct &&
            html`
              <form
                id="algolia-add-to-cart-${hit.objectID}"
                style="display: none;"
                action="/cart/add"
                method="post"
                enctype="multipart/form-data"
              >
                <input type="hidden" name="id" value="${hit.objectID}" />
              </form>
              <p class="ais-hit--cart">
                ${hit.can_order
                  ? html`
                      <button
                        class="ais-hit--cart-button"
                        data-form-id="algolia-add-to-cart-${hit.objectID}"
                      >
                        ${algoliaShopify.translations.addToCart}
                      </button>
                    `
                  : html`
                      <button
                        class="ais-hit--cart-button ais-hit--cart-button__disabled"
                      >
                        ${algoliaShopify.translations.outOfStock}
                      </button>
                    `}
              </p>
            `}
        </div>
      </div>
    `;
  });
});

beforeInstantSearchNoResultTemplate(defaultTemplate, html)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
document.addEventListener('algolia.hooks.initialize', function() {
  algoliaShopify.hooks.registerHook('beforeInstantSearchNoResultTemplate', function(_defaultTemplate, html) {
    return html`
      <div class="ais-hit-empty">
        <div class="ais-hit-empty--title">
          ${algoliaShopify.translations.noResultFound}
        </div>
        <div class="ais-hit-empty--clears">
          ${algoliaShopify.translations.try} ${' '}
          <a class="ais-hit-empty--clear-filters ais-link">
            ${algoliaShopify.translations.clearFilters} ${' '}
          </a>
          ${algoliaShopify.translations.or} ${' '}
          <a class="ais-hit-empty--clear-input ais-link">
            ${algoliaShopify.translations.changeInput}
          </a>
        </div>
      </div>
    `;
  });
});

beforeInstantSearchFacetItemTemplate(defaultTemplate, item, html)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
document.addEventListener('algolia.hooks.initialize', function() {
  algoliaShopify.hooks.registerHook('beforeInstantSearchFacetItemTemplate', function(_defaultTemplate, item, html) {
    return html`
      <label class="${item.cssClasses.label}">
        ${item.type === 'disjunctive' &&
          (item.isRefined
            ? html`
                <input
                  type="checkbox"
                  class="${item.cssClasses.checkbox}"
                  checked
                />
              `
            : html`
                <input type="checkbox" class="${item.cssClasses.checkbox}" />
              `)}
        ${item.label}
        <span class="${item.cssClasses.count}">
          ${algoliaShopify.helpers.formatNumber(item.count)}
        </span>
      </label>
    `;
  });
});

beforeInstantSearchShowMoreTemplate(defaultTemplate, data, html)

1
2
3
4
5
6
7
8
9
10
11
document.addEventListener('algolia.hooks.initialize', function() {
  algoliaShopify.hooks.registerHook('beforeInstantSearchShowMoreTemplate', function(_defaultTemplate, data, html) {
    return html`
      <span
        >${data.isShowingMore
          ? algoliaShopify.translations.showLess
          : algoliaShopify.translations.showMore}</span
      >
    `;
  });
});

Example of beforeInstantSearchFacetLimitNumber(limit) hook:

1
2
3
4
5
6
7
// Modify default `limit`
document.addEventListener('algolia.hooks.initialize', function() {
  algoliaShopify.hooks.registerHook('beforeInstantSearchFacetLimitNumber', function(limit) {
    // Modify default limit, then return a number
    return 12;
  });
});

Example of afterISStartRemoveDefaultWidget(defaultWidgets) hook:

1
2
3
4
5
6
7
8
9
10
document.addEventListener('algolia.hooks.initialize', function() {
  algoliaShopify.hooks.registerHook('afterISStartRemoveDefaultWidget', function(defaultWidgets) {
    // Find and return the default pagination widget
    const defaultPaginationWidget = defaultWidgets.find(
      widget => widget.$$widgetType === 'ais.pagination'
    );

    return [defaultPaginationWidget];
  });
});

Example of beforeISStartAddWidgetArray() hook:

1
2
3
4
5
6
7
8
9
10
11
12
document.addEventListener('algolia.hooks.initialize', function() {
  algoliaShopify.hooks.registerHook('beforeISStartAddWidgetArray', function() {
    // Please be aware not all widgets are available
    const { searchBox } = window.algoliaShopify.externals.widgets;

    const searchBoxWidget = searchBox({
      container: '#search-box'
    });

    return [searchBoxWidget];
  });
});

Insights hook example

  • beforeAlgoliaAnalyticsOptions(options)
  • beforeAddToCartSelectorString(selector)
    • Used to modify the selector string for the add to cart button

Example of beforeAlgoliaAnalyticsOptions(options) hook:

1
2
3
4
5
6
7
8
// Modify default `options`
document.addEventListener('algolia.hooks.initialize', function() {
  algoliaShopify.hooks.registerHook('beforeAlgoliaAnalyticsOptions', function(options) {
    // Modify default options, then return them
    options.userToken = 'd41951d5-4d0a-4907-8c1f-e98f6360e44d'; // random UUID;
    return options;
  });
});

Example of beforeAddToCartSelectorString(selector) hook:

1
2
3
4
5
6
7
8
// Modify default `options`
document.addEventListener('algolia.hooks.initialize', function() {
  algoliaShopify.hooks.registerHook('beforeAddToCartSelectorString', function(_selector) {
    // The default selector is '[name="add"]'
    // Return a CSS selector
    return '#add-to-cart';
  });
});
Did you find this page helpful?