Skip to main content

ArtinTech Solution

Shopify FAQ page with a live search box filtering questions on desktop and mobile

Kestrel’s FAQ page had grown to the point where shoppers scrolled past the answer they were looking for. The merchant pointed us to a competitor’s help page with a search box in the header and asked for the same: type a word, see only the questions that match.

This is the story of that Shopify FAQ search: the snippet, the bug that made the first version find nothing on the live store, and the fix that turned out to be a lesson about inline scripts in Shopify themes.

About this case study: it is a composite based on real Shopify project work. The brand name and some details have been changed. The code, the bug and the fix are exactly as they happened.

Shopify FAQ page with a live search box filtering questions on desktop and mobile
The FAQ page filtering as the shopper types. (Illustration, brand anonymised.)

Why not use Shopify’s own search?

Shopify’s storefront search covers products, collections, pages and blog articles. Text that a merchant types into theme section blocks, which is where most FAQ sections keep their questions, is not part of that index. A shopper searching the store for “retour” finds products, not the answer about returns.

The FAQ answers are already in the page’s HTML, though. Filtering them in the browser needs no request, no app and no index. Results appear while the shopper is still typing.

Version one: a snippet and one render line

The merchant edits the theme in the code editor, so we kept the change as small as possible: one new snippet with the markup, styles and script, and one line in the FAQ section to render it.

{%- render 'faq-search', section: section -%}
<div class="faqs ...">  <!-- the theme's existing FAQ markup -->

The script is a small custom element. On every input it does four things:

  • Normalises the text: lower case and without accents, so “e” also finds “é”.
  • Splits the query into words and keeps a question only if it contains all of them, in the title or in the answer.
  • Hides a whole category, heading included, when none of its questions match.
  • Shows a “no questions found” message with a nudge to contact support when nothing matches at all.

We tested it against a copy of the FAQ markup in a headless browser. Every query returned the right questions. We sent it over.

The screenshot

The reply came with a screenshot. The merchant had pasted a full sentence from one of the answers into the search box. The page showed “no questions found”, and every single question was still visible underneath it. Nothing was hidden, and nothing was found.

Both symptoms pointed to the same thing: the script believed the page had no questions. We opened the live page and asked the element directly. The page had two FAQ groups with seven questions. The search element’s own list of groups was empty.

The cause: an inline script that runs too early

The snippet renders above the questions, and its <script> tag sits inside the snippet. The browser parses the HTML from top to bottom. When it reaches the script, it defines the custom element, and because the <faq-search> element is already in the document, its connectedCallback runs immediately. At that moment, the parser has not yet reached the questions below it.

Our first version looked up the FAQ groups in connectedCallback and stored them. It stored an empty list, once, forever. Our test had passed because the test page happened to put the script after the questions.

Code diff in the Shopify theme editor replacing a cached list with a getter in the FAQ search snippet
The fix: look the groups up when searching, not when the element connects.

The fix is one getter. Instead of storing the groups when the element connects, the script looks them up each time the shopper types:

get groups() {
  return Array.from(this.closest('.section').querySelectorAll('.faq'));
}

By the time anyone types, the page is fully parsed. The lookup costs next to nothing for a few dozen questions, and it also keeps working when the theme editor re-renders the section while the merchant edits it, which a cached list would not.

A second, quieter bug

While moving the code into its final snippet, we found one more problem. The CSS rule that hid filtered items was written as .faq [data-faq-hidden], with a space. That hides questions inside a group, but not the group itself, so a category heading could stay visible with nothing under it. The rule now covers both: .faq [data-faq-hidden], .faq[data-faq-hidden].

Shopify FAQ page search results for the word retour with one answer opened
After the fix: “retour” shows only the three return questions, and other categories disappear.

Testing it where it lives

This time we tested on the live FAQ page itself, by running the corrected logic in the browser against the real markup, before asking the merchant to change anything.

“levertijd”Only the delivery-time question
“garantie”The warranty questions from two different categories
“€70 gratis”Only the shipping-costs question, matched on its answer
“retour”Only the returns question, the other category hidden
“xyz”Nothing, with the “no questions found” message

What we took away from it

  • Test in the order the real page uses. A custom element defined in an inline script sees only the HTML above it.
  • Do not cache DOM lookups in connectedCallback unless you know the content already exists. A getter is simpler than waiting for DOMContentLoaded and survives theme-editor re-renders.
  • When a merchant sends a screenshot, read both symptoms together. “No results” plus “nothing hidden” narrowed the bug down before we opened the console.

The search went on to become part of a full help-centre page; we wrote about that in our Shopify FAQ page template case study. For the product-page offer we built for the same store, see the buy one get one free picker. If your FAQ or any other part of your theme needs work like this, see our Shopify theme development service.

Frequently asked questions

Does a FAQ search bar hurt SEO?

No. All questions and answers stay in the HTML. They are only hidden in the shopper’s browser after the shopper types a query.

Do I need an app to add search to a Shopify FAQ page?

No. Because the questions are already on the page, a small script can filter them. That is faster than an app and adds no monthly cost.

Will it work with a large FAQ?

Yes. Filtering a few hundred questions in the browser is instant. Beyond that, splitting the FAQ into several pages is usually better for the shopper anyway.

Does it search the answers as well as the questions?

Yes. Each question is matched on its title and its answer text, without accents, and all words in the query must appear.

Share this article