woocommerce breadcrumb missing shop link

I was debugging this and unfortunatelly Woocommerce (ver. 2.3.8) doesn't use any hooks to directly adjust the breadcrumbs array. So if you want to modify the breadcrumbs shown without changing the permalinks structure, best is to copy the breadcrumbs template file from plugin ( /woocommerce/templates/global/breadcrumb.php) into your theme ( /theme_name/woocommerce/global/ ) and there add the code to include the link before the output loop starts. I only do it for product category, tag and detail but you can add other conditionals if you like.

<?php
/**
 * Shop breadcrumb
 *
 * @author      WooThemes
 * @package     WooCommerce/Templates
 * @version     2.3.0
 * @see         woocommerce_breadcrumb()
 */

if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

if ( $breadcrumb ) {

    // add shop home url to breadcrumbs
    if( is_product_category() || is_product_tag() || is_product() ) {
        $shop_page_id = wc_get_page_id( 'shop' );
        $shop_home_arr = array( get_the_title($shop_page_id), get_permalink($shop_page_id));

        // insert to breadcrumbs array on second position
        array_splice($breadcrumb, 1, 0, array($shop_home_arr));
    }

    echo $wrap_before;

    foreach ( $breadcrumb as $key => $crumb ) {

        echo $before;

        if ( ! empty( $crumb[1] ) && sizeof( $breadcrumb ) !== $key + 1 ) {
            echo '<a href="' . esc_url( $crumb[1] ) . '">' . esc_html( $crumb[0] ) . '</a>';
        } else {
            echo esc_html( $crumb[0] );
        }

        echo $after;

        if ( sizeof( $breadcrumb ) !== $key + 1 ) {
            echo $delimiter;
        }
    }
    echo $wrap_after;
}

For anyone who stumbles on this in 2019, there is a much easier way to add an item after the "Home" breadcrumb, if you don't want to change your permalinks or edit theme files. This may not be a perfect solution, but it worked for me.

The WC_Breadcrumb class filters the breadcrumbs before it returns them, and we can hook in and modify the array. The $crumbs array is just an array of [ [title, url], [title, url] ]

add_filter( 'woocommerce_get_breadcrumb', function($crumbs, $Breadcrumb){
        $shop_page_id = wc_get_page_id('shop'); //Get the shop page ID
        if($shop_page_id > 0 && !is_shop()) { //Check we got an ID (shop page is set). Added check for is_shop to prevent Home / Shop / Shop as suggested in comments
            $new_breadcrumb = [
                _x( 'Shop', 'breadcrumb', 'woocommerce' ), //Title
                get_permalink(wc_get_page_id('shop')) // URL
            ];
            array_splice($crumbs, 1, 0, [$new_breadcrumb]); //Insert a new breadcrumb after the 'Home' crumb
        }
        return $crumbs;
    }, 10, 2 );

This can be done a lot easier. It is just necessary to change the permalinks settings accordingly - as mentioned on github at the issue 3145:

Meet this criteria:

// If permalinks contain the shop page in the URI prepend the breadcrumb with shop 
if (
  $shop_page_id
  && strstr( $permalinks['product_base'], '/' . $shop_page->post_name )
  && get_option( 'page_on_front' ) !== $shop_page_id
 ) {
   $prepend = $before 
     . '<a href="' . get_permalink( $shop_page ) . '">' 
     . $shop_page->post_title . '</a> ' 
     . $after . $delimiter;
 }

Otherwise its never prepended.

To apply this one has to go to:

→ WordPress Backend → Settings → Permalinks

And set the woocommerce permalinks settings to one of these:

  • Shop Base
  • Shop Base With Category
  • Custom Base

If the latter is used the slug »/shop/...« has to be prepended.

There is an issue 6584:

Warning: preg_match(): Unknown modifier 't' in wc-core-functions.php on line 533

Which for example occures if the »Custom Base« looks like this: »/shop/product/...«. There is a commit that fixed it, which is available in master, but not 2.2.8.

The slug part shop can be replaced by something else too, for example something localized.