Shopify Navigation Headaches: How to Hide Empty Filtered Collection Links
Hey fellow store owners! Navigating the world of Shopify customization can sometimes feel like a puzzle, especially when you're trying to perfect the user experience for different markets. I recently stumbled upon a really insightful community discussion that hit on a common pain point: how do you hide navigation links for collections that, while technically not empty, become effectively empty once filters or market restrictions are applied?
It's a tricky one, and it sparked a great conversation that I wanted to break down for you. Let's dive into what Jason.Hart was grappling with and the expert advice that came out of it.
The 'Empty' Filtered Collection Dilemma
Jason.Hart, like many of us, wanted to keep his store's navigation clean and user-friendly. His store had a main collection called "shirt-and-trouser", which, as the name suggests, included products tagged with both "shirt" and "trouser". In his navigation, he had a structure like this:
Shirts and Trousers
Shirts
Trousers
The "Shirts" and "Trousers" links were designed to point to the main "shirt-and-trouser" collection, but with a filter applied (e.g., /collections/shirt-and-trouser/shirts). The problem arose because one of his markets didn't sell trousers. This meant that for customers in that market, the "Trousers" link would lead to a page with no products, even though the underlying "shirt-and-trouser" collection still contained shirts.
Jason was using a Liquid snippet to check if a collection link should be rendered based on its product availability:
{% assign render_link = true %}
{% if current_link.type == 'collection_link' and current_link.links == blank %}
{% assign render_link = false %}
{% for item in current_link.object.products %}
{% if item.available %}
{% assign render_link = true %}
{% endif %}
{% endfor %}
{% elsif current_link.type == 'collection_link' %}
{% assign render_link = false %}
{% for current_child_link in current_link.links %}
{% for item in current_child_link.object.products %}
{% if item.available %}
{% assign render_link = true %}
{% endif %}
{% endfor %}
{% endfor %}
{% endif %}
{% if render_link == true %}
{{ current_link.title }}
{% endif %}
As you can see, this snippet checks current_link.object.products, which refers to the entire collection the link points to. Since "shirt-and-trouser" still had shirts, the trousers link was always considered "renderable".
The Expert Take: Liquid's Limitations
Steve_TopNewYork jumped in with a clear explanation, confirming what many seasoned Shopify developers already know: Liquid has limitations when it comes to dynamic filtering awareness at the navigation level.
Steve pointed out that Jason's logic was sound for checking if an entire collection had available products. The core issue, however, is that Liquid, when rendering navigation links (main_menu.links), doesn't "know" about the specific tags or filters that a particular navigation link is *intended* to apply. It only sees the underlying collection object.
So, even if your "Trousers" navigation link is set up to go to /collections/shirt-and-trouser?filter=trousers, Liquid just sees that it links to the shirt-and-trouser collection. If that collection isn't empty, the link gets rendered.
Solutions from the Community
Steve offered two main paths forward, and Jason's response showed a clear preference for the first, simpler option:
1. The "Pure Collection" Approach (Recommended)
This is often the most straightforward and robust solution for this kind of problem. Instead of having a single broad collection (like shirt-and-trouser) and relying on filters for child navigation links, you create dedicated, "pure" collections:
- A
Shirtscollection that only contains shirts. - A
Trouserscollection that only contains trousers.
Then, your navigation links would point directly to these specific collections:
Collections / Shirts
Collections / Trousers
Why this works: With this structure, your Liquid snippet can accurately check current_link.object.products because the current_link.object *is* the actual filtered collection. If the Trousers collection has no available products in a specific market, then current_link.object.products for that link will indeed be empty, and your snippet will correctly hide it.
Jason's take: He confirmed this was his expected solution and stated he would "reorganize the website into ‘pure’ collections." He even noted a bonus benefit: "It was initially done this way as to have nice breadcrumbs for navigation." This is a great point! Pure collections often lead to clearer URLs and breadcrumb trails, which is a win for SEO and user experience.
How to implement the "Pure Collection" approach:
- Create New Collections: Go to your Shopify admin > Products > Collections. Create a new collection for each specific category (e.g., "Shirts", "Trousers").
- Populate Collections: Set up these new collections to automatically include products based on tags or conditions. For instance, your "Shirts" collection would automatically include all products tagged "shirt".
- Update Navigation: Go to Online Store > Navigation. Edit your main menu and update the problematic child links to point directly to these newly created, specific collections instead of relying on filters on a broader collection.
- Test: Crucially, test your navigation in different markets (if you use Shopify Markets) to ensure the links appear and disappear as expected.
2. Advanced Custom Logic (Metafields or JavaScript)
For more complex scenarios where restructuring collections isn't feasible or desired, Steve mentioned implementing custom logic outside of standard Liquid. This could involve:
- Metafields: Storing pre-calculated counts of filtered products per market in product or collection metafields, which Liquid *can* access. This would require a process (either manual or automated via an app/script) to update these metafields.
- JavaScript: Using JavaScript on the frontend to check if a filtered collection page would be empty after the page loads. If it is, JavaScript could then hide the navigation link dynamically. This approach can be more complex and might lead to a brief "flash" of the link before it's hidden.
While these are valid technical solutions, they add layers of complexity and development effort. For most store owners, especially those looking for a cleaner, more maintainable solution within the standard Shopify framework, the "pure collection" method is often the better path.
Wrapping It Up
This community thread is a fantastic example of how seemingly small UI issues can lead to deeper discussions about Shopify's architecture and best practices. The key takeaway here is that while Liquid is powerful, it has specific data contexts it operates within. When you're trying to make dynamic decisions in your navigation, sometimes the most elegant solution isn't more complex code, but a smarter structural approach to your Shopify store's data.
Thinking about your collection structure from the outset, especially if you're dealing with multiple markets or complex filtering, can save you a lot of headaches down the line. It's all about making sure your customers always find what they're looking for, or at least don't get frustrated by dead-end links!