' . \"\\n\";\n}\nadd_action( 'wp_head', 'wp_breadcrumb_schema_jsonld' );","programmingLanguage":"PHP","codeRepository":"https://fysalyaqoob.com/snippets/breadcrumb-schema-wordpress","url":"https://fysalyaqoob.com/snippets/breadcrumb-schema-wordpress","datePublished":"2025-12-20","dateModified":"2025-12-20","keywords":"wordpress, breadcrumb, schema, seo, structured-data, json-ld, navigation, rich-snippets","about":{"@type":"Thing","name":"wordpress","description":"wordpress development"},"educationalLevel":"beginner","isAccessibleForFree":true,"license":"https://opensource.org/licenses/MIT"}
PHPwordpressbeginner

Breadcrumb Schema for WordPress Without Plugins

Add BreadcrumbList JSON-LD structured data to WordPress for enhanced Google search navigation

Faisal Yaqoob
#wordpress#breadcrumb#schema#seo#structured-data#json-ld#navigation#rich-snippets
Share this snippet:

Code

php
1/**
2 * Output BreadcrumbList JSON-LD Schema
3 * Automatically detects page type and builds breadcrumb trail
4 */
5function wp_breadcrumb_schema_jsonld() {
6 if ( is_front_page() ) {
7 return; // No breadcrumbs on homepage
8 }
9
10 $breadcrumbs = [];
11 $position = 1;
12
13 // Home is always the first item
14 $breadcrumbs[] = [
15 '@type' => 'ListItem',
16 'position' => $position++,
17 'name' => 'Home',
18 'item' => home_url( '/' ),
19 ];
20
21 if ( is_singular( 'post' ) ) {
22 // Blog > Category > Post
23 $categories = get_the_category();
24 if ( ! empty( $categories ) ) {
25 $primary_cat = $categories[0];
26 $breadcrumbs[] = [
27 '@type' => 'ListItem',
28 'position' => $position++,
29 'name' => $primary_cat->name,
30 'item' => get_category_link( $primary_cat->term_id ),
31 ];
32 }
33
34 $breadcrumbs[] = [
35 '@type' => 'ListItem',
36 'position' => $position++,
37 'name' => get_the_title(),
38 'item' => get_permalink(),
39 ];
40
41 } elseif ( is_page() ) {
42 // Handle nested pages (parent > child)
43 global $post;
44 $ancestors = array_reverse( get_post_ancestors( $post->ID ) );
45
46 foreach ( $ancestors as $ancestor_id ) {
47 $breadcrumbs[] = [
48 '@type' => 'ListItem',
49 'position' => $position++,
50 'name' => get_the_title( $ancestor_id ),
51 'item' => get_permalink( $ancestor_id ),
52 ];
53 }
54
55 $breadcrumbs[] = [
56 '@type' => 'ListItem',
57 'position' => $position++,
58 'name' => get_the_title(),
59 'item' => get_permalink(),
60 ];
61
62 } elseif ( is_category() ) {
63 $term = get_queried_object();
64 $breadcrumbs[] = [
65 '@type' => 'ListItem',
66 'position' => $position++,
67 'name' => $term->name,
68 'item' => get_category_link( $term->term_id ),
69 ];
70
71 } elseif ( is_tag() ) {
72 $term = get_queried_object();
73 $breadcrumbs[] = [
74 '@type' => 'ListItem',
75 'position' => $position++,
76 'name' => $term->name,
77 'item' => get_tag_link( $term->term_id ),
78 ];
79
80 } elseif ( is_singular() ) {
81 // Custom post types
82 $post_type = get_post_type_object( get_post_type() );
83 $breadcrumbs[] = [
84 '@type' => 'ListItem',
85 'position' => $position++,
86 'name' => $post_type->labels->name,
87 'item' => get_post_type_archive_link( get_post_type() ),
88 ];
89
90 $breadcrumbs[] = [
91 '@type' => 'ListItem',
92 'position' => $position++,
93 'name' => get_the_title(),
94 'item' => get_permalink(),
95 ];
96
97 } elseif ( is_search() ) {
98 $breadcrumbs[] = [
99 '@type' => 'ListItem',
100 'position' => $position++,
101 'name' => 'Search Results: ' . get_search_query(),
102 'item' => get_search_link( get_search_query() ),
103 ];
104
105 } elseif ( is_archive() ) {
106 $breadcrumbs[] = [
107 '@type' => 'ListItem',
108 'position' => $position++,
109 'name' => post_type_archive_title( '', false ) ?: 'Archives',
110 'item' => get_post_type_archive_link( get_post_type() ),
111 ];
112 }
113
114 if ( count( $breadcrumbs ) < 2 ) {
115 return; // Need at least 2 items for valid breadcrumbs
116 }
117
118 $schema = [
119 '@context' => 'https://schema.org',
120 '@type' => 'BreadcrumbList',
121 'itemListElement' => $breadcrumbs,
122 ];
123
124 echo '<script type="application/ld+json">' . wp_json_encode( $schema, JSON_UNESCAPED_SLASHES ) . '</script>' . "\n";
125}
126add_action( 'wp_head', 'wp_breadcrumb_schema_jsonld' );

Add BreadcrumbList structured data to your WordPress site so Google displays breadcrumb navigation trails in search results instead of plain URLs. This improves click-through rates and helps users understand your site structure.

Complete Breadcrumb Schema Generator

/**
 * Output BreadcrumbList JSON-LD Schema
 * Automatically detects page type and builds breadcrumb trail
 */
function wp_breadcrumb_schema_jsonld() {
    if ( is_front_page() ) {
        return; // No breadcrumbs on homepage
    }

    $breadcrumbs = [];
    $position    = 1;

    // Home is always the first item
    $breadcrumbs[] = [
        '@type'    => 'ListItem',
        'position' => $position++,
        'name'     => 'Home',
        'item'     => home_url( '/' ),
    ];

    if ( is_singular( 'post' ) ) {
        // Blog > Category > Post
        $categories = get_the_category();
        if ( ! empty( $categories ) ) {
            $primary_cat   = $categories[0];
            $breadcrumbs[] = [
                '@type'    => 'ListItem',
                'position' => $position++,
                'name'     => $primary_cat->name,
                'item'     => get_category_link( $primary_cat->term_id ),
            ];
        }

        $breadcrumbs[] = [
            '@type'    => 'ListItem',
            'position' => $position++,
            'name'     => get_the_title(),
            'item'     => get_permalink(),
        ];

    } elseif ( is_page() ) {
        // Handle nested pages (parent > child)
        global $post;
        $ancestors = array_reverse( get_post_ancestors( $post->ID ) );

        foreach ( $ancestors as $ancestor_id ) {
            $breadcrumbs[] = [
                '@type'    => 'ListItem',
                'position' => $position++,
                'name'     => get_the_title( $ancestor_id ),
                'item'     => get_permalink( $ancestor_id ),
            ];
        }

        $breadcrumbs[] = [
            '@type'    => 'ListItem',
            'position' => $position++,
            'name'     => get_the_title(),
            'item'     => get_permalink(),
        ];

    } elseif ( is_category() ) {
        $term          = get_queried_object();
        $breadcrumbs[] = [
            '@type'    => 'ListItem',
            'position' => $position++,
            'name'     => $term->name,
            'item'     => get_category_link( $term->term_id ),
        ];

    } elseif ( is_tag() ) {
        $term          = get_queried_object();
        $breadcrumbs[] = [
            '@type'    => 'ListItem',
            'position' => $position++,
            'name'     => $term->name,
            'item'     => get_tag_link( $term->term_id ),
        ];

    } elseif ( is_singular() ) {
        // Custom post types
        $post_type     = get_post_type_object( get_post_type() );
        $breadcrumbs[] = [
            '@type'    => 'ListItem',
            'position' => $position++,
            'name'     => $post_type->labels->name,
            'item'     => get_post_type_archive_link( get_post_type() ),
        ];

        $breadcrumbs[] = [
            '@type'    => 'ListItem',
            'position' => $position++,
            'name'     => get_the_title(),
            'item'     => get_permalink(),
        ];

    } elseif ( is_search() ) {
        $breadcrumbs[] = [
            '@type'    => 'ListItem',
            'position' => $position++,
            'name'     => 'Search Results: ' . get_search_query(),
            'item'     => get_search_link( get_search_query() ),
        ];

    } elseif ( is_archive() ) {
        $breadcrumbs[] = [
            '@type'    => 'ListItem',
            'position' => $position++,
            'name'     => post_type_archive_title( '', false ) ?: 'Archives',
            'item'     => get_post_type_archive_link( get_post_type() ),
        ];
    }

    if ( count( $breadcrumbs ) < 2 ) {
        return; // Need at least 2 items for valid breadcrumbs
    }

    $schema = [
        '@context'        => 'https://schema.org',
        '@type'           => 'BreadcrumbList',
        'itemListElement' => $breadcrumbs,
    ];

    echo '<script type="application/ld+json">' . wp_json_encode( $schema, JSON_UNESCAPED_SLASHES ) . '</script>' . "\n";
}
add_action( 'wp_head', 'wp_breadcrumb_schema_jsonld' );

Visual Breadcrumbs with Schema (Optional)

/**
 * Render visible breadcrumbs with matching HTML markup
 * Place in your theme template: <?php wp_render_breadcrumbs(); ?>
 */
function wp_render_breadcrumbs() {
    if ( is_front_page() ) {
        return;
    }

    echo '<nav class="breadcrumbs" aria-label="Breadcrumb">';
    echo '<ol class="breadcrumb-list">';

    echo '<li class="breadcrumb-item"><a href="' . esc_url( home_url( '/' ) ) . '">Home</a></li>';

    if ( is_singular( 'post' ) ) {
        $categories = get_the_category();
        if ( ! empty( $categories ) ) {
            $cat = $categories[0];
            echo '<li class="breadcrumb-item"><a href="' . esc_url( get_category_link( $cat->term_id ) ) . '">' . esc_html( $cat->name ) . '</a></li>';
        }
        echo '<li class="breadcrumb-item active" aria-current="page">' . esc_html( get_the_title() ) . '</li>';

    } elseif ( is_page() ) {
        global $post;
        $ancestors = array_reverse( get_post_ancestors( $post->ID ) );
        foreach ( $ancestors as $ancestor_id ) {
            echo '<li class="breadcrumb-item"><a href="' . esc_url( get_permalink( $ancestor_id ) ) . '">' . esc_html( get_the_title( $ancestor_id ) ) . '</a></li>';
        }
        echo '<li class="breadcrumb-item active" aria-current="page">' . esc_html( get_the_title() ) . '</li>';

    } elseif ( is_category() || is_tag() ) {
        $term = get_queried_object();
        echo '<li class="breadcrumb-item active" aria-current="page">' . esc_html( $term->name ) . '</li>';
    }

    echo '</ol></nav>';
}
.breadcrumbs {
  padding: 12px 0;
  font-size: 14px;
}

.breadcrumb-list {
  display: flex;
  flex-wrap: wrap;
  list-style: none;
  padding: 0;
  margin: 0;
  gap: 4px;
}

.breadcrumb-item + .breadcrumb-item::before {
  content: "›";
  margin-right: 4px;
  color: #6b7280;
}

.breadcrumb-item a {
  color: #2563eb;
  text-decoration: none;
}

.breadcrumb-item a:hover {
  text-decoration: underline;
}

.breadcrumb-item.active {
  color: #6b7280;
}

Best Practices

  • Always start with Home as the first breadcrumb item
  • Use primary category for posts with multiple categories
  • Include aria-label on nav element for accessibility
  • Match visible breadcrumbs with JSON-LD output
  • Test with Google Rich Results Test after deployment
  • Minimum 2 items required for valid BreadcrumbList schema

Features

  • Auto Page Detection: Handles posts, pages, categories, tags, CPTs, and archives
  • Nested Page Support: Follows WordPress page hierarchy
  • No Plugin Overhead: Pure PHP, lightweight implementation
  • Google Rich Results: Replaces plain URLs in search results with breadcrumb trails
  • Accessible: ARIA landmark and current page indication
  • Custom Post Types: Automatically supports any registered CPT

Related Snippets