How to display product category path in breadcrumbs?

Topic summary

A Shopify store owner is seeking help to display the complete product category path in their breadcrumb navigation. Currently, their breadcrumbs only show the path on the item/product page itself, but they want to include the full category hierarchy.

Current Issue:

  • Breadcrumbs are not displaying the product category path as desired
  • The user has shared their existing breadcrumbs.liquid code for review

Code Details:

  • The provided code appears corrupted or improperly formatted (contains reversed/garbled text)
  • The code attempts to handle breadcrumbs for different template types (article, product, collection)
  • It includes logic to traverse navigation menus and product collections

Status:
The discussion remains open with no responses yet. The user needs assistance debugging their breadcrumb code to properly display the category path for products.

Summarized with AI on November 18. AI used: claude-sonnet-4-5-20250929.

Hello

I used that code, good, but for me missing the path from product category. Now, showing the path only on item side. Could you help me please?

webside: https://vitotuzep.hu/collections/falazohabarcs

my breadcumbs.liquid code

{%- unless template == ‘index’ or template == ‘cart’ -%}
Home
{% case template %}
{% when ‘article’ %}
{% for link in linklists.main-menu.links %}
{%- if link.url == blog.url -%}

{{link.title | link_to: link.url}}
{% break %}
{%- endif -%}
{% endfor %}

{{ article.title }}
{%- when “product” -%}
{%- capture product_url_string -%}
{%- for collection in product.collections -%}
{{collection.url }}|
{%- endfor -%}
{%- endcapture -%}

{%- assign object_url_string = product_url_string | append: product.url -%}

{%- assign object_urls = object_url_string | split: ‘|’ -%}
{%- capture linklist_titles_str -%}{%- for linklist in linklists -%}{{ linklist.title | handleize }}|{%- endfor -%}{%- endcapture -%}
{%- assign str_size = linklist_titles_str | size | minus: 1 -%}
{%- assign linklist_titles_str = linklist_titles_str | slice: 0, str_size -%}
{%- assign linklist_titles = linklist_titles_str | split: ‘|’ -%}

{%- assign level = 1 -%}
{%- for link in linklists.main-menu.links -%}
{%- assign link_handle = link.title | handle -%}
{%- assign link_titles = link_titles | append: link.title | append: ‘|’ -%}
{%- assign link_urls = link_urls | append: link.url | append: ‘|’ -%}
{%- assign link_levels = link_levels | append: level | append: ‘|’ -%}
{%- assign link_parents = link_parents | append: ‘main-menu’ | append: ‘|’ -%}
{%- assign link_handles = link_handles | append: link_handle | append: ‘|’ -%}

{%- if linklist_titles contains link_handle -%}

{%comment%} GET CHILDREN {%endcomment%}

{%- for clink in linklists[link_handle].links -%}
{%- if forloop.first == true -%}
{%- assign level = level | plus: 1 -%}
{%- endif -%}
{% assign clink_handle = clink.title | handle %}
{%- assign link_titles = link_titles | append: clink.title | append: ‘|’ -%}
{%- assign link_urls = link_urls | append: clink.url | append: ‘|’ -%}
{%- assign link_levels = link_levels | append: level | append: ‘|’ -%}
{%- assign link_parents = link_parents | append: link_handle | append: ‘|’ -%}
{%- assign handle = link.title | handleize -%}
{%- assign link_handles = link_handles | append: clink_handle | append: ‘|’ -%}

{%- if linklist_titles contains clink_handle -%}

{%comment%} GET GRANDCHILDREN {%endcomment%}

{%- for gclink in linklists[clink_handle].links -%}
{%- if forloop.first == true -%}
{%- assign level = level | plus: 1 -%}
{%- endif -%}

{% assign gclink_handle = gclink.title | handle %}
{%- assign link_titles = link_titles | append: gclink.title | append: ‘|’ -%}
{%- assign link_urls = link_urls | append: gclink.url | append: ‘|’ -%}
{%- assign link_levels = link_levels | append: level | append: ‘|’ -%}
{%- assign link_parents = link_parents | append: gclink_handle | append: ‘|’ -%}
{%- assign link_handles = link_handles | append: gclink_handle | append: ‘|’ -%}

{%- comment -%}It’s done at this point{%- endcomment -%}
{%- if forloop.last == true -%}
{%- assign level = level | minus: 1 -%}
{%- endif -%}
{%- endfor -%}
{%comment%} END GRANDCHILDREN {%endcomment%}

{%- endif -%}
{%- if forloop.last == true -%}
{%- assign level = level | minus: 1 -%}
{%- endif -%}
{%- endfor -%}
{%comment%} END CHILDREN {%endcomment%}
{%- endif -%}
{%- endfor -%}

{%- comment -%} CONVERT TO ARRAYS {%- endcomment -%}
{%- assign str_size = link_levels | size | minus: 1 -%}
{%- assign llevels = link_levels | slice: 0, str_size | split: ‘|’ -%}

{%- assign str_size = link_titles | size | minus: 1 -%}
{%- assign ltitles = link_titles | slice: 0, str_size | split: ‘|’ -%}

{%- assign str_size = link_handles | size | minus: 1 -%}
{%- assign lhandles = link_handles | slice: 0, str_size | split: ‘|’ -%}

{%- assign str_size = link_parents | size | minus: 1 -%}
{%- assign lparents = link_parents | slice: 0, str_size | split: ‘|’ -%}

{%- assign str_size = link_urls | size | minus: 1 -%}
{%- assign lurls = link_urls | slice: 0, str_size | split: ‘|’ -%}

{%- comment -%} GET THE DEEPEST LEVEL WE FOUND {%- endcomment -%}
{%- assign depth = ‘3’ -%}
{%- assign bc3_parent_list_handle = ‘’ %}

{%- comment -%}Example output for {{ llevels }} this could be: 11122211 {%- endcomment -%}

{%- comment -%} LEVEL 3: THREE DOWN FROM THE TOP {%- endcomment -%}
{%- comment -%} Do we have a link to this product or its collection on the deepest level? {%- endcomment -%}

{%- for url in lurls -%}

{%- if object_urls contains url and llevels[forloop.index0] == depth -%}
{%- unless url == product.url or url == collection.url -%}
{%- capture bc3 -%}{{ ltitles[forloop.index0] | link_to: url, ltitles[forloop.index0] }}{%- endcapture -%}
{%- endunless -%}
{%- assign bc3_parent_list_handle = lparents[forloop.index0] -%}
{%- assign bc3_list_handle = lhandles[forloop.index0] -%}
{% break %}
{%- endif -%}
{%- endfor -%}

{%- comment -%} LEVEL 2: TWO DOWN FROM THE TOP
Next level. If we found something, we can save a lot of processing. Otherwise,
we need to scan everything on this level
{%- endcomment -%}
{%- assign depth = ‘2’ -%}
{%- assign bc2_parent_list_handle = ‘’ %}

{%- comment -%} IF we didn’t find anything on the deepest level, we start from scratch one level up {%- endcomment -%}
{%- if bc3_parent_list_handle == ‘’ -%}
{%- for url in lurls -%}
{%- if llevels[forloop.index0] == depth -%}
{%- if object_urls contains url -%}
{%- unless url == product.url or url == collection.url -%}
{%- capture bc2 -%}{{ ltitles[forloop.index0] | link_to: url, ltitles[forloop.index0] }}{%- endcapture -%}
{% endunless %}
{%- assign bc2_parent_list_handle = lparents[forloop.index0] -%}
{%- break -%}
{%- endif -%}
{%- endif -%}
{%- endfor -%}

{%- comment -%} ELSE we have a parent handle. We need its array index to find its other data {%- endcomment -%}
{%- else -%}
{%- for list_handle in lhandles -%}
{%- if list_handle == bc3_parent_list_handle -%}
{% assign bc2_list_handle = list_handle %}
{%- assign bc2_parent_list_handle = lparents[forloop.index0] -%}
{%- assign bc2_list_title = ltitles[forloop.index0] -%}
{%- comment -%} we have the handle of bc2’s parent, so now we get the parent links, find where title matches parent title, then we have the collection URL {%- endcomment -%}
{%- for bc2_sibling_link in linklists[bc2_parent_list_handle].links -%}
{%- assign bc2_sibling_title_handleized = bc2_sibling_link.title | handle -%}
{% if bc2_sibling_title_handleized == bc2_list_handle %}
{%- capture bc2 -%}{{ bc2_sibling_link.title | link_to: bc2_sibling_link.url, bc2_sibling_link.title }}{%- endcapture -%}
{% break %}
{%- endif -%}
{%- endfor -%}
{% break %}
{%- endif -%}
{%- endfor -%}
{%- endif -%}

{%- comment -%} LEVEL 1: MAIN ITEMS BELOW MAIN MENU (I.E. TOP NAV BAR) {%- endcomment -%}

{%- assign depth = depth | minus: 1 | append: ‘’ -%}
{%- assign bc1_parent_list_handle = ‘’ %}

{%- if bc2_parent_list_handle == ‘’ -%}
{%- comment -%} IF found nothing on deepest level or middle level, we start from scratch on top level {%- endcomment -%}
{% for url in lurls %}
{%- if object_urls contains url and llevels[forloop.index0] == depth -%}
{%- unless url == product.url or url == collection.url -%}
{%- capture bc1 -%}{{ ltitles[forloop.index0] | link_to: url, ltitles[forloop.index0] }}{%- endcapture -%}
{% endunless %}
{%- assign bc1_parent_list_handle = lparents[forloop.index0] -%}
{%- break -%}
{%- endif -%}
{%- endfor -%}

{%- comment -%}
ELSE we have a parent handle. We need its array index to find its other data
{%- endcomment -%}
{%- else -%}
{%- for list_handle in lhandles -%}
{%- if bc2_parent_list_handle == list_handle -%}
{% assign bc1_list_handle = list_handle %}
{%- assign bc1_parent_list_handle = lparents[forloop.index0] -%}
{%- assign bc1_title = ltitles[forloop.index0] -%}
{%- comment -%}
We HAVE PARENT, so now we GET THE SIBLING links, find where title
matches parent title, then we have the collection URL
{%- endcomment -%}
{%- for bc1_sibling_link in linklists[bc1_parent_list_handle].links -%}
{%- assign bc1_sibling_title_handleized = bc1_sibling_link.title | handle -%}
{% if bc1_sibling_title_handleized == bc1_list_handle %}
{%- capture bc1 -%}{{ bc1_sibling_link.title | link_to: bc1_sibling_link.url, bc1_sibling_link.title }}{%- endcapture -%}
{% break %}
{%- endif -%}
{%- endfor -%}
{%- endif -%}
{%- endfor -%}
{%- endif -%}

{%- if bc1 -%}

{{ bc1 }}
{%- endif -%}
{%- if bc2 -%}

{{ bc2 }}
{%- endif -%}
{%- if bc3 -%}

{{ bc3 }}
{%- endif -%}


{{ product.title }}
{%- else -%}
{% for link in linklists.main-menu.links %}
{% if link.child_active or link.active %}


{{ link.title | escape }}

{% for clink in link.links %}
{% if clink.child_active or clink.active %}


{{ clink.title | escape }}

{% for gclink in clink.links %}
{% if gclink.child_active or gclink.active %}


{{ gclink.title | escape }}

{% endif %}
{%- endfor -%}
{% endif %}
{%- endfor -%}
{% endif %}
{%- endfor -%}
{% endcase %}
{%endunless%}