All things Shopify and commerce
Hello,
We have a lot of products that are no longer manufactured. We want to hide them from the search box. However, we want them to be indexed by Google. We just want to hide them in the store so that customers cannot find them in our website search. I spoke to Shopify support, there is only one way to do this, which is to use metafield seo.hidden. However, this method disables indexing by Google. This option is not suitable for us. We just want to prevent customers from finding certain products in our search box. Can anyone help to modify search functionalities or even offer custom solutions without risking any disruptions in other areas of our site? Maybe someone have efficient methods or already available options within the theme settings that could help achieve what we looking for regarding hiding products from searches while still allowing them to be indexed by Google.
Theme name: Enterprise
Solved! Go to the solution
This is an accepted solution.
@DeividasAL ,
Thank you for your patience while I revisited the issue. I’ve devised a complete solution that will effectively hide discontinued products from your internal search while maintaining their indexing on Google. Here’s the updated approach:
Custom Search Implementation
Create a New JavaScript File:
// Add this code to a new JavaScript file (e.g., custom-search.js)
const customSearchImplementation = {
init() {
this.searchForm = document.querySelector('form[action="/search"]');
this.searchInput = this.searchForm?.querySelector('input[type="search"]');
this.searchResultsContainer = document.querySelector('#search-results-container');
if (this.searchForm) {
this.bindEvents();
this.setupPredictiveSearch();
}
},
bindEvents() {
this.searchForm.addEventListener('submit', (e) => {
e.preventDefault();
this.performSearch();
});
},
async performSearch() {
const searchTerm = this.searchInput.value;
const response = await fetch(`/search/suggest.json?q=${encodeURIComponent(searchTerm)}&resources[type]=product`);
const data = await response.json();
// Filter out products with specific tag or metafield
const filteredResults = this.filterResults(data.resources.results);
this.renderResults(filteredResults);
},
filterResults(results) {
return results.products.filter(product => {
// Check for discontinued tag/metafield
return !product.tags.includes('discontinued') &&
!product.tags.includes('hide-from-search');
});
},
renderResults(results) {
if (!this.searchResultsContainer) return;
const resultsHTML = results.map(product => `
<div class="search-result-item">
<a href="${product.url}" class="search-result-link">
<img src="${product.featured_image.url}" alt="${product.title}" class="search-result-image">
<div class="search-result-details">
<h3>${product.title}</h3>
<p>${product.price}</p>
</div>
</a>
</div>
`).join('');
this.searchResultsContainer.innerHTML = resultsHTML;
},
setupPredictiveSearch() {
// Add debounced predictive search functionality
let timeout;
this.searchInput.addEventListener('input', () => {
clearTimeout(timeout);
timeout = setTimeout(() => this.performSearch(), 300);
});
}
};
// Initialize the custom search
document.addEventListener('DOMContentLoaded', () => {
customSearchImplementation.init();
});
Include the JavaScript File:
Add the Search Results Container:
Tag Your Products:
Add Custom CSS (Optional):
If you encounter any issues during implementation or require further customization, feel free to reach out on my email. I’m here to assist you every step of the way.
Best regards,
Shubham
Untechnickle
Oh, and there’s something brewing behind the scenes that’s redefining customer experience. Curious? It’s time to Revize your store. Don’t say we didn’t warn you.
Hello @DeividasAL ,
Thank you for sharing your requirements.
To hide discontinued products from the internal search while keeping them indexed by Google, you can use a simple method involving product tags and minor modifications to your theme code. Here's how:
1. Add a Tag to the Products:
2. Modify Your Search Functionality:
In your Shopify admin, navigate to Online Store > Themes and click Actions > Edit code.
Locate the search.liquid or search-results.liquid file in the Templates or Sections folder.
Find the loop responsible for displaying search results, typically {% for item in search.results %}.
Add this condition to exclude tagged products:
{% for item in search.results %}
{% if item.object_type == 'product' and item.tags contains 'hidden-from-search' %}
{% continue %}
{% endif %}
<!-- Your existing code for displaying results -->
{% endfor %}
Save the file.
3. Verify and Test:
This approach ensures that these products are hidden from the search box without affecting their Google indexing. If you're unfamiliar with editing theme code, let me know my team will do it for free.
Let me know if you need further help!
Best regards,
Shubham | Untechnickle
Oh, and there’s something brewing behind the scenes that’s redefining customer experience. Curious? It’s time to Revize your store. Don’t say we didn’t warn you.
Hello,
Thank you for sharing your requirements.
To hide discontinued products from the internal search while keeping them indexed by Google, you can use a simple method involving product tags and minor modifications to your theme code. Here's how:
1. Add a Tag to the Products:
2. Modify Your Search Functionality:
In your Shopify admin, navigate to Online Store > Themes and click Actions > Edit code.
Locate the search.liquid or search-results.liquid file in the Templates or Sections folder.
Find the loop responsible for displaying search results, typically {% for item in search.results %}.
Add this condition to exclude tagged products:
{% for item in search.results %}
{% if item.object_type == 'product' and item.tags contains 'hidden-from-search' %}
{% continue %}
{% endif %}
<!-- Your existing code for displaying results -->
{% endfor %}
Save the file.
3. Verify and Test:
This approach ensures that these products are hidden from the search box without affecting their Google indexing. If you're unfamiliar with editing theme code, my team will do it for you, for free.
Let me know if you need further help!
Best regards,
Shubham | Untechnickle
Oh, and there’s something brewing behind the scenes that’s redefining customer experience. Curious? It’s time to Revize your store. Don’t say we didn’t warn you.
Hello,
Thank you for sharing your requirements.
To hide discontinued products from the internal search while keeping them indexed by Google, you can use a simple method involving product tags and minor modifications to your theme code. Here's how:
1. Add a Tag to the Products:
2. Modify Your Search Functionality:
In your Shopify admin, navigate to Online Store > Themes and click Actions > Edit code.
Locate the search.liquid or search-results.liquid file in the Templates or Sections folder.
Find the loop responsible for displaying search results, typically {% for item in search.results %}.
Add this condition to exclude tagged products:
{% for item in search.results %}
{% if item.object_type == 'product' and item.tags contains 'hidden-from-search' %}
{% continue %}
{% endif %}
<!-- Your existing code for displaying results -->
{% endfor %}
Save the file.
3. Verify and Test:
This approach ensures that these products are hidden from the search box without affecting their Google indexing. If you're unfamiliar with editing theme code, my team will do it for you, for free.
Let me know if you need further help!
Best regards,
Shubham | Untechnickle
Oh, and there’s something brewing behind the scenes that’s redefining customer experience. Curious? It’s time to Revize your store. Don’t say we didn’t warn you.
{% for item in search.results %} {% if item.object_type == 'product' and item.tags contains 'hidden-from-search' %} {% continue %} {% endif %} <!-- Your existing code for displaying results --> {% endfor %}
Hello,
Thanks for the answer. Im not good at the code, but i found this in main-search.liquid :
{%- for item in search.results -%}
<li class="js-pagination-result">
{%- case item.object_type -%}
{%- when 'product' -%}
{% render 'product-card', product: item, image_ratio: image_ratio, show_compare: settings.enable_compare %}
{%- when 'article' -%}
{% render 'article-card',
Should i put your code after the first line i wrote?
Hey @DeividasAL,
Just replace
{%- for item in search.results -%}
with
{%- for item in search.results -%}
{%- if item.object_type == 'product' and item.tags contains 'hidden-from-search' -%}
{%- continue -%}
{%- endif -%}
This should do that job 🙂
- Shubham | Untechnickle
Oh, and there’s something brewing behind the scenes that’s redefining customer experience. Curious? It’s time to Revize your store. Don’t say we didn’t warn you.
Hello, i have replaced as you said, but the problem is still the same. The product can be found on search box.
Code looks like that:
This is an accepted solution.
@DeividasAL ,
Thank you for your patience while I revisited the issue. I’ve devised a complete solution that will effectively hide discontinued products from your internal search while maintaining their indexing on Google. Here’s the updated approach:
Custom Search Implementation
Create a New JavaScript File:
// Add this code to a new JavaScript file (e.g., custom-search.js)
const customSearchImplementation = {
init() {
this.searchForm = document.querySelector('form[action="/search"]');
this.searchInput = this.searchForm?.querySelector('input[type="search"]');
this.searchResultsContainer = document.querySelector('#search-results-container');
if (this.searchForm) {
this.bindEvents();
this.setupPredictiveSearch();
}
},
bindEvents() {
this.searchForm.addEventListener('submit', (e) => {
e.preventDefault();
this.performSearch();
});
},
async performSearch() {
const searchTerm = this.searchInput.value;
const response = await fetch(`/search/suggest.json?q=${encodeURIComponent(searchTerm)}&resources[type]=product`);
const data = await response.json();
// Filter out products with specific tag or metafield
const filteredResults = this.filterResults(data.resources.results);
this.renderResults(filteredResults);
},
filterResults(results) {
return results.products.filter(product => {
// Check for discontinued tag/metafield
return !product.tags.includes('discontinued') &&
!product.tags.includes('hide-from-search');
});
},
renderResults(results) {
if (!this.searchResultsContainer) return;
const resultsHTML = results.map(product => `
<div class="search-result-item">
<a href="${product.url}" class="search-result-link">
<img src="${product.featured_image.url}" alt="${product.title}" class="search-result-image">
<div class="search-result-details">
<h3>${product.title}</h3>
<p>${product.price}</p>
</div>
</a>
</div>
`).join('');
this.searchResultsContainer.innerHTML = resultsHTML;
},
setupPredictiveSearch() {
// Add debounced predictive search functionality
let timeout;
this.searchInput.addEventListener('input', () => {
clearTimeout(timeout);
timeout = setTimeout(() => this.performSearch(), 300);
});
}
};
// Initialize the custom search
document.addEventListener('DOMContentLoaded', () => {
customSearchImplementation.init();
});
Include the JavaScript File:
Add the Search Results Container:
Tag Your Products:
Add Custom CSS (Optional):
If you encounter any issues during implementation or require further customization, feel free to reach out on my email. I’m here to assist you every step of the way.
Best regards,
Shubham
Untechnickle
Oh, and there’s something brewing behind the scenes that’s redefining customer experience. Curious? It’s time to Revize your store. Don’t say we didn’t warn you.
Hello,
Where exactly in the code i should put this line <div id="search-results-container"></div> ?
In my theme there is no "search.liquid" template , there is Sections/main-search.liquid , code:
_____________
{{ 'products-grid.css' | asset_url | stylesheet_tag }}
{{ 'product.css' | asset_url | stylesheet_tag }}
{%- if settings.card_hover_action == 'slideshow' -%}
<script src="{{ 'product-card-image-slider.js' | asset_url }}" defer="defer"></script>
{%- endif -%}
{%- if settings.enable_quick_add -%}
<link rel="stylesheet" href="{{ 'quick-add.css' | asset_url }}" media="print" onload="this.media='all'">
<script src="{{ 'quick-add.js' | asset_url }}" defer="defer"></script>
<script src="{{ 'variant-picker.js' | asset_url }}" defer="defer"></script>
<script src="{{ 'product-form.js' | asset_url }}" defer="defer"></script>
<script src="{{ 'custom-select.js' | asset_url }}" defer="defer"></script>
{%- endif -%}
{%- if settings.pagination_style == "modern" or settings.pagination_infinite -%}
<script src="{{ 'custom-pagination.js' | asset_url }}" defer="defer"></script>
{%- endif -%}
{%- if settings.enable_predictive_search -%}
<link rel="stylesheet" href="{{ 'predictive-search.css' | asset_url }}" media="print" onload="this.media='all'">
<script src="{{ 'predictive-search.js' | asset_url }}" defer="defer"></script>
<script src="{{ 'tabs.js' | asset_url }}" defer="defer"></script>
{%- endif -%}
{%- liquid
if search.results_count > 0
if section.settings.card_size == 'small'
assign grid_classes_filters_open = 'grid-cols-2 md:grid-cols-3 xl:grid-cols-4'
assign grid_classes_filters_closed = 'grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5'
elsif section.settings.card_size == 'medium'
assign grid_classes_filters_open = 'grid-cols-1 sm:grid-cols-3'
assign grid_classes_filters_closed = 'grid-cols-1 sm:grid-cols-3 xl:grid-cols-4'
else
assign grid_classes_filters_open = 'grid-cols-1 sm:grid-cols-2 xl:grid-cols-3'
assign grid_classes_filters_closed = 'grid-cols-1 sm:grid-cols-2 xl:grid-cols-3'
endif
endif
assign compare_toggle = false
assign compare_visible = false
if settings.enable_compare
if settings.compare_toggle == "none" or settings.compare_toggle == "toggle_on"
assign compare_toggle = true
endif
if settings.compare_toggle != "none"
assign compare_visible = true
endif
endif
-%}
<div class="container">
{%- if section.settings.show_search_title or section.settings.show_search_input -%}
<div class="{{ section.settings.heading_align }}">
{%- if section.settings.show_search_title -%}
<h1>{{ 'general.search.title' | t }}</h1>
{%- endif -%}
{%- if section.settings.show_search_input -%}
<div class="form-width mb-section block{% if section.settings.heading_align == "text-center" %} mx-auto{% elsif section.settings.heading_align == "text-end" %} mis-auto{% endif %}">
{% render 'predictive-search', id: 'main-search', persist_value: true %}
</div>
{%- endif -%}
</div>
{%- endif -%}
{%- if search.performed -%}
{%- if search.results_count == 0 and search.filters == empty -%}
<p class="reading-width {{ section.settings.heading_align }}" role="status">
{{- 'templates.search.no_results' | t: terms: search.terms -}}
</p>
{%- endif -%}
{%- if section.settings.enable_filtering or section.settings.show_layout_toggle or section.settings.enable_sorting or compare_visible -%}
<script src="{{ 'products-toolbar.js' | asset_url }}" defer="defer"></script>
{% render 'products-toolbar', results: search %}
{%- endif -%}
{%- paginate search.results by section.settings.products_per_page -%}
<custom-pagination class="main-products-grid{% if settings.card_contain %} main-products-grid--contained{% endif %} flex" data-layout="grid" data-compare="{{ compare_toggle }}" data-infinite-scroll="{{ settings.pagination_infinite }}" data-pause-infinite-scroll="false">
{%- if search.filters != empty and section.settings.enable_filtering -%}
<div class="main-products-grid__filters{% if section.settings.filters_open_lg == false %} lg:js-hidden{% endif %}">
{% render 'facet-filters', results: search %}
</div>
{%- endif -%}
<div class="main-products-grid__results relative flex-auto" id="filter-results">
{%- if search.results.size == 0 and search.filters != empty -%}
<p>{{ 'sections.collection.empty' | t }}</p>
{%- else -%}
{%- liquid
if settings.prod_card_image_ratio == 'shortest'
assign image_ratio = 0
for item in search.results
if item.object_type == 'product'
if item.featured_media.preview_image.aspect_ratio > image_ratio
assign image_ratio = item.featured_media.preview_image.aspect_ratio
endif
else
if item.image.aspect_ratio > image_ratio
assign image_ratio = item.image.aspect_ratio
endif
endif
endfor
elsif settings.prod_card_image_ratio == 'tallest'
assign image_ratio = 99
for item in search.results
if item.object_type == 'product'
if item.featured_media.preview_image.aspect_ratio < image_ratio
assign image_ratio = item.featured_media.preview_image.aspect_ratio
endif
else
if item.image.aspect_ratio < image_ratio
assign image_ratio = item.image.aspect_ratio
endif
endif
endfor
else
assign image_ratio = settings.prod_card_image_ratio
endif
-%}
<ul class="grid mb-8 md:mb-12 {% if section.settings.filters_open_lg %}{{ grid_classes_filters_open }}{% else %}{{ grid_classes_filters_closed }}{% endif %} gap-x-theme {% if settings.card_contain %}gap-y-5 md:gap-y-8{% else %}gap-y-10{% endif %}"
data-filters-open-classes="grid mb-8 md:mb-12 {{ grid_classes_filters_open }} gap-x-theme {% if settings.card_contain %}gap-y-5 md:gap-y-8{% else %}gap-y-10{% endif %}"
data-filters-closed-classes="grid mb-8 md:mb-12 {{ grid_classes_filters_closed }} gap-x-theme {% if settings.card_contain %}gap-y-5 md:gap-y-8{% else %}gap-y-10{% endif %}" role="list">
{%- for item in search.results -%}
<li class="js-pagination-result">
{%- case item.object_type -%}
{%- when 'product' -%}
{% render 'product-card', product: item, image_ratio: image_ratio, show_compare: settings.enable_compare %}
{%- when 'article' -%}
{% render 'article-card',
article: item,
image_ratio: image_ratio,
show_image: section.settings.show_article_featured_image,
image_ratio: image_ratio,
show_author: section.settings.show_article_author,
show_date: section.settings.show_article_date,
show_tags: section.settings.show_article_tags,
show_excerpt: section.settings.show_article_excerpt
%}
{%- when 'page' -%}
<article class="card relative">
<div class="card__info">
<h3 class="card__title h5 last:mb-0">
<a href="{{ item.url }}" class="card-link text-current">
{{ item.title | truncate: 50 | escape }}
</a>
</h3>
{%- if section.settings.show_page_excerpt -%}
{%- if item.content.size > 0 -%}
<p class="mb-2 last:mb-0">
{{ item.content | strip_html | truncatewords: 30 }}
</p>
{%- endif -%}
{%- endif -%}
{%- if section.settings.show_page_date -%}
<p class="text-theme-light last:mb-0">
{{ item.published_at | time_tag: format: 'date' }}
</p>
{%- endif -%}
</div>
</article>
{%- endcase -%}
</li>
{%- endfor -%}
</ul>
{%- if paginate.pages > 1 -%}
{% render 'pagination', paginate: paginate, style: settings.pagination_style %}
{%- endif -%}
{%- endif -%}
</div>
</custom-pagination>
{%- endpaginate -%}
{%- endif -%}
</div>
{% schema %}
{
"name": "Search page",
"class": "cc-main-search section section--template",
"settings": [
{
"type": "header",
"content": "Heading"
},
{
"type": "checkbox",
"id": "show_search_title",
"label": "Show the default search title",
"info": "If hidden, you should provide a primary page heading (h1 tag) in another section with h1 option (rich text, image banner, slideshow, video) for SEO purposes.",
"default": true
},
{
"type": "checkbox",
"id": "show_search_input",
"label": "Show the search box",
"info": "You could hide this in favor of using the search box in the Header.",
"default": true
},
{
"type": "select",
"id": "heading_align",
"label": "Alignment",
"options": [
{
"value": "text-start",
"label": "Left"
},
{
"value": "text-center",
"label": "Center"
},
{
"value": "text-end",
"label": "Right"
}
],
"default": "text-center"
},
{
"type": "header",
"content": "Layout"
},
{
"type": "range",
"id": "products_per_page",
"min": 8,
"max": 50,
"step": 1,
"label": "Results per page",
"default": 16
},
{
"type": "select",
"id": "card_size",
"label": "Card size",
"options": [
{
"value": "small",
"label": "Small"
},
{
"value": "medium",
"label": "Medium"
},
{
"value": "large",
"label": "Large"
}
],
"default": "medium"
},
{
"type": "header",
"content": "Toolbar"
},
{
"type": "paragraph",
"content": "The Compare toggle can be disabled in \"Theme Settings > Product Compare\"."
},
{
"type": "checkbox",
"id": "show_layout_toggle",
"label": "Show grid/list layout buttons",
"default": true
},
{
"type": "header",
"content": "Filtering"
},
{
"type": "checkbox",
"id": "enable_filtering",
"label": "Enable filtering",
"info": "[Customize filters](/admin/menus)",
"default": true
},
{
"type": "checkbox",
"id": "filters_open_lg",
"label": "Open filters by default on large screens",
"default": true
},
{
"type": "checkbox",
"id": "stick_on_scroll",
"label": "Stick on scroll on large screens",
"default": true
},
{
"type": "checkbox",
"id": "show_filter_counts",
"label": "Show product counts",
"default": true
},
{
"type": "checkbox",
"id": "expand_filters",
"label": "Expand all filters by default",
"default": true
},
{
"type": "range",
"id": "max_filter_options",
"label": "Visible options per filter",
"info": "Remaining options will be automatically collapsed.",
"min": 2,
"max": 50,
"step": 1,
"default": 7
},
{
"type": "header",
"content": "Sorting"
},
{
"type": "checkbox",
"id": "enable_sorting",
"label": "Enable sorting",
"default": true
},
{
"type": "checkbox",
"id": "sort_first",
"label": "Show the sort options first on mobile",
"default": true
},
{
"type": "header",
"content": "Blog cards"
},
{
"type": "checkbox",
"id": "show_article_featured_image",
"label": "Show featured image",
"default": true
},
{
"type": "checkbox",
"id": "show_article_tags",
"label": "Show tags",
"default": false
},
{
"type": "checkbox",
"id": "show_article_excerpt",
"label": "Show excerpt",
"default": false
},
{
"type": "checkbox",
"id": "show_article_author",
"label": "Show author",
"default": true
},
{
"type": "checkbox",
"id": "show_article_date",
"label": "Show published date",
"default": true
},
{
"type": "header",
"content": "Page cards"
},
{
"type": "checkbox",
"id": "show_page_date",
"default": true,
"label": "Show date"
},
{
"type": "checkbox",
"id": "show_page_excerpt",
"default": true,
"label": "Show an excerpt of page content"
}
]
}
{% endschema %}
Hey Community! As the holiday season unfolds, we want to extend heartfelt thanks to a...
By JasonH Dec 6, 2024Dropshipping, a high-growth, $226 billion-dollar industry, remains a highly dynamic bus...
By JasonH Nov 27, 2024Hey Community! It’s time to share some appreciation and celebrate what we have accomplis...
By JasonH Nov 14, 2024