search ]

How to add BreadCrumbs Navigation to a WordPress Site

Breadcrumb trails show users their current location on your website. The term “breadcrumbs” comes from the tale of Hansel and Gretel, where the main characters left a trail of breadcrumbs to find their way back home.

Just like in the fairy tale, your users need to know where they are in the site hierarchy so they can navigate to higher levels. In this guide, you’ll learn why breadcrumbs matter, how to add them to your WordPress site, and how they benefit both SEO and user experience.

Why Use Breadcrumbs

Breadcrumbs are a visual aid that shows the user’s position in your site’s hierarchy. They help users answer three key questions:

  • Where am I? Breadcrumbs show users their location relative to the overall site structure.
  • Where can I go? Breadcrumbs make site navigation clearer than the main menu alone. Users can quickly see the hierarchy and jump to any parent level.
  • Should I navigate there? Breadcrumbs encourage exploration. On e-commerce sites, for example, a visitor on a product page that doesn’t quite match can click up to the product category and find a better fit – reducing your bounce rate in the process.

Additional Benefits

  • Fewer actions needed – Breadcrumbs reduce the number of clicks a user needs to reach a higher level. Instead of the browser’s back button or the main menu, one click on a breadcrumb takes them where they want to go.
  • Minimal space – Breadcrumbs are compact horizontal text links. They take up very little page space and don’t interfere with the main content.
  • Universally understood – Users may overlook breadcrumbs, but they’ll never be confused by them. Everyone intuitively knows how they work.
  • Google loves them – Breadcrumbs can appear in search results and improve your CTR. More on that below.

When to Use Breadcrumbs

To determine whether your site needs breadcrumbs, think about its structure. Sites with deep hierarchies and clearly defined categories benefit the most.

  • Use breadcrumbs when your site has a large amount of content organized in a hierarchical structure with defined categories. E-commerce sites with many products grouped into categories are a great example.
  • Don’t use breadcrumbs on flat, single-level websites with no logical hierarchy.

There are three types of breadcrumbs: location-based, attribute-based, and path-based. Location-based breadcrumbs (showing the page’s position in the site hierarchy) are the most common and the type most sites should implement.

Best Practices for Breadcrumbs

When designing breadcrumbs, follow these guidelines to keep them effective:

1. Don’t Replace the Main Menu

Breadcrumbs are a secondary navigation aid, not a replacement for your site’s main menu. Think of them as a convenience feature that supplements primary navigation.

2. Don’t Link to the Current Page

The last item in the breadcrumb trail is optional, but if you display it, make sure it’s not clickable. The user is already on that page.

3. Use Clear Separators

The most common separator is the “greater than” sign ( > ), indicating hierarchy: Parent Category > Subcategory.

Other options include arrows or slashes ( / ). Choose based on your design and the type of breadcrumbs you’re using.

4. Use Proper Sizes and Spacing

Make sure there’s enough space between breadcrumb levels so they’re easy to click. At the same time, breadcrumbs should be less visually dominant than the main navigation menu.

5. Keep Breadcrumbs Subtle

Breadcrumbs shouldn’t be the first thing that catches the user’s eye. If they’re too prominent, they can draw attention away from the main content.

Here’s how Amazon displays breadcrumbs – visible but not distracting:

Breadcrumbs example on a product page

6. Breadcrumbs on Mobile Are Optional

If you feel you need breadcrumbs to navigate your mobile site, the real problem might be the site structure itself. Simplify your mobile navigation first.

That said, if you can add breadcrumbs on mobile without cluttering the interface, they probably won’t hurt.

How to Add Breadcrumbs in WordPress

There are several plugins that add breadcrumbs, but they may not always fit your theme or requirements. Here’s a custom PHP function that works without any plugin and supports:

  • Parent and child pages
  • Archive pages
  • Custom post types
  • Custom taxonomies

Add this code to your child theme’s functions.php file. Never edit the parent theme directly – your changes will be lost on the next update.

<?php
function custom_breadcrumbs() {
    $separator        = '&gt;';
    $breadcrumbs_id    = 'breadcrumbs';
    $breadcrumbs_class = 'breadcrumbs';
    $home_title       = 'Homepage';
    $custom_taxonomy  = 'product_cat';

    global $post, $wp_query;

    if ( ! is_front_page() ) {
        echo '<ul id="' . $breadcrumbs_id . '" class="' . $breadcrumbs_class . '">';
        echo '<li class="item-home"><a class="bread-link bread-home" href="' . get_home_url() . '" title="' . $home_title . '">' . $home_title . '</a></li>';
        echo '<li class="separator separator-home"> ' . $separator . '</li>';

        if ( is_archive() && ! is_tax() && ! is_category() && ! is_tag() ) {
            echo '<li class="item-current item-archive"><strong class="bread-current bread-archive">' . post_type_archive_title( $prefix, false ) . '</strong></li>';

        } else if ( is_archive() && is_tax() && ! is_category() && ! is_tag() ) {
            $post_type = get_post_type();
            if ( $post_type != 'post' ) {
                $post_type_object  = get_post_type_object( $post_type );
                $post_type_archive = get_post_type_archive_link( $post_type );
                echo '<li class="item-cat item-custom-post-type-' . $post_type . '"><a class="bread-cat bread-custom-post-type-' . $post_type . '" href="' . $post_type_archive . '" title="' . $post_type_object->labels->name . '">' . $post_type_object->labels->name . '</a></li>';
                echo '<li class="separator"> ' . $separator . '</li>';
            }
            $custom_tax_name = get_queried_object()->name;
            echo '<li class="item-current item-archive"><strong class="bread-current bread-archive">' . $custom_tax_name . '</strong></li>';

        } else if ( is_single() ) {
            $post_type = get_post_type();
            if ( $post_type != 'post' ) {
                $post_type_object  = get_post_type_object( $post_type );
                $post_type_archive = get_post_type_archive_link( $post_type );
                echo '<li class="item-cat item-custom-post-type-' . $post_type . '"><a class="bread-cat bread-custom-post-type-' . $post_type . '" href="' . $post_type_archive . '" title="' . $post_type_object->labels->name . '">' . $post_type_object->labels->name . '</a></li>';
                echo '<li class="separator"> ' . $separator . '</li>';
            }
            $category = get_the_category();
            if ( ! empty( $category ) ) {
                $last_category   = end( array_values( $category ) );
                $get_cat_parents = rtrim( get_category_parents( $last_category->term_id, true, ',' ), ',' );
                $cat_parents     = explode( ',', $get_cat_parents );
                $cat_display     = '';
                foreach ( $cat_parents as $parents ) {
                    $cat_display .= '<li class="item-cat">' . $parents . '</li>';
                    $cat_display .= '<li class="separator"> ' . $separator . '</li>';
                }
            }
            $taxonomy_exists = taxonomy_exists( $custom_taxonomy );
            if ( empty( $last_category ) && ! empty( $custom_taxonomy ) && $taxonomy_exists ) {
                $taxonomy_terms = get_the_terms( $post->ID, $custom_taxonomy );
                $cat_id         = $taxonomy_terms[0]->term_id;
                $cat_nicename   = $taxonomy_terms[0]->slug;
                $cat_link       = get_term_link( $taxonomy_terms[0]->term_id, $custom_taxonomy );
                $cat_name       = $taxonomy_terms[0]->name;
            }
            if ( ! empty( $last_category ) ) {
                echo $cat_display;
                echo '<li class="item-current item-' . $post->ID . '"><strong class="bread-current bread-' . $post->ID . '" title="' . get_the_title() . '">' . get_the_title() . '</strong></li>';
            } else if ( ! empty( $cat_id ) ) {
                echo '<li class="item-cat item-cat-' . $cat_id . ' item-cat-' . $cat_nicename . '"><a class="bread-cat bread-cat-' . $cat_id . ' bread-cat-' . $cat_nicename . '" href="' . $cat_link . '" title="' . $cat_name . '">' . $cat_name . '</a></li>';
                echo '<li class="separator"> ' . $separator . '</li>';
                echo '<li class="item-current item-' . $post->ID . '"><strong class="bread-current bread-' . $post->ID . '" title="' . get_the_title() . '">' . get_the_title() . '</strong></li>';
            } else {
                echo '<li class="item-current item-' . $post->ID . '"><strong class="bread-current bread-' . $post->ID . '" title="' . get_the_title() . '">' . get_the_title() . '</strong></li>';
            }

        } else if ( is_category() ) {
            echo '<li class="item-current item-cat"><strong class="bread-current bread-cat">' . single_cat_title( '', false ) . '</strong></li>';

        } else if ( is_page() ) {
            if ( $post->post_parent ) {
                $anc = get_post_ancestors( $post->ID );
                $anc = array_reverse( $anc );
                if ( ! isset( $parents ) ) {
                    $parents = null;
                }
                foreach ( $anc as $ancestor ) {
                    $parents .= '<li class="item-parent item-parent-' . $ancestor . '"><a class="bread-parent bread-parent-' . $ancestor . '" href="' . get_permalink( $ancestor ) . '" title="' . get_the_title( $ancestor ) . '">' . get_the_title( $ancestor ) . '</a></li>';
                    $parents .= '<li class="separator separator-' . $ancestor . '"> ' . $separator . '</li>';
                }
                echo $parents;
                echo '<li class="item-current item-' . $post->ID . '"><strong title="' . get_the_title() . '"> ' . get_the_title() . '</strong></li>';
            } else {
                echo '<li class="item-current item-' . $post->ID . '"><strong class="bread-current bread-' . $post->ID . '"> ' . get_the_title() . '</strong></li>';
            }

        } else if ( is_tag() ) {
            $term_id       = get_query_var( 'tag_id' );
            $taxonomy      = 'post_tag';
            $args          = 'include=' . $term_id;
            $terms         = get_terms( $taxonomy, $args );
            $get_term_id   = $terms[0]->term_id;
            $get_term_slug = $terms[0]->slug;
            $get_term_name = $terms[0]->name;
            echo '<li class="item-current item-tag-' . $get_term_id . ' item-tag-' . $get_term_slug . '"><strong class="bread-current bread-tag-' . $get_term_id . ' bread-tag-' . $get_term_slug . '">' . $get_term_name . '</strong></li>';

        } elseif ( is_day() ) {
            echo '<li class="item-year item-year-' . get_the_time( 'Y' ) . '"><a class="bread-year bread-year-' . get_the_time( 'Y' ) . '" href="' . get_year_link( get_the_time( 'Y' ) ) . '" title="' . get_the_time( 'Y' ) . '">' . get_the_time( 'Y' ) . ' Archive</a></li>';
            echo '<li class="separator separator-' . get_the_time( 'Y' ) . '"> ' . $separator . '</li>';
            echo '<li class="item-month item-month-' . get_the_time( 'm' ) . '"><a class="bread-month bread-month-' . get_the_time( 'm' ) . '" href="' . get_month_link( get_the_time( 'Y' ), get_the_time( 'm' ) ) . '" title="' . get_the_time( 'M' ) . '">' . get_the_time( 'M' ) . ' Archive</a></li>';
            echo '<li class="separator separator-' . get_the_time( 'm' ) . '"> ' . $separator . '</li>';
            echo '<li class="item-current item-' . get_the_time( 'j' ) . '"><strong class="bread-current bread-' . get_the_time( 'j' ) . '"> ' . get_the_time( 'jS' ) . ' ' . get_the_time( 'M' ) . ' Archive</strong></li>';

        } else if ( is_month() ) {
            echo '<li class="item-year item-year-' . get_the_time( 'Y' ) . '"><a class="bread-year bread-year-' . get_the_time( 'Y' ) . '" href="' . get_year_link( get_the_time( 'Y' ) ) . '" title="' . get_the_time( 'Y' ) . '">' . get_the_time( 'Y' ) . ' Archive</a></li>';
            echo '<li class="separator separator-' . get_the_time( 'Y' ) . '"> ' . $separator . '</li>';
            echo '<li class="item-month item-month-' . get_the_time( 'm' ) . '"><strong class="bread-month bread-month-' . get_the_time( 'm' ) . '" title="' . get_the_time( 'M' ) . '">' . get_the_time( 'M' ) . ' Archive</strong></li>';

        } else if ( is_year() ) {
            echo '<li class="item-current item-current-' . get_the_time( 'Y' ) . '"><strong class="bread-current bread-current-' . get_the_time( 'Y' ) . '" title="' . get_the_time( 'Y' ) . '">' . get_the_time( 'Y' ) . ' Archive</strong></li>';

        } else if ( is_author() ) {
            global $author;
            $userdata = get_userdata( $author );
            echo '<li class="item-current item-current-' . $userdata->user_nicename . '"><strong class="bread-current bread-current-' . $userdata->user_nicename . '" title="' . $userdata->display_name . '">' . 'Author: ' . $userdata->display_name . '</strong></li>';

        } else if ( get_query_var( 'paged' ) ) {
            echo '<li class="item-current item-current-' . get_query_var( 'paged' ) . '"><strong class="bread-current bread-current-' . get_query_var( 'paged' ) . '" title="Page ' . get_query_var( 'paged' ) . '">' . __( 'Page' ) . ' ' . get_query_var( 'paged' ) . '</strong></li>';

        } else if ( is_search() ) {
            echo '<li class="item-current item-current-' . get_search_query() . '"><strong class="bread-current bread-current-' . get_search_query() . '" title="Search results for: ' . get_search_query() . '">Search results for: ' . get_search_query() . '</strong></li>';

        } elseif ( is_404() ) {
            echo '<li>' . 'Error 404' . '</li>';
        }
        echo '</ul>';
    }
}

Line 6 sets the homepage label in the breadcrumbs – change it to match your site. Line 7 defines the custom taxonomy (e.g., product_cat for WooCommerce).

To call the function in your template, add this to single.php or header.php:

<?php custom_breadcrumbs(); ?>

Here’s some basic CSS to get you started:

#breadcrumbs {
    list-style: none;
    margin: 10px 0;
    overflow: hidden;
}

#breadcrumbs li {
    display: inline-block;
    vertical-align: middle;
    margin-right: 5px;
}

#breadcrumbs .separator {
    font-size: 18px;
    font-weight: 100;
    color: #ccc;
}

Since every WordPress installation and theme is different, you may need to adjust the code slightly. If you prefer not to work with code, use an SEO plugin like Yoast or Rank Math as described below.

Adding Breadcrumbs with Yoast SEO

Yoast has a built-in breadcrumb feature that works well out of the box. To enable it, go to Yoast SEO > Settings > Advanced, then navigate to the Breadcrumbs tab and enable the option “Enable breadcrumbs for your theme.”

Yoast provides a straightforward interface for customizing breadcrumb settings:

Adding Breadcrumbs with Yoast SEO

The plugin lets you choose which taxonomy to display in the breadcrumbs. This is useful when you have custom taxonomies for organizing content.

To display Yoast breadcrumbs in your theme, add this to single.php or header.php:

if ( function_exists( 'yoast_breadcrumb' ) ) {
    yoast_breadcrumb();
}

You can also use the shortcode [wpseo_breadcrumb] to display breadcrumbs anywhere in your content:

Savvy / Blog / SEO & GEO / How to add BreadCrumbs Navigation to a WordPress Site

Adding Breadcrumbs with Rank Math SEO

To add breadcrumbs with Rank Math, go to Rank Math SEO > General Settings > Breadcrumbs and enable the feature.

To display them in your theme, use this code:

if ( function_exists( 'rank_math_the_breadcrumbs' ) ) {
    rank_math_the_breadcrumbs();
}

You can also insert them using the shortcode:

[rank_math_breadcrumb]

Rank Math offers advanced control with filters – like removing breadcrumbs from the homepage, shortening titles, or adding tags.

Breadcrumbs and SEO

Proper breadcrumb implementation is an integral part of Technical SEO. Here are the key benefits:

Google Displays Breadcrumbs in Search Results

Breadcrumbs help both users and Google understand your site’s hierarchy. If you’ve implemented correct structured data or are using Yoast or Rank Math to embed breadcrumbs, Google may display them in search results.

This enhanced display highlights your link in search results and can lead to a higher Click-Through Rate (CTR).

Breadcrumbs Improve User Experience

Nobody likes being lost. Just as a person arriving at a new place looks for landmarks to orient themselves, users landing on your site need context.

Breadcrumbs provide instant orientation. They’re familiar to everyone and enable navigation without wasting thought or time searching for a way around.

Breadcrumbs Reduce Bounce Rate

Most visitors don’t enter your site through the homepage. They arrive via organic search, making every page a potential entry point.

Breadcrumbs give those visitors a simple way to explore other sections of your site. This naturally reduces your bounce rate by providing an easy alternative to hitting the back button.

FAQs

Common questions about WordPress breadcrumbs:

Do breadcrumbs directly affect SEO rankings?
Breadcrumbs are not a direct ranking factor, but they contribute to SEO indirectly. They help Google understand your site structure, improve internal linking, and can appear in search results as enhanced snippets - all of which can improve your CTR and overall visibility.
Should I add breadcrumbs to every page on my site?
Breadcrumbs are most useful on sites with a clear hierarchy. Add them to posts, product pages, and category archives. The homepage typically doesn't need breadcrumbs since it's the top-level page. Single-level sites with no hierarchy don't benefit from them either.
What is the difference between Q&A breadcrumbs and FAQ breadcrumbs?
There are no "Q&A breadcrumbs" or "FAQ breadcrumbs." Breadcrumbs are a navigation element showing the page's position in the site hierarchy (e.g., Home > Category > Post). You may be thinking of breadcrumb types: location-based (most common), attribute-based (used in e-commerce for filtering), and path-based (showing the user's browsing history).
Do I need a plugin to add breadcrumbs to WordPress?
No. You can add breadcrumbs with a custom PHP function in your child theme's functions.php file, as shown in this guide. However, SEO plugins like Yoast SEO and Rank Math include built-in breadcrumb features that are easier to set up and automatically add structured data markup.
Should breadcrumbs include structured data?
Yes. Adding BreadcrumbList structured data (Schema.org markup) helps Google understand and display your breadcrumbs in search results. Both Yoast SEO and Rank Math automatically add this markup when you enable their breadcrumb features.
Can I use breadcrumbs with WooCommerce?
Yes. WooCommerce includes its own breadcrumb function, but you can also use Yoast SEO or Rank Math breadcrumbs instead. Both support WooCommerce's product_cat taxonomy. The custom PHP function in this guide also supports custom taxonomies like product_cat.

Summary

Breadcrumbs provide a simple, compact way for users to navigate your site and understand its structure. They benefit user experience, reduce bounce rate, and support SEO by helping Google display your page hierarchy in search results.

You can add breadcrumbs with a custom PHP function, or use the built-in features in Rank Math or Yoast SEO for a quicker setup that includes automatic structured data markup.

Join the Discussion
0 Comments  ]

Leave a Comment

To add code, use the buttons below. For instance, click the PHP button to insert PHP code within the shortcode. If you notice any typos, please let us know!

Savvy WordPress Development official logo