Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Missing breadcrumb text name within the "breadcrumb structured data schema" Bug Fix. #15800

Open
2 tasks done
mattu08 opened this issue Aug 5, 2020 · 22 comments
Open
2 tasks done
Labels
QA Unverified Not tested by the QA team severity: minor

Comments

@mattu08
Copy link

mattu08 commented Aug 5, 2020

  • I've read and understood the contribution guidelines.
  • I've searched for any related issues and avoided creating a duplicate issue.

Please give us a description of what happened.

Background:
This is the same issue that was patched in Ticket: #13616 and #13617

After Yoast has moved to “indexables that were introduced in 14.0.” referred in @Djennez comment here: #15652 (comment) the following patched code has been removed/is missing in 14.0. So currently sites that do not have the correct schema setup will display errors within breadcrumb schema displaying missing schema values this mainly happens on title and URL if they are empty.

How can we reproduce this behavior?

This can be reproduced if there are missing schema values. With no default value displayed.

Technical info

How to Fix:

To fix the problem of missing or empty values within the schema, I have managed to Patch the issue. By adding in the below error checking code, checking if the value is empty. A similar fix that was in: #13616

To fix this issue I have added the below code to: wordpress-seo –> src –> generators –> schema -> breadcrumb.php Line 97:

private function create_breadcrumb( $index, $breadcrumb ) {

Current plugin code below:

private function create_breadcrumb( $index, $breadcrumb ) {
		return [
			'@type'    => 'ListItem',
			'position' => ( $index + 1 ),
			'item'     => [
				'@type' => 'WebPage',
				'@id'   => $breadcrumb['url'],
				'url'   => $breadcrumb['url'], // For future proofing, we're trying to change the standard for this.
				'name'  => $this->helpers->schema->html->smart_strip_tags( $breadcrumb['text'] ),
			],
		];
	}

Fixed plugin code below:

        private function create_breadcrumb( $index, $breadcrumb ) {
		if ( empty( $breadcrumb['url'] ) ) {
			$breadcrumb['url'] = $this->context->canonical;
		}
		if ( empty( $breadcrumb['text'] ) ) {
			$breadcrumb['text'] = $this->helpers->schema->html->smart_strip_tags( $this->context->title );
		}
		
		return [
			'@type'    => 'ListItem',
			'position' => ( $index + 1 ),
			'item'     => [
				'@type' => 'WebPage',
				'@id'   => $breadcrumb['url'],
				'url'   => $breadcrumb['url'], // For future proofing, we're trying to change the standard for this.
				'name'  => $this->helpers->schema->html->smart_strip_tags( $breadcrumb['text'] ),
			],
		];
	}

Following code fix added to the above:

                if ( empty( $breadcrumb['url'] ) ) {
			$breadcrumb['url'] = $this->context->canonical;
		}
		if ( empty( $breadcrumb['text'] ) ) {
			$breadcrumb['text'] = $this->helpers->schema->html->smart_strip_tags( $this->context->title );
		}

As an example, from the below function "format_last_breadcrumb" within breadcrumb.php at Line 120, the error checking empty code has already been added, So i'm guessing this has been missed in the above function "create_breadcrumb".

private function format_last_breadcrumb( $breadcrumb ) {

Used versions

  • WordPress version: 5.4.2
  • Yoast SEO version: 14.7
@Djennez
Copy link
Member

Djennez commented Aug 6, 2020

@mattu08 I am not sure which problem this is fixing, it is breaking things (SEO wise) for my test setup, so I'm not sure this is likely to make it in.

Adding this check, and having a category without a title, will put the title of a post in place of the title of the category, when categories are part of the breadcrumb. So that is less favorable than no "name" entry I believe.

@mattu08
Copy link
Author

mattu08 commented Aug 6, 2020

Hi @Djennez

Sorry for not saying what the issue is, so I’m getting the same error again that I was getting from the old fix: #13616

This fix doesn't work anymore because it is missing after moving to indexables that were introduced in 14.0

Currently all sites are stating that they have unnamed values within the Yoast SEO generated schema. Here’s an example below:

Error2

Error

After the above suggested fix is added it is fixed like before 14.0, example below:

fixed

But that's a fair point you make about SEO being broken. After looking at the fix, I guess the question is why is there a second
item being created with blank values in the first place.

Although on your last point "Adding this check, and having a category without a title, will put the title of a post in place of the title of the category, when categories are part of the breadcrumb. So that is less favorable than no "name" entry I believe." After doing a code review, This is already being done on Line 112 this is also stated within the code comment:

* Provides a fallback for the URL and text:

And is in use? Under fallback. All the above is doing is adding in the same functionality that is already in use.

Here are the errors i'm getting, if this helps:

https://search.google.com/structured-data/testing-tool/u/0/#url=https%3A%2F%2Fwww.hiltonbaird.co.uk%2Fhilton-baird-group-reaches-20-year-milestone%2F

And the one that's fixed with the above code:

https://search.google.com/structured-data/testing-tool/u/0/#url=https%3A%2F%2Fwww.hiltonbairdaudit.co.uk%2Fgraham-bird-promoted-to-managing-director%2F

Last question: If this can't be fixed, is there a way I can override the missing blank schema and input the missing values myself?

Cheers 👍

@Djennez
Copy link
Member

Djennez commented Aug 10, 2020

The fallback you're describing is for the last item in the list, so the current page you are visiting. If you introduce this fallback for the parent items, they will still get the canonical / title of the current item. True, this would solve the error of an empty title / url, but it would solve it with the wrong information.

Suppose Home -> products -> shirts -> Brown T-shirt is the breadcrumb. And something causes the parent shirts to have no indexation data. That would produce Home -> products -> -> Brown T-shirt. But your fallback would make it Home -> products -> Brown T-shirt -> Brown T-shirt, which would arguably be more wrong (SEO-wise).

I am wondering why your parent pages don't have any indexation data. Have you tried re-indexing your site? (wp yoast index --reindex via WP-CLI, or using the Yoast test helper plugin)

@mattu08
Copy link
Author

mattu08 commented Aug 10, 2020

Yeah good points, probably not the best fix outcome. I have now tested after a reindex with the "Yoast test helper plugin" the problem is still there. It's slightly odd I must say. Do you know of anything else I could check?

@Djennez
Copy link
Member

Djennez commented Aug 21, 2020

@mattu08 for the breadcrumbs in the schema, you can hook into wpseo_schema_breadcrumblist and modify the breadcrumblist schema data in there. For the breadcrumb HTML output you may be able to hook into wpseo_breadcrumb_single_link to alter the needed item.

If you're able to pinpoint why some breadcrumb items in your site don't have the necessary data, that might be a bug that we can fix.

@mattu08
Copy link
Author

mattu08 commented Aug 24, 2020

@Djennez Thanks for the extra of information, I'll do some more digging/investigation. I'll leave this open for now just in case I manage to pinpoint anything. Thanks for your help. 👍

@mattu08
Copy link
Author

mattu08 commented Aug 26, 2020

@Djennez Do you have any helpful links to show how to use these hooks, I've found some information on wpseo_breadcrumb_single_link but can't find anything refereeing to "wpseo_schema_breadcrumblist". Any information on both of these would be greatly appreciated.

Thanks,

Matt

@Djennez
Copy link
Member

Djennez commented Aug 26, 2020

@mattu08 https://developer.yoast.com/features/schema/api/#change-a-graph-pieces-data should provide you with what you need. wpseo_schema_<piece> is a dynamic filter. breadcrumblist is the name of the breadcrumbs piece. You can send 2 arguments: the return value is $graph_piece and the second one is $context.

@mattu08
Copy link
Author

mattu08 commented Aug 27, 2020

@Djennez

Managed to Hook into the "breadcrumblist" as suggested and removed the blank array from the schema data this has fixed the issue. The schema now passes!

Before fix $data Array.

Array
(
    [@type] => BreadcrumbList
    [@id] => https://www.hiltonbairdaudit.co.uk/alan-baird-named-lecturer-of-the-year-again/#breadcrumb
    [itemListElement] => Array
        (
            [0] => Array
                (
                    [@type] => ListItem
                    [position] => 1
                    [item] => Array
                        (
                            [@type] => WebPage
                            [@id] => https://www.hiltonbairdaudit.co.uk/
                            [url] => https://www.hiltonbairdaudit.co.uk/
                            [name] => Home
                        )

                )

            [1] => Array
                (
                    [@type] => ListItem
                    [position] => 2
                    [item] => Array
                        (
                            [@type] => WebPage
                            [@id] => 
                            [url] => 
                            [name] => 
                        )

                )

            [2] => Array
                (
                    [@type] => ListItem
                    [position] => 3
                    [item] => Array
                        (
                            [@type] => WebPage
                            [@id] => https://www.hiltonbairdaudit.co.uk/alan-baird-named-lecturer-of-the-year-again/
                            [url] => https://www.hiltonbairdaudit.co.uk/alan-baird-named-lecturer-of-the-year-again/
                            [name] => Alan Baird named Lecturer of the Year again
                        )

                )

        )

)

After fix, $data Array:

Array
(
    [@type] => BreadcrumbList
    [@id] => https://www.hiltonbairdaudit.co.uk/alan-baird-named-lecturer-of-the-year-again/#breadcrumb
    [itemListElement] => Array
        (
            [0] => Array
                (
                    [@type] => ListItem
                    [position] => 1
                    [item] => Array
                        (
                            [@type] => WebPage
                            [@id] => https://www.hiltonbairdaudit.co.uk/
                            [url] => https://www.hiltonbairdaudit.co.uk/
                            [name] => Home
                        )

                )

            [1] => Array
                (
                    [@type] => ListItem
                    [position] => 2
                    [item] => Array
                        (
                            [@type] => WebPage
                            [@id] => https://www.hiltonbairdaudit.co.uk/alan-baird-named-lecturer-of-the-year-again/
                            [url] => https://www.hiltonbairdaudit.co.uk/alan-baird-named-lecturer-of-the-year-again/
                            [name] => Alan Baird named Lecturer of the Year again
                        )

                )

        )

)

Created the hook and removed the blank Array example test code below:

// Remove Blog/Success Stories blank Schema fix.
add_filter( 'wpseo_schema_breadcrumblist', 'unit_test_change_breadcrumblist' );

/**
 * Remove Blog/Success Stories Schema from BreadcrumbList Schema data.
 *
 * @param array $data Schema.org BreadcrumbList data array.
 *
 * @return array Schema.org BreadcrumbList data array.
 */

function unit_test_change_breadcrumblist( $data ) {

    // Check if name value is blank.
    if($data['itemListElement'][1]['item']['name'] == '') 
    {
        // Remove blank unused Schema data, reindex array.
        array_splice($data['itemListElement'], 1, 1);

        // Set the position value of now indexed array 1.
        $data['itemListElement'][1]['position'] = '2';
    }
    return $data;
}
// End.

Also a heads up for anyone doing this to get a PHP usable Array back use var_dump(); on the $data Array object. e.g. var_dump($data); Helps with testing/debugging.

Thanks for your help. 👍

@Djennez
Copy link
Member

Djennez commented Aug 28, 2020

Just FYI, we've recently began investigating when / why / how these empty schema pieces are returning as we're seeing it too often. So any information you can provide us about your setup would be useful. Like for example: what settings do you use in your settings -> reading page and what settings are used in SEO -> Search Appearance -> breadcrumbs?

@mattu08
Copy link
Author

mattu08 commented Aug 28, 2020

@Djennez I have happened to find out what was creating the blanks our end, this may be different for other people. The two sites with the issue, have had there /blog/ and /success-stories/ removed, For example: https://www.hiltonbairdaudit.co.uk/alan-baird-named-lecturer-of-the-year-again/ would be /blog/alan-baird-named-lecturer-of-the-year-again/

Example of one of our sites with the blog still present schema: https://search.google.com/structured-data/testing-tool#url=https%3A%2F%2Fwww.hiltonbairdcollections.co.uk%2Fhow-to-approach-a-difficult-late-paying-customer%2F

And here's the one we just fixed: https://search.google.com/structured-data/testing-tool#url=https%3A%2F%2Fwww.hiltonbairdaudit.co.uk%2Falan-baird-named-lecturer-of-the-year-again/

I can’t remember how the blog functionality was removed, but I’m guessing there is some left over code, there that Yoast still sees, to create the schema.

Before the above fix this was showing a blank entry, this was where the blog schema would of been the input. But because the blog is removed on this site it is not be present. Like mentioned above I think Yoast still hooks into the code somewhere, I guess the key is to try and figure out where it is doing that.

As the way of the plugin goes its just a default install. We don’t use anything else apart from Yoast for the SEO side of things. My guess is that this is not the issue anyway.

Hopefully the above helps in your investigation.

@Djennez Djennez added QA Unverified Not tested by the QA team severity: minor and removed wait for feedback labels Nov 9, 2020
@ytwala
Copy link

ytwala commented May 18, 2021

hello, recently I have updates my Yoast Plugin am also facing the same issue please help me to fix this my blog youtube to mp3

here is the screen shot
Screenshot at May 18 20-13-54

@Djennez
Copy link
Member

Djennez commented May 18, 2021

@mattu08 we changed some logic regarding breadcrumb names in 16.3, could you check if these possibly fixed your specific case?

@zmonteca
Copy link

zmonteca commented May 18, 2021

Broken for me. No matter what single I have, the final ListItem is broken and missing the item.name.

Running Yoast Premium Version 16.3

{
"@type":"ListItem",
"position":3,
"item":{
"@id":"https://site.com/portfolio/page-name/#webpage"
}
}

Also tried to override, but no avail.

/*
* Yoast SEO Breadcrumb overrides
* Fixing the ListItem schemas for CPTs because they are missing the 2nd level
* back to the archive pages
*/
function _s_override_yoast_breadcrumb_trail($links)
{
    global $post;

    if (!is_archive() && !is_home() && !is_front_page()) {
        $post_type = get_post_type();
        $post_type_data = get_post_type_object($post_type);
        $post_type_slug = $post_type_data->rewrite['slug'];
        $post_type_name = $post_type_data->label;

        $obj_id = get_queried_object_id();
        $current_url = get_permalink($obj_id);

        $links[0] = array('text' => 'Home', 'url' => get_site_url() . '/', 'allow_html' => 1, 'id' => get_option('page_on_front'));
        $links[1] = array('text' => $post_type_name, 'url' => get_site_url() . '/' . $post_type_slug . '/', 'allow_html' => 1);
        $links[2] = array('text' => $post->post_title, 'url' => $current_url, 'allow_html' => 1, 'id' => $post->ID);
    }

    if (is_singular('post')) {
        $links[1] = array('text' => 'Blog', 'url' => get_site_url() . '/blog/', 'allow_html' => 1);
    }

    return $links;
}
add_filter("wpseo_breadcrumb_links", "_s_override_yoast_breadcrumb_trail");

@Djennez
Copy link
Member

Djennez commented May 18, 2021

@zmonteca the last item in the breadcrumb list is supposed to only contain an @id since version 16.2. That is expected and correct behavior. Please see any other thread about that issue. This thread is regarding another property that is missing an item name.

@mattu08
Copy link
Author

mattu08 commented May 20, 2021

@Djennez I'll run a test now removing the code patch I added above and will get back to you, later on today.

@mattu08
Copy link
Author

mattu08 commented May 20, 2021

@Djennez Update: I have just ran a quick test, it fails after removing my code fix above. The blank values reappear again. So reverted back to my fix.

The only thing I will add I no longer need to set the position of the indexed array, this line within my code is no longer needed:
// Set the position value of now indexed array 1.
// $data['itemListElement'][1]['position'] = '2'; // Not needed since 12/01/2020

So something has been updated, don't really know if this will help you though.

@Djennez
Copy link
Member

Djennez commented May 21, 2021

Ok, thanks! I was hoping that the most recent release would've fixed a part of this, but this means that your case differs a lot from the code that we touched, unfortunately.

@mattu08
Copy link
Author

mattu08 commented May 21, 2021

@Djennez No problem at all and that's okay the current fix still works my end hooking into the breadcrumblist, so it's not much of an issue. Thanks for looking into this.

@davidwebca
Copy link

I came here searching for the solution because I just bumped into this and it seems like this filter is the cause which might be because it's one of the topmost results when you google "remove home breadcrumb yoast". Just to clarify my setup, I have a static front page and home (blog) on another page.

add_filter('wpseo_breadcrumb_links', function ($links){
    if (isset($links[0]['url']) && trim($links[0]['url'], '/') == trim(get_home_url(), '/')) {
        unset($links[0]);
    }
    return $links;  
}, 10, 1);

Somehow, this gets called at a weird timing during the schema generation and allows the returned $links being empty to bug out the rest of the pipeline. I personally solved by checking if I'm on the front page before doing anything.

add_filter('wpseo_breadcrumb_links', function ($links){
    if (!is_front_page() && isset($links[0]['url']) && trim($links[0]['url'], '/') == trim(get_home_url(), '/')) {
        unset($links[0]);
    }
    return $links;  
}, 10, 1);

Maybe adding a check if the array is empty later down in the pipeline on your end would help?

@yvesh
Copy link

yvesh commented Mar 6, 2022

Having the same issue with the current version of Yoast and it shows up only on three pages (out of thousands). There is nothing special about these.. Reindex didn't help, even made it worse with one more broken page.

@Djennez For reference: https://www.cmt.de/seminare/f-sharp-einstieg/ - Let me know if there's anything that could help debugging it.

@beseenontop
Copy link

Hello.

I have the same problem. Breadcrumbs are missing the name of the blog folder. So, for example, instead of seeing >home>blog>blogpost in breadcrumbs, I am seeing >home>blogpost.

This problem seems to have been out there for some time now. Does anyone have a permanent fix for this?

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
QA Unverified Not tested by the QA team severity: minor
Projects
None yet
Development

No branches or pull requests

7 participants