Adding Shopify breadcrumbs to your theme helps both users and search engines understand the structure of your store. Breadcrumbs improve site navigation, enhance user experience, and boost your Shopify store’s SEO by creating a clear content hierarchy and internal linking structure.
Whether you’re looking to add Shopify breadcrumbs on product pages or create custom breadcrumb navigation, this guide will walk you through step-by-step instructions to implement breadcrumbs in your theme—without relying on third-party apps.
1. Open the Theme Editor
Open your Shopify admin and go to Online Store > Themes.
2. Edit the Code
Find your current theme and click the Actions button. From the dropdown, choose Edit Code.

3. Add a New Section
In the Sections folder, click Add a new section.

4. Name Your New Section
Give your new Liquid file a name — for example, shopify-breadcrumbs.liquid. You can use any name you prefer.
5. Paste Your Code
Once the file is created, you’re ready to paste your code into it. (Code Snippet Below)

6. Add it on the front End
Add Section > Search for “breadcrumbs”

Shopify breadcrumbs code
{%- if section.settings.breadcrumbs_enabled -%}
{%- unless template == 'index' or template == 'cart' or template == '404' -%}
{% assign breadcrumbs_menu = linklists[section.settings.breadcrumbs_menu_definition].links %}
{% assign max_depth = 0 %}
{% if section.settings.prefer_shortest_path %}
{% assign previous_max_depth = 9 %}
{% else %}
{% assign previous_max_depth = 0 %}
{% endif %}
{% assign current_template_type = template | split: '.' | first %}
{% assign current_template = nil %}
{% assign current_template_parents = nil %}
{% assign link_found = false %}
{% assign link_depth1 = nil %}
{% assign link_depth2 = nil %}
{% assign link_depth3 = nil %}
{% comment %}Determine page identifier based on page type{% endcomment %}
{% case current_template_type %}
{% when 'product' %}
{% assign current_template = product %}
{% assign current_template_parents = product.collections %}
{% when 'collection' %}
{% assign current_template = collection %}
{% when 'page' %}
{% assign current_template = page %}
{% when 'blog' %}
{% assign current_template = blog %}
{% when 'article' %}
{% assign current_template = article %}
{% assign article_handle_parts = article.handle | split: '/' %}
{% assign blog_handle_extracted = article_handle_parts[0] %}
{% assign template_type_other = true %}
{% else %}
{% comment %}
For all Other template types:
- policies (no actual template)
- search
- list-collections
Use built-in variables request.path and page_title
{% endcomment %}
{% assign template_type_other = true %}
{% endcase %}
{% for link in breadcrumbs_menu %}
{% assign current_depth = 1 %}
{% if link.object %}
{% if link.object.handle and current_template.handle and link.object.handle == current_template.handle %}
{% if link_found == false %}
{% assign max_depth = current_depth %}
{% assign previous_max_depth = max_depth %}
{% assign link_found = true %}
{% elsif section.settings.prefer_shortest_path and current_depth < previous_max_depth %}
{% assign link_depth1 = nil %}
{% assign link_depth2 = nil %}
{% assign link_depth3 = nil %}
{% assign max_depth = current_depth %}
{% assign previous_max_depth = max_depth %}
{% elsif section.settings.prefer_shortest_path == false and current_depth > previous_max_depth %}
{% assign max_depth = current_depth %}
{% assign previous_max_depth = max_depth %}
{% endif %}
{% elsif current_template_parents %}
{% for parent in current_template_parents %}
{% if link.object.handle and parent.handle and link.object.handle == parent.handle %}
{% assign current_depth = current_depth | plus: 1 %}
{% if link_found == false %}
{% assign link_depth1 = link %}
{% assign max_depth = current_depth %}
{% assign previous_max_depth = max_depth %}
{% assign link_found = true %}
{% break %}
{% elsif section.settings.prefer_shortest_path and current_depth < previous_max_depth %}
{% assign link_depth1 = link %}
{% assign link_depth2 = nil %}
{% assign link_depth3 = nil %}
{% assign max_depth = current_depth %}
{% assign previous_max_depth = max_depth %}
{% break %}
{% elsif section.settings.prefer_shortest_path == false and current_depth > previous_max_depth %}
{% assign link_depth1 = link %}
{% assign max_depth = current_depth %}
{% assign previous_max_depth = max_depth %}
{% break %}
{% endif %}
{% endif %}
{% endfor %}
{% elsif template_type_other %}
{% if current_template_type == 'article' %}
{% if link.object.handle and blog_handle_extracted and link.object.handle == blog_handle_extracted %}
{% assign current_depth = current_depth | plus: 1 %}
{% if link_found == false %}
{% assign link_depth1 = link %}
{% assign max_depth = current_depth %}
{% assign previous_max_depth = max_depth %}
{% assign link_found = true %}
{% elsif section.settings.prefer_shortest_path and current_depth < previous_max_depth %}
{% assign link_depth1 = link %}
{% assign link_depth2 = nil %}
{% assign link_depth3 = nil %}
{% assign max_depth = current_depth %}
{% assign previous_max_depth = max_depth %}
{% elsif section.settings.prefer_shortest_path == false and current_depth > previous_max_depth %}
{% assign link_depth1 = link %}
{% assign max_depth = current_depth %}
{% assign previous_max_depth = max_depth %}
{% endif %}
{% endif %}
{% else %}
{% if link.object.title == page_title %}
{% if link_found == false %}
{% assign max_depth = current_depth %}
{% assign previous_max_depth = max_depth %}
{% assign link_found = true %}
{% elsif section.settings.prefer_shortest_path and current_depth < previous_max_depth %}
{% assign link_depth1 = nil %}
{% assign link_depth2 = nil %}
{% assign link_depth3 = nil %}
{% assign max_depth = current_depth %}
{% assign previous_max_depth = max_depth %}
{% elsif section.settings.prefer_shortest_path == false and current_depth > previous_max_depth %}
{% assign max_depth = current_depth %}
{% assign previous_max_depth = max_depth %}
{% endif %}
{% endif %}
{% endif %}
{% endif %}
{% endif %}
{% if link.links %}
{% for childlink in link.links %}
{% assign current_depth = 2 %}
{% if childlink.object %}
{% if childlink.object.handle and current_template.handle and childlink.object.handle == current_template.handle %}
{% if link_found == false %}
{% assign link_depth1 = link %}
{% assign max_depth = current_depth %}
{% assign previous_max_depth = max_depth %}
{% assign link_found = true %}
{% elsif section.settings.prefer_shortest_path and current_depth < previous_max_depth %}
{% assign link_depth1 = link %}
{% assign link_depth2 = nil %}
{% assign link_depth3 = nil %}
{% assign max_depth = current_depth %}
{% assign previous_max_depth = max_depth %}
{% elsif section.settings.prefer_shortest_path == false and current_depth > previous_max_depth %}
{% assign link_depth1 = link %}
{% assign max_depth = current_depth %}
{% assign previous_max_depth = max_depth %}
{% endif %}
{% elsif current_template_parents %}
{% for parent in current_template_parents %}
{% if childlink.object.handle and parent.handle and childlink.object.handle == parent.handle %}
{% assign current_depth = current_depth | plus: 1 %}
{% if link_found == false %}
{% assign link_depth1 = link %}
{% assign link_depth2 = childlink %}
{% assign max_depth = current_depth %}
{% assign previous_max_depth = max_depth %}
{% assign link_found = true %}
{% break %}
{% elsif section.settings.prefer_shortest_path and current_depth < previous_max_depth %}
{% assign link_depth1 = link %}
{% assign link_depth2 = childlink %}
{% assign link_depth3 = nil %}
{% assign max_depth = current_depth %}
{% assign previous_max_depth = max_depth %}
{% break %}
{% elsif section.settings.prefer_shortest_path == false and current_depth > previous_max_depth %}
{% assign link_depth1 = link %}
{% assign link_depth2 = childlink %}
{% assign max_depth = current_depth %}
{% assign previous_max_depth = max_depth %}
{% break %}
{% endif %}
{% endif %}
{% endfor %}
{% elsif template_type_other %}
{% if current_template_type == 'article' %}
{% if link.object.handle and blog_handle_extracted and link.object.handle == blog_handle_extracted %}
{% assign current_depth = current_depth | plus: 1 %}
{% if link_found == false %}
{% assign link_depth1 = link %}
{% assign link_depth2 = childlink %}
{% assign max_depth = current_depth %}
{% assign previous_max_depth = max_depth %}
{% assign link_found = true %}
{% elsif section.settings.prefer_shortest_path and current_depth < previous_max_depth %}
{% assign link_depth1 = link %}
{% assign link_depth2 = childlink %}
{% assign link_depth3 = nil %}
{% assign max_depth = current_depth %}
{% assign previous_max_depth = max_depth %}
{% elsif section.settings.prefer_shortest_path == false and current_depth > previous_max_depth %}
{% assign link_depth1 = link %}
{% assign link_depth2 = childlink %}
{% assign max_depth = current_depth %}
{% assign previous_max_depth = max_depth %}
{% endif %}
{% endif %}
{% else %}
{% if link.object.title == page_title %}
{% if link_found == false %}
{% assign link_depth1 = link %}
{% assign max_depth = current_depth %}
{% assign previous_max_depth = max_depth %}
{% assign link_found = true %}
{% elsif section.settings.prefer_shortest_path and current_depth < previous_max_depth %}
{% assign link_depth1 = link %}
{% assign link_depth2 = nil %}
{% assign link_depth3 = nil %}
{% assign max_depth = current_depth %}
{% assign previous_max_depth = max_depth %}
{% elsif section.settings.prefer_shortest_path == false and current_depth > previous_max_depth %}
{% assign link_depth1 = link %}
{% assign max_depth = current_depth %}
{% assign previous_max_depth = max_depth %}
{% endif %}
{% endif %}
{% endif %}
{% endif %}
{% endif %}
{% if childlink.links %}
{% for grandchildlink in childlink.links %}
{% if section.settings.prefer_shortest_path and link_found %}{% break %}{% endif %}
{% assign current_depth = 3 %}
{% if grandchildlink.object.handle and current_template.handle and grandchildlink.object.handle == current_template.handle %}
{% if link_found == false %}
{% assign link_depth1 = link %}
{% assign link_depth2 = childlink %}
{% assign max_depth = current_depth %}
{% assign previous_max_depth = max_depth %}
{% assign link_found = true %}
{% elsif section.settings.prefer_shortest_path and current_depth < previous_max_depth %}
{% assign link_depth1 = link %}
{% assign link_depth2 = childlink %}
{% assign link_depth3 = nil %}
{% assign max_depth = current_depth %}
{% assign previous_max_depth = max_depth %}
{% elsif section.settings.prefer_shortest_path == false and current_depth > previous_max_depth %}
{% assign link_depth1 = link %}
{% assign link_depth2 = childlink %}
{% assign max_depth = current_depth %}
{% assign previous_max_depth = max_depth %}
{% endif %}
{% elsif current_template_parents %}
{% for parent in current_template_parents %}
{% if grandchildlink.object.handle and parent.handle and grandchildlink.object.handle == parent.handle %}
{% assign current_depth = current_depth | plus: 1 %}
{% if link_found == false %}
{% assign link_depth1 = link %}
{% assign link_depth2 = childlink %}
{% assign link_depth3 = grandchildlink %}
{% assign max_depth = current_depth %}
{% assign previous_max_depth = max_depth %}
{% assign link_found = true %}
{% break %}
{% elsif section.settings.prefer_shortest_path and current_depth < previous_max_depth %}
{% assign link_depth1 = link %}
{% assign link_depth2 = childlink %}
{% assign link_depth3 = grandchildlink %}
{% assign max_depth = current_depth %}
{% assign previous_max_depth = max_depth %}
{% break %}
{% elsif section.settings.prefer_shortest_path == false and current_depth > previous_max_depth %}
{% assign link_depth1 = link %}
{% assign link_depth2 = childlink %}
{% assign link_depth3 = grandchildlink %}
{% assign max_depth = current_depth %}
{% assign previous_max_depth = max_depth %}
{% break %}
{% endif %}
{% endif %}
{% endfor %}
{% elsif template_type_other %}
{% if current_template_type == 'article' %}
{% if link.object.handle and blog_handle_extracted and link.object.handle == blog_handle_extracted %}
{% assign current_depth = current_depth | plus: 1 %}
{% if link_found == false %}
{% assign link_depth1 = link %}
{% assign link_depth2 = childlink %}
{% assign link_depth3 = grandchildlink %}
{% assign max_depth = current_depth %}
{% assign previous_max_depth = max_depth %}
{% assign link_found = true %}
{% elsif section.settings.prefer_shortest_path and current_depth < previous_max_depth %}
{% assign link_depth1 = link %}
{% assign link_depth2 = childlink %}
{% assign link_depth3 = grandchildlink %}
{% assign max_depth = current_depth %}
{% assign previous_max_depth = max_depth %}
{% elsif section.settings.prefer_shortest_path == false and current_depth > previous_max_depth %}
{% assign link_depth1 = link %}
{% assign link_depth2 = childlink %}
{% assign link_depth3 = grandchildlink %}
{% assign max_depth = current_depth %}
{% assign previous_max_depth = max_depth %}
{% endif %}
{% endif %}
{% else %}
{% if link.object.title == page_title %}
{% if link_found == false %}
{% assign link_depth1 = link %}
{% assign link_depth2 = childlink %}
{% assign max_depth = current_depth %}
{% assign previous_max_depth = max_depth %}
{% assign link_found = true %}
{% elsif section.settings.prefer_shortest_path and current_depth < previous_max_depth %}
{% assign link_depth1 = link %}
{% assign link_depth2 = childlink %}
{% assign link_depth3 = nil %}
{% assign max_depth = current_depth %}
{% assign previous_max_depth = max_depth %}
{% elsif section.settings.prefer_shortest_path == false and current_depth > previous_max_depth %}
{% assign link_depth1 = link %}
{% assign link_depth2 = childlink %}
{% assign max_depth = current_depth %}
{% assign previous_max_depth = max_depth %}
{% endif %}
{% endif %}
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
{% endfor %}
{% endif %}
{% endfor %}
<div class="page-width gradient color-{{ section.settings.color_scheme }}">
<nav aria-label="Breadcrumb" class="breadcrumbs ">
<ol class="breadcrumbs__list">
<li class="breadcrumbs__item"><a class="breadcrumbs__link" href="{{ request.locale.root_url }}">Home</a></li>
{% if link_depth1 %}
<li class="breadcrumbs__item"><a class="breadcrumbs__link" href="{{ link_depth1.url }}">{{ link_depth1.title }}</a></li>
{% endif %}
{% if link_depth2 %}
<li class="breadcrumbs__item"><a class="breadcrumbs__link" href="{{ link_depth2.url }}">{{ link_depth2.title }}</a></li>
{% endif %}
{% if link_depth3 %}
<li class="breadcrumbs__item"><a class="breadcrumbs__link" href="{{ link_depth3.url }}">{{ link_depth3.title }}</a></li>
{% endif %}
{% if template_type_other %}
<li class="breadcrumbs__item" aria-current="page">{{ page_title }}</li>
{% else %}
<li class="breadcrumbs__item" aria-current="page">{{ current_template.title }}</li>
{% endif %}
</ol>
</nav>
{% if section.settings.enable_divider %}
<div id="breadcrumbs-divider"></div>
{% endif %}
</div>
{% endunless %}
{%- endif -%}
{% schema %}
{
"name": "Breadcrumbs",
"tag": "section",
"class": "section",
"settings": [
{
"type": "checkbox",
"id": "breadcrumbs_enabled",
"label": "Enable Breadcrumbs",
"default": true
},
{
"type": "link_list",
"id": "breadcrumbs_menu_definition",
"default": "main-menu",
"label": "Breadcrumbs Menu Definition"
},
{
"type": "checkbox",
"id": "prefer_shortest_path",
"label": "Use Shortest Path",
"default": false
},
{
"type": "select",
"id": "separator_shape",
"label": "Breadcrumb Separator Shape",
"options": [
{
"value": "triangle",
"label": "Triangle ( > )"
},
{
"value": "slash",
"label": "Slash ( / )"
}
],
"default": "triangle"
},
{
"type": "range",
"id": "font_size",
"label": "Font Size",
"min": 10,
"max": 20,
"step": 1,
"default": 14,
"unit": "px"
},
{
"type": "color_scheme",
"id": "color_scheme",
"label": "t:sections.all.colors.label",
"default": "scheme-1"
},
{
"type": "checkbox",
"id": "enable_divider",
"label": "Enable Divider",
"default": false
},
{
"type": "color",
"id": "divider_color",
"label": "Divider Color",
"default": "#ccc"
},
{
"type": "header",
"content": "t:sections.all.padding.section_padding_heading"
},
{
"type": "range",
"id": "padding_top",
"min": 0,
"max": 50,
"step": 2,
"unit": "px",
"label": "t:sections.all.padding.padding_top",
"default": 12
},
{
"type": "range",
"id": "padding_bottom",
"min": 0,
"max": 50,
"step": 2,
"unit": "px",
"label": "t:sections.all.padding.padding_bottom",
"default": 12
}
],
"presets": [
{
"name": "breadcrumbs"
}
]
}
{% endschema %}
<style>
.breadcrumbs {
padding-top: {{ section.settings.padding_top }}px;
padding-bottom: {{ section.settings.padding_bottom }}px;
}
.breadcrumbs__list {
list-style-type: none;
margin: 0;
padding: 0;
font-size: {{ section.settings.font_size }}px;
}
.breadcrumbs__item {
display: inline-block;
}
.breadcrumbs__item:not(:last-child):after {
content: '';
display: inline-block;
margin: 0 .20em;
position: relative;
vertical-align: middle;
{% if section.settings.separator_shape == 'triangle' %}
border-style: solid;
border-width: .10em .10em 0 0;
height: .30em;
width: .30em;
transform: rotate(45deg);
top: -0.1em;
{% elsif section.settings.separator_shape == 'slash' %}
content: '/';
margin-left: .5em;
{% endif %}
}
.breadcrumbs__link {
cursor: pointer;
display: inline-block;
border: none;
box-shadow: none;
text-decoration: none;
text-underline-offset: 0.3rem;
color: rgb(var(--color-text));
/*font-size: 1.4rem;*/
font-family: inherit;
}
.breadcrumbs__link:hover {
text-decoration: underline;
text-underline-offset: 0.3rem;
color: rgb(var(--color-foreground));
}
#breadcrumbs-divider {
display: block;
height: 1px;
background-color: {{ section.settings.divider_color }};
}
</style>
4 Comments
Gabriel
This article was really interesting and gave me a lot of
useful information. The site is definitely a great resource for learning more.
Kate
Hi, thanks for the instructions. I tried and thought it’s working but it’s not showing the right path. For example, even if I came through “Home > Shop > Gifts >Product A”, or “Home > Shop > Tools >Product A”, the breadcrumb only shows “Home > Shop > New in > Product A”.
admin
Hi @Kate, This is working on my end and shows the path correctly. Can you provide me your menu structure ?
Tom
If a collection appears in two separate menu paths, this code defaults to populating whichever path is listed first. For example:
Collection 1 > Collection 2
Collection 3 > Collection 2
In this case, if someone is on Collection 2, the code will always select the first path (Collection 1 > Collection 2) by default—even if the user navigated there from Collection 3. Is there a way to work around this behavior?