Problems with Breadcrumb on custom-post-type

Hi experts

I have a WP project with pages and custom-post-types.

With the structured pages, the URL and breadcrumb display work perfectly:


And here is a screenshot from my custom-post-type “news”: The URL works perfect, but the breadcrumb is incorrect. The slug of the custom-post-type “news” should appear there so that you have the link to the archive, but it does not appear.


And when I’m in the archive-news.php the URL is correct, but the breadcrumb shows the title of the first post instead of the slug “news”.

Am I doing something wrong? Or does it not work (that would be very, very bad).?

Can someone help me please? Tank you.


Hi @HoWin,
I’ll try to take a look at this tomorrow. Is there any other info you can give?

Hi Bob
Thank you in advance :slight_smile:

Here are some information about how I set it up:

The breadcrumbs:

Pages: Breadcrumbs work fine (pages are structured)

Custom Post Type: Breadcrumbs don’t work there (CPT are not structured)

  • For displaying the custom-post-types I use: single-{slug}.php and achrive-{slug}.php.
  • For displaying the pages I use the template and linked posts (linked by a custom field).

Anything else you need?

I’m curious whether you can find the mistake or suggest a work-around.


Hi again,
You set-up for the breadcrumbs looks okay.
Can you show me how you registered the CPT?

Hi Bob

here are the screenshots:

btw: I tried both settings at hierarchical, and I couldn’t see a difference.


Okay - confessing to learning as I go. As it turns out, the archive isn’t actually a “parent” of any of the CPT posts. So, to have it included in your breadcrumbs you will have to put it in programmatically.

One way would be by creating a single-companies.php template for displaying the companies CPT posts. On that page you could add a block of php for out-puting the breadcrumbs. You can still use the PG_Helper::getBreadcrumbs to help you out.

Make sense?

Hi Bob
I do have a single-companies.php and an archive-companies.php. Both templates use the same breadcrumps from index.php.

It should work this way, but it doesn’t.

Can it be that this is a bug?

One thing is strange: The shown URL always is correct, only the breadcrumbs are wrong.

That’s why I think it could be a bug. What do you mean?

So, what is the hierarchy of the pages where it does work?

You mean that the URL in the browser bar is correct, but the breadcrumbs don’t show the part of the URL before the current post name?
Also, can you just look at what your breadcrumbs look like if you have a grandchild CPT post?

I tried to fix the problem with child-parent CPT, and the result is: correct breadcrumbs but wrong URL :frowning:

here is how it looks like with child-parent CPT:

and from the admin-panel:

On the other hand, child-parent PAGES are correct on both sides:

and here from the admin-panel:

FYI: I also tried to change the breadcrumb-settings from “Post parents” to “Post categories”, but this also wouldn’t solve the problem with CPT. (I thought I can use two different breadcrumbs, depending on the page-type)

?? any idea ??

I’m not quite sure what you changed. It looks the same to me.

I’m not surprised by the resulting behavior. If you look at the structure of your pages ‘Dienstleistungen’ is the parent that you get to from the home page. ‘Engineering’ is the child page you get to from ‘Dienstleistungen’. This is reflected in the breadcrumbs.

For your CPT, ‘Germany|Ober-Ramstadt’ is the parent you get to from the home page. ‘Child Company’ is the child page you get to from ‘Germany|Ober-Ramstadt’. This is also reflected in the breadcrumbs.

The breadcrumbs represent the path that you took through the website to get to where you are now. Since you did not have to navigate the archive, it isn’t included in the breadcrumbs.
Under the hood, this uses the WP function, ‘get_post_ancestors’, which will not return the archive page. You would have to modify the PHP block if you want this behavior.

    <?php $breadcrumbs = PG_Helper::getBreadcrumbs( 'parents', true, 'Home'); ?>
    <?php if( !empty( $breadcrumbs ) ) : ?>
        <div cms-breadcrumbs-home cms-breadcrumbs-separator="span">
            <p><?php _e( 'Breadcrumb', 'st2' ); ?></p>
                <?php for( $breadcrumbs_i = 0; $breadcrumbs_i < count( $breadcrumbs ); $breadcrumbs_i++) : ?>
                    <?php $breadcrumb = $breadcrumbs[ $breadcrumbs_i ]; ?>
                        <a href="<?php echo esc_url( $breadcrumb[ 'link' ] ); ?>"><?php echo $breadcrumb[ 'name' ]; ?></a>
//insert new code here
                    <?php if( $breadcrumbs_i < count( $breadcrumbs ) - 1 ) : ?>
                    <?php endif; ?>
                <?php endfor; ?>
    <?php endif; ?>

Here is the generated PHP when you use the WP Action in Pinegrow - yours may slightly differ based on your separator, plus I had a holder of ‘Breadcrumb’ that is in the code. The $breadcrumbs variable is populated with an array of all the post ancestors. I’ve indicated where to insert the code that I show below.

The easiest way I see to get the solution you want is to create a single-companies.php page for displaying the companies and to alter the PHP for the breadcrumbs on that page.

Let’s walk through the code a little. The first line populates the $breadcrumbs variable. Next, we set up an if loop to only display the breadcrumbs if they exist. Next is a <div> element for the breadcrumb output , followed by my placeholder in a <p>. Now we get to the main part.

The breadcrumbs are set up in an unordered list, <ul>. Nested in this is a for loop that goes through each of the elements of the $breadcrumbs array. Each element is outputted into a <li> element with a link(<a>) and name.

     <a href="<?php echo esc_url( $breadcrumb[ 'link' ] ); ?>"><?php echo $breadcrumb[ 'name' ]; ?></a>

That is then followed by an if statement to insert your separator if there is another item in the breadcrumb array.

So, what you want to do is inject a link between the home breadcrumb and the first page breadcrumb. We can do this by inserting an if statement along with another divider above the existing if statement.

<?php if($breadcrumbs_i === 0) : ?>
        <a href="<?php echo get_site_url() . '/companies/'; ?>"><?php echo 'Companies'; ?></a>
<?php endif; ?>

So, in the second line this code will add your span after the ‘Home’ breadcrumb. You will need to change this to reflect your separator. It then adds a link for the archive, assuming you have pretty permalinks the allows access to the archive at ‘’ .

Hope this helps,

Hi Bob

I see you gave me a workaround for my problem. I need to inject a link between home and first page. I’ll do this tomorrow and will inform you if this works.

But still, I think there is a bug in either WP or in PG. But if I can solve it (with your help) I’m happy with it.

I’ll keep you informed.


Edge cases.
WP dev is full of possibilities, there are situations where smart actions are not enough and where hand coding special functions is mandatory. (or using code snippets from a third party)

Hi Emmanuel

Yes, I know that, and there was nothing I complained.
The only reason for my question was: I wanted to know if I do something wrong or didn’t understand.

Many Thanks to @Bob, he helped me a lot.
And many thanks to Pnegrow, it’s a phantastic app I use since many years.

Best regards,

Hi @Bob

Thanks for your help. Your explanations helped me a lot.

For your information: I have now modified the whole thing so that it works equally for all single- {slug} .php and archive- {slug} .php.

I made the following modifications:

1.) First, I’ll define a couple of variables:

	$Separator = "&nbsp;>&nbsp;";
    $p_Url     = "/".get_post_type( get_the_ID() )."/";
    $p_Name    = get_post_type_object( get_post_type( get_the_ID() ) )->labels->name;

2.) This snippet of code goes to the place you suggested:

<?php if($breadcrumbs_i === 0) : ?>
    <span><?php echo $Separator; ?></span>
        <a href="<?php echo $p_Url; ?>"><?php echo $p_Name; ?></a>
    <?php if(is_archive()) $breadcrumbs_i = count( $breadcrumbs ); ?>
<?php endif; ?>

The whole thing now works great on all my CPT’s.

Important: with the CPT’s I now use the breadcrump definition above. For the standard posts and pages I use the standard breadcrumbs generated by the Pinegrow Smart-Action.

Thanks a lot Bob.

Kind regards,

1 Like

Thanks a lot to you for sharing your experience :slight_smile:

Hi Horst,
Glad it is working and you found a custom solution. Just out of curiosity, why the second if statement? Doesn’t it throw an error without it’s own endif;?

Hi Bob

The second if-statement is necessary for the archive-{slug}.php. This ends the breadcrumbs output. Otherwise the breadcrumb also shows the first entry of the displayed posts.

And no, this if-statement does not return an error message because that is the short form of an if-statement (one liner), and it doesn’t need an endif.


PS: and here how it looks now (compare it to my first screenshots) :slight_smile:

Just for information: The CPT is called “news”, but it’s german name is “Aktuelles”. That’s why the difference in URL and breadcrumb. If my boss doesn’t accept this I have to rename the CPT. But the main thing is that the breadcrumb now shows the same behavior on all CPT’s, posts and pages :wink:

The archive-news.php:


and here the single-news.php:

I knew you could leave off the endif for ternaries, didn’t realize you could also do it for straight if statements.

I have also had a breadcrumb issue with my website MyAssignmentHelp, please help me if any one knows this.