No Results UX and Query Handling
Design helpful no-results experiences with suggestions, spell-checking, popular searches, and graceful degradation.
When search returns nothing, it’s an opportunity to help customers rather than leave them at a dead end. A well-designed no-results experience guides users toward finding what they need.
Basic No Results State
{# snippets/search-no-results.liquid #}
<div class="search-no-results"> <div class="search-no-results__icon"> {% render 'icon-search' %} </div>
<h2 class="search-no-results__title"> No results found for "{{ terms }}" </h2>
<p class="search-no-results__message"> We couldn't find any matches. Try checking your spelling or using different keywords. </p></div>Helpful Suggestions
Provide actionable next steps:
<div class="search-no-results"> <h2 class="search-no-results__title"> No results for "{{ terms }}" </h2>
<div class="search-no-results__suggestions"> <h3>Suggestions:</h3> <ul> <li>Check your spelling</li> <li>Try more general keywords</li> <li>Try fewer keywords</li> </ul> </div>
<div class="search-no-results__actions"> <a href="{{ routes.all_products_collection_url }}" class="button button--primary"> Browse All Products </a> <a href="{{ routes.collections_url }}" class="button button--secondary"> View Collections </a> </div></div>Popular Searches
Show what others are searching for:
{# Popular searches (could be hardcoded or from metafields) #}{%- assign popular_searches = 'shirts,dresses,accessories,sale' | split: ',' -%}
<div class="search-no-results__popular"> <h3>Popular Searches</h3> <div class="search-no-results__tags"> {%- for search in popular_searches -%} <a href="{{ routes.search_url }}?q={{ search | url_encode }}" class="search-no-results__tag" > {{ search | capitalize }} </a> {%- endfor -%} </div></div>Trending Products
Show popular products as alternatives:
{%- assign trending = collections['bestsellers'].products | slice: 0, 4 -%}
{%- if trending.size > 0 -%} <div class="search-no-results__products"> <h3>Trending Right Now</h3> <ul class="product-grid product-grid--4"> {%- for product in trending -%} <li> {% render 'product-card', product: product %} </li> {%- endfor -%} </ul> </div>{%- endif -%}Complete No Results Component
{# snippets/search-no-results.liquid #}
<div class="search-no-results"> <div class="search-no-results__content"> <div class="search-no-results__icon"> {% render 'icon-search-x' %} </div>
<h2 class="search-no-results__title"> No results found </h2>
<p class="search-no-results__query"> We couldn't find anything for "<strong>{{ terms }}</strong>" </p>
<div class="search-no-results__tips"> <p>Try:</p> <ul> <li>Using more general terms</li> <li>Checking for typos</li> <li>Searching for a product type instead of a specific name</li> </ul> </div> </div>
{# Popular searches #} {%- assign popular = section.settings.popular_searches | split: ',' -%} {%- if popular.size > 0 -%} <div class="search-no-results__section"> <h3 class="search-no-results__section-title">Popular Searches</h3> <div class="search-no-results__tags"> {%- for term in popular -%} {%- assign term_trimmed = term | strip -%} <a href="{{ routes.search_url }}?q={{ term_trimmed | url_encode }}" class="tag"> {{ term_trimmed }} </a> {%- endfor -%} </div> </div> {%- endif -%}
{# Featured collections #} {%- if section.settings.show_collections -%} <div class="search-no-results__section"> <h3 class="search-no-results__section-title">Browse by Category</h3> <div class="search-no-results__collections"> {%- for collection in collections limit: 6 -%} {%- if collection.products_count > 0 -%} <a href="{{ collection.url }}" class="search-no-results__collection"> {%- if collection.image -%} <img src="{{ collection.image | image_url: width: 150 }}" alt="{{ collection.title }}" loading="lazy" > {%- endif -%} <span>{{ collection.title }}</span> </a> {%- endif -%} {%- endfor -%} </div> </div> {%- endif -%}
{# Suggested products #} {%- if section.settings.suggested_collection != blank -%} {%- assign suggested = section.settings.suggested_collection.products | slice: 0, 4 -%} {%- if suggested.size > 0 -%} <div class="search-no-results__section"> <h3 class="search-no-results__section-title">You Might Like</h3> <ul class="product-grid product-grid--4"> {%- for product in suggested -%} <li>{% render 'product-card', product: product %}</li> {%- endfor -%} </ul> </div> {%- endif -%} {%- endif -%}
{# CTA #} <div class="search-no-results__cta"> <a href="{{ routes.all_products_collection_url }}" class="button button--primary"> View All Products </a> </div></div>No Results Styles
.search-no-results { text-align: center; padding: var(--spacing-2xl) var(--spacing-md); max-width: 800px; margin: 0 auto;}
.search-no-results__content { margin-bottom: var(--spacing-2xl);}
.search-no-results__icon { display: flex; align-items: center; justify-content: center; width: 80px; height: 80px; margin: 0 auto var(--spacing-lg); background: var(--color-background-secondary); border-radius: 50%;}
.search-no-results__icon svg { width: 40px; height: 40px; color: var(--color-text-light);}
.search-no-results__title { font-size: 1.5rem; margin: 0 0 var(--spacing-sm);}
.search-no-results__query { color: var(--color-text-light); margin: 0 0 var(--spacing-lg);}
.search-no-results__tips { text-align: left; max-width: 400px; margin: 0 auto; padding: var(--spacing-md); background: var(--color-background-secondary); border-radius: var(--border-radius);}
.search-no-results__tips ul { margin: var(--spacing-xs) 0 0; padding-left: var(--spacing-lg);}
.search-no-results__section { margin-top: var(--spacing-xl); padding-top: var(--spacing-xl); border-top: 1px solid var(--color-border);}
.search-no-results__section-title { font-size: 1rem; margin: 0 0 var(--spacing-md);}
.search-no-results__tags { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--spacing-xs);}
.tag { display: inline-block; padding: var(--spacing-xs) var(--spacing-sm); font-size: 0.875rem; background: var(--color-background-secondary); border-radius: var(--border-radius); text-decoration: none; color: inherit; transition: background-color 0.2s;}
.tag:hover { background: var(--color-border);}
.search-no-results__collections { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--spacing-md);}
.search-no-results__collection { display: flex; flex-direction: column; align-items: center; gap: var(--spacing-xs); text-decoration: none; color: inherit;}
.search-no-results__collection img { width: 80px; height: 80px; object-fit: cover; border-radius: var(--border-radius);}
.search-no-results__cta { margin-top: var(--spacing-xl);}Query Normalization
Clean up search queries before processing:
function normalizeQuery(query) { return query .trim() .toLowerCase() .replace(/\s+/g, ' '); // Collapse multiple spaces}Common Misspellings
Handle known misspellings with redirects or suggestions:
{%- liquid assign query_lower = search.terms | downcase
# Common misspellings mapping case query_lower when 'tshirt', 't shirt', 'teeshirt' assign suggested_query = 't-shirt' when 'jeans', 'jeens', 'genes' assign suggested_query = 'jeans' when 'accesories', 'acessories' assign suggested_query = 'accessories' endcase-%}
{%- if suggested_query -%} <p class="search-suggestion"> Did you mean <a href="{{ routes.search_url }}?q={{ suggested_query | url_encode }}"> "{{ suggested_query }}" </a>? </p>{%- endif -%}Empty Query Handling
When no query is entered:
{%- if search.terms == blank -%} <div class="search-prompt"> <p>Enter a search term to find products, articles, and pages.</p>
<div class="search-prompt__suggestions"> <p>Try searching for:</p> <div class="search-prompt__tags"> <a href="{{ routes.search_url }}?q=new+arrivals" class="tag">New Arrivals</a> <a href="{{ routes.search_url }}?q=sale" class="tag">Sale</a> <a href="{{ routes.search_url }}?q=bestsellers" class="tag">Best Sellers</a> </div> </div> </div>{%- endif -%}Predictive Search No Results
For the live search dropdown:
{# In predictive search section #}{%- if predictive_search.performed and has_results == false -%} <div class="predictive-search__no-results"> <p>No results for "{{ predictive_search.terms }}"</p> <a href="{{ routes.search_url }}?q={{ predictive_search.terms | url_encode }}"> Search all products </a> </div>{%- endif -%}Keep predictive no-results minimal since users are still typing.
Schema Settings
{% schema %}{ "name": "Search Results", "settings": [ { "type": "header", "content": "No results" }, { "type": "text", "id": "popular_searches", "label": "Popular searches", "info": "Comma-separated list", "default": "shirts, dresses, accessories, sale" }, { "type": "checkbox", "id": "show_collections", "label": "Show browse by category", "default": true }, { "type": "collection", "id": "suggested_collection", "label": "Suggested products collection" } ]}{% endschema %}Practice Exercise
Create a no-results experience that:
- Shows a friendly message with the search term
- Lists helpful tips
- Displays popular search terms as links
- Shows trending products
- Provides a “Browse All” button
Test with:
- Various failed searches
- Misspelled terms
- Empty search queries
Key Takeaways
- Never leave a dead end: Always provide next steps
- Show the search term: Confirm what was searched
- Offer tips: Help users refine their search
- Popular searches: Guide users to common queries
- Show products: Trending items keep them engaged
- Collection links: Alternative browsing paths
- Keep predictive minimal: Users are still typing
- Handle empty queries: Prompt with suggestions
What’s Next?
The final search lesson covers Performance Considerations for Search for optimizing search speed and efficiency.
Finished this lesson?
Mark it complete to track your progress.
Discussion
Loading comments...