Dynamic BreadcrumbList Schema Markup with all displayed levels

Topic summary

A user is attempting to manually implement BreadcrumbList schema markup for collection pages without using plugins, but lacks development experience.

Current Issue:

  • The script works correctly on URLs with multiple breadcrumb levels (e.g., /collections/des-20-faces-a-lunite)
  • Breaks when applied to parent URLs with fewer breadcrumb levels (e.g., /collections/des-jdr)
  • Testing is being done on a duplicated theme, not production

Goal:
Create conditional logic that adapts the schema markup to work across all pages regardless of breadcrumb depth.

Code Provided:
The user shared a Liquid template script that:

  • Handles product, collection, and page templates
  • Attempts to dynamically generate breadcrumb hierarchy
  • Contains reversed/obfuscated code sections (text written backwards)
  • Uses linklist navigation to build breadcrumb structure

Status:
The discussion remains open with no responses yet. The user is seeking help to add conditions that make the script flexible enough to handle varying breadcrumb levels.

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

Hello Guys,

I’m trying to set some Schema markups without any plugin as I can’t relate on apps for my project.

I’m not a dev so I’m struggling a bit on this. My goal is to have correctly implemented BreadcrumbList on my collection pages (I’ll do it on product pages later, one step at a time… :sweat_smile: )

I’ve implemented something that works for my url https://youroll.fr/collections/des-20-faces-a-lunite (it’s on a duplicated theme so you can’t test it on the prod). With my script below, the breadcrumb schema is correctly implemented on this url (with all the breadcrumb levels) BUT if I go on a mother url with less breadcrumb levels (like https://youroll.fr/collections/des-jdr), it’s all broken.

Can you guys help me to implement conditions for my script to work on every pages regardless the breadcrumb levels number please ?

This is my script :

{%- if template contains 'product' -%}
  {%- capture product_url_string -%}{%- for collection in product.collections -%}{{collection.url }}|{%- endfor -%}{%- endcapture -%}
  {%- assign object_url_string = product_url_string | append: product.url -%}
{%- elsif template contains 'collection' and collection.handle -%}
  {%- capture object_url_string -%}/collections/{{ collection.handle }}{%- endcapture -%}
{%- elsif template contains 'page' -%}
  {%- capture object_url_string -%}/pages/{{ page.url }}{%- endcapture -%}
{% endif %}
 
{%- 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 -%}
 
    
 
    {%- 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 -%}
 
             
 
            {%- 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: clink_handle | append: '|'  -%}
              {%- assign link_handles = link_handles | append: gclink_handle | append: '|' -%}
 
              {%- if linklist_titles contains gclink_handle -%}
                
              {%- endif -%}
              {%- if forloop.last == true -%}
                {%- assign level = level | minus: 1 -%}
              {%- endif -%}
            {%- endfor -%}
                
 
      {%- endif -%}
      {%- if forloop.last == true -%}
        {%- assign level = level | minus: 1 -%}
      {%- endif -%}
    {%- endfor -%}
              
  {%- 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: '|' -%}
 

{%- assign depth = '3' -%}
{%- assign bc3_parent_list_handle = '' %}
 

{%- 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] -%}
    {%- assign bc3_list_title = ltitles[forloop.index0] -%}
    {% break %}
  {%- endif -%}
{%- endfor -%}
 

{%- assign depth = '2' -%}
{%- assign bc2_parent_list_handle = '' %}
 

{%- 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 -%}
   
  
{%- 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] -%}
      
      {%- 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 -%}
 

 
{%- assign depth = depth | minus: 1 | append: '' -%}
{%- assign bc1_parent_list_handle = '' %}
 
{%- if bc2_parent_list_handle == '' -%} 
   
  {% 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 -%}
 

{%- 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_list_title = ltitles[forloop.index0] -%}
            
      {%- 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 -%}
 
 
  
<script type="application/ld+json">
{
  "@context": "http://schema.org",
  "@type": "BreadcrumbList",
  "itemListElement": [
    {
      "@type": "ListItem",
      "position": 1,
      "name": "Accueil",
      "item": "{{ shop.url }}"
    },
    {%- if template contains 'collection' -%}
      {
        "@type": "ListItem",
        "position": 2,
        "name": "{{ bc1_list_title }}",
        "item": "{{ shop.url }}/{{ bc1_list_handle }}"
      },
      {
        "@type": "ListItem",
        "position": 3,
        "name": "{{ bc2_list_title }}",
        "item": "{{ shop.url }}/{{ bc2_list_handle }}"
      },
            {
        "@type": "ListItem",
        "position": 4,
        "name": "{{ bc3_list_title }}",
        "item": "{{ shop.url }}/{{ bc3_list_handle }}"
      }
    {%- elsif template == 'product' -%}
      {
        "@type": "ListItem",
        "position": 2,
        "name": "{{ product.title }}",
        "item": "{{ product.url }}"
      }
	{%- else -%}	  
	{
	  "@type": "ListItem",
	  "position": 2,
	  "name": "{{ page.title }}",
	  "item": "{{ shop.url }}{{ request.path }}"
	}
    {%- endif -%}
  ]
}
</script>

If you have any simpler solution I would be glad to read it as well :sweat_smile:

Many thanks for your help