WordPress YoastSEO’s Breadcrumb RDF Valid HTML Fix

and published
WP YoastSEO Breadcrumb Fix

BYBE recently ran an online design competition and asked users to tell us what they liked or disliked about our website, one user was kind enough to tell us that they liked the site however they could see several problems in regards of HTML validation! Eek! Not something we want to hear after all we are a website design company and should be leading by example!

After reading the comment I wasted no time and started to investigate, using W3C’s HTML validators tools I discovered that most issues was a direct result of HTML5 code becoming deprecated and just goes to show that you should regularly audit your site for deprecated errors.

I generally find that the documentation at W3C is pretty solid and replacing deprecated code was a fairly easily task but one of the errors found was related directly to a WordPress plugin that I’m sure you’ve all heard of or used before, that being the ever so famous YoastSEO plugin.

The particular problem we had with YoastSEO’s plugin was to do with the breadcrumbs, so if you don’t use YoastSEO’s breadcrumb feature then this article is not for you. The problem with the rdf vocabulary breadcrumbs is it fails to validate due to invalid HTML markup, W3C reports the following errors and warnings:

Error: Attribute xmlns:v not allowed here. <span xmlns:v="http://rdf.data-vocabulary.org/#">
Warning: Attribute with the local name xmlns:v is not serializable as XML 1.0. <span xmlns:v="http://rdf.data-vocabulary.org/#">

Searching the internet I quickly found that we was not alone, in fact this issue was rather common. In a discussion thread on the official WordPress forums I found a good fix that simply uses an add_filter that triggers a PHP preg_replace.

The following code will fix the “Attribute xmlns:v not allowed here” breadcrumb errors and warnings:

add_filter ('wpseo_breadcrumb_output','bybe_crumb_v_fix');
function bybe_crumb_v_fix ($link_output) {
  $link_output = preg_replace(array('#<span xmlns:v="http://rdf.data-vocabulary.org/\#">#','#<span typeof="v:Breadcrumb"><a href="(.*?)" .*?'.'>(.*?)</a></span>#','#<span typeof="v:Breadcrumb">(.*?)</span>#','# property=".*?"#','#</span>$#'), array('','<span itemscope itemtype="http://data-vocabulary.org/Breadcrumb"><a href="$1" itemprop="url"><span itemprop="title">$2</span></a></span>','<span itemscope itemtype="http://data-vocabulary.org/Breadcrumb"><span itemprop="title">$1</span></span>','',''), $link_output);
  return $link_output;
}

Structured Data Testing Tool url: missing and required

breadcrumb url error

The fix works great apart from the fact that Google’s Structured Data Testing Tool now throws up the following error message:

url: missing and required

Further investigations lead me to believe that it was because the Yoast’s last breadcrumb doesn’t have a URL link, once I found this out finding a relevant fix was fairly straight forward, add the following code above the previous code:

add_filter( 'wpseo_breadcrumb_single_link', 'bybe_crumb_fix' , 10, 2 );
function bybe_crumb_fix( $output, $crumb ){
  if ( is_array( $crumb ) && $crumb !== array() ) {               
    if( strpos( $output, '<span class="breadcrumb_last"' ) !== false  ||   strpos( $output, '<strong class="breadcrumb_last"' ) !== false ) { 
      $output = '<a property="v:title" rel="v:url" href="'. $crumb['url']. '" >';
      $output.= $crumb['text'];
      $output.= '</a>';
    } else { $output .= "</span>"; }
  }
  return $output;
}

Similar problem? or just want to say hello then please use the comment fields below!

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

20 Responses to “WordPress YoastSEO’s Breadcrumb RDF Valid HTML Fix”

  1. Mike D (SEO Monster)

    Lovely article and fixed the issue straight away! Thanks Simon and BYBE!

    Reply
  2. Louis Woods

    Finally, a working fix and great instructions how to interment.

    Reply
  3. Where do I put this code in yoast seo plugin?

    Reply
    • Hi Shri, you don’t put anything in YoastSEO.

      Locate your functions.php with Appearance > Editor.

      Then copy and paste supplied code, if your not familiar within PHP and WordPress templates then I recommend that you make a backup of functions.php before editing anything, just as a precaution.

      Reply
      • Hi Simon,

        I have inputted your codes at the end line of function.php and rechecked using W3C HTML5 Validator but the problem still appear… Can you please advise on my issue? Thanks.

        Reply
  4. It is working great for my website. However, I still don’t understand why the Yoast team hasn’t fixed the error in the plugin by themselves.

    Reply
  5. I implemented your code on WP 4.5.2 and the first part of the code works as described and remove the HTML errors. But the 2nd part complete code brings the HTML errors back. Let me know if this make sense?

    Reply
  6. Tad Heigel

    That last snippet throws up all kinds of HTML and nesting errors when validating (no matter the order it is placed in).

    Reply
    • Will check this out later for you 🙂

      Reply
    • Same here the code makes the last breadcrumb a link but it throws many additional structural data items and URL still validating as error
      URL --> is not a known valid target type for the http://rdf.data-vocabulary.org/#url property.

      Reply
  7. Amar Ilindra

    Hai Simon,
    Thanks for the snippet. It worked like a charm. But I can not understand why Yoast is not keeping efforts to fix this issue? Do you think it is better to keep it since Yoast decided to not remove.

    Reply
  8. Hi! Thanks for the informative article. It helped us towards achieving W3C validation for our website. Unfortunately I experienced the same nesting issue as Robin Demey with the second block of PHP. I fixed it quite simply by adding a closing span tag to each crumb, excluding the last one.

    You can see this working in action on our website.

    Hopefully this will help others in the future 🙂

    Here is the second block with my change, for reference:

    add_filter( 'wpseo_breadcrumb_single_link', 'bybe_crumb_fix' , 10, 2 );
    function bybe_crumb_fix( $output, $crumb ){
      if ( is_array( $crumb ) && $crumb !== array() ) {               
        if( strpos( $output, '<span class="breadcrumb_last"' ) !== false  ||   strpos( $output, '<strong class="breadcrumb_last"' ) !== false ) { 
          $output = '<a property="v:title" rel="v:url" href="'. $crumb['url']. '" >';
          $output.= $crumb['text'];
          $output.= '</a>';
        } else { $output .= "</span>"; }
      }
      return $output;
    }
    Reply
  9. Thank you for your post. The filters you provided in this article fixed my issues with the Google AMP errors.

    I had one further error in case anyone has it and that was with W3 Total Cache, I had to install the AMP extension for W3 Total Cache. The google error was an invalid stylesheet.

    Reply