![]()
Breadcrumbs are the unsung heroes of website navigation. They tell users exactly where they are and tell Google how your site is structured. While the Yoast SEO plugin works wonders out of the box, every developer eventually runs into a scenario where the default hierarchy just doesn’t fit the client’s needs.
Perhaps you need to remove a specific category from the path, inject a static “Shop” link where one doesn’t exist, or rename a specific archive title.
In this guide, we aren’t using settings menus. We are going to dive into the code to customize Yoast Breadcrumbs programmatically. We will master the powerful wpseo_breadcrumb_links filter to take full control of your breadcrumb output.
Why You Should Customize Yoast Breadcrumbs Programmatically
Before we open our code editor, it is important to understand why we are doing this. Yoast offers some settings in the WordPress dashboard (under Yoast SEO > Settings > Advanced > Breadcrumbs), but these are global settings. They apply to everything or nothing.
When you customize Yoast Breadcrumbs using PHP filters, you gain surgical precision. You can:
- Improve User Experience (UX): Shorten overly long trails on mobile devices.
- Fix Logic Errors: sometimes Custom Post Types (CPTs) don’t inherit the parent structure you want.
- Boost SEO: manipulating the breadcrumb trail can influence how search engines display your site hierarchy in SERPs (Search Engine Results Pages).
Understanding the wpseo_breadcrumb_links Filter
The magic happens within the wpseo_breadcrumb_links filter. This filter exposes the breadcrumb “links” as an array just before Yoast generates the final HTML.
Each item in the array is an associative array containing:
- ‘
text‘: The label shown to the user. - ‘
url‘: The destination link. - ‘
id‘: The ID of the post/term (optional, but often present).
Here is the basic syntax we will be using in your child theme’s functions.php file or a code snippet plugin:
add_filter( 'wpseo_breadcrumb_links', 'pnet_custom_breadcrumb_logic' );
function pnet_custom_breadcrumb_logic( $links ) {
// We will manipulate the $links array here
return $links;
}
Let’s look at real-world scenarios where you need to customize Yoast Breadcrumbs.
Scenario 1: Removing a Specific Breadcrumb Item
A common annoyance for developers is when a “Blog” or “News” archive page appears in the breadcrumb trail for a custom post type where it doesn’t belong. Or perhaps you want to hide a specific parent category to keep the trail clean.
To customize Yoast Breadcrumbs by removing an item, we loop through the $links array, find the offending item, and unset it.
The Code:
/**
* Remove the "Uncategorized" category from Yoast Breadcrumbs
*/
add_filter( 'wpseo_breadcrumb_links', 'pnet_remove_specific_breadcrumb' );
function pnet_remove_specific_breadcrumb( $links ) {
// Loop through the breadcrumbs
foreach ( $links as $index => $link ) {
// Check if the text matches what we want to remove
// You could also check against $link['term_id'] for more precision
if ( isset( $link['text'] ) && 'Uncategorized' === $link['text'] ) {
unset( $links[$index] );
}
}
// Important: Re-index the array so keys are sequential again
return array_values( $links );
}
Developer Note: Always use array_values() after unsetting an item. If you don’t, the array keys will be non-sequential (e.g., 0, 2, 3), which can break the loop Yoast uses to render the HTML.
You might also like:
Scenario 2: Injecting a New Link (Middle of Path)
Sometimes, your site structure is virtual. You might have a Custom Post Type for “Projects” that technically belongs to a page called “Portfolio,” but they aren’t linked via WordPress page attributes. Yoast won’t see this connection automatically.
To fix this, we need to customize Yoast Breadcrumbs by injecting a static link into the array using PHP’s array_splice.
The Code:
/**
* Inject a "Portfolio" link before the single Project post title
*/
add_filter( 'wpseo_breadcrumb_links', 'pnet_inject_portfolio_crumb' );
function pnet_inject_portfolio_crumb( $links ) {
// Only run this on single 'project' post types
if ( is_singular( 'project' ) ) {
// Define the new breadcrumb item
$new_crumb = array(
array(
'text' => 'Portfolio',
'url' => home_url( '/portfolio/' ),
'allow_html' => true
)
);
// Usage: array_splice( input_array, offset, length, replacement )
// We insert at index 1 (after Home)
array_splice( $links, 1, 0, $new_crumb );
}
return $links;
}
In this snippet, array_splice allows us to push the new link exactly where we want it without deleting existing items. This is the cleanest method to customize Yoast Breadcrumbs when adding hierarchy.
Scenario 3: Renaming a Breadcrumb Text
Have you ever had a client say, “The page name is ‘Our Exclusive Services’, but can the breadcrumb just say ‘Services’?”
Changing the page title affects the H1 and the Title Tag. If you only want to change the navigation label, you need to filter the breadcrumb text specifically.
The Code:
/**
* Rename specific breadcrumb text to be shorter
*/
add_filter( 'wpseo_breadcrumb_links', 'pnet_rename_breadcrumb_text' );
function pnet_rename_breadcrumb_text( $links ) {
// Iterate through links
foreach ( $links as &$link ) {
if ( isset( $link['text'] ) && 'Our Exclusive Services' === $link['text'] ) {
$link['text'] = 'Services';
}
}
return $links;
}
Notice the usage of &$link in the foreach loop? The & creates a reference. This allows us to modify the $link directly inside the loop without creating a temporary array. It is a highly efficient way to customize Yoast Breadcrumbs.
Scenario 4: Changing the “Home” Link Text
By default, Yoast uses “Home” or your site name as the first link. While there is a setting for this in the plugin, sometimes you want to change it conditionally based on the language or the section of the site (e.g., changing “Home” to “Shop Root” when inside WooCommerce pages).
Here is how to target the very first item (index 0) to customize Yoast Breadcrumbs:
/**
* Change "Home" text to "Main" on specific pages
*/
add_filter( 'wpseo_breadcrumb_links', 'pnet_modify_home_link' );
function pnet_modify_home_link( $links ) {
// Check if the first item exists
if ( isset( $links[0] ) ) {
$links[0]['text'] = 'Start'; // Change the text label
// You could even change the URL if you wanted:
// $links[0]['url'] = 'https://google.com';
}
return $links;
}
Troubleshooting Common Issues
When you start writing code to customize Yoast Breadcrumbs, you might run into a few hiccups. Here is a quick checklist for debugging:
- Breadcrumbs Disappeared: You likely returned null or an empty array. Ensure your function always ends with return
$links;. - PHP Warning (Illegal String Offset): You might be trying to access
$links['text']directly without looping. Remember,$linksis a multidimensional array (an array of arrays). - Changes Not Visible: Clear your caching plugin (WP Rocket, W3 Total Cache) and your browser cache. Breadcrumbs are often cached heavily to save database queries.
Best Practices for Breadcrumb Customization
As we wrap up this guide, keep these best practices in mind when you customize Yoast Breadcrumbs:
- Keep it Short: Breadcrumbs are for navigation, not SEO keyword stuffing. Keep the ‘text’ concise.
- Use Conditional Tags: Always wrap your logic in WordPress conditional tags like
is_singular(),is_category(), oris_post_type_archive(). If you don’t, your custom code might break breadcrumbs on pages you didn’t intend to touch. - Backup: Before editing
functions.php, always back up your site or use a staging environment.
Conclusion
Taking control of your site’s structure distinguishes a professional WordPress developer from a casual user. By utilizing the wpseo_breadcrumb_links filter, you can customize Yoast Breadcrumbs to fit any complex requirement your clients throw at you.
Whether you are removing redundant categories, fixing parent-child relationships, or simply cleaning up the text, the power is now in your hands.
Do you have a unique breadcrumb setup you are trying to achieve? Let me know in the comments below, and I’ll help you troubleshoot the code!