I am trying to auto generate a schema markup from a WordPress PHP loop. I am trying to create my markup from five latest post in my "hovedret" WordPress post category.
The schema markup I am trying to generate:
<script type="application/ld+json">
{
"@context":"https://schema.org",
"@type":"ItemList",
"itemListElement":[
{
"@type":"ListItem",
"position":1,
"url":"http://example.com/peanut-butter-cookies.html"
},
{
"@type":"ListItem",
"position":2,
"url":"http://example.com/triple-chocolate-chunk.html"
},
{
"@type":"ListItem",
"position":3,
"url":"http://example.com/snickerdoodles.html"
}
]
}
</script>
My code should loop through the latest five posts in "hovedret" category so I would have positions 1, 2, 3, 4, and 5. I am using get_the_permalink in order to fill in URL.
I am using wp_head hook in order to return my code in of my website. For some reason, the code breaks my site. I am not sure if I have constructed my while loop the right way or something else is wrong with my code? I have tried echo instead of return $string;
any clues on what I am missing ??
//SCHEMA MARKUP
function tt_hook_schema_new()
{
if ( is_category() )
{
$post_per_page = 5;
$the_query = new WP_Query( array( 'category_name' => 'hovedret', 'posts_per_page' => $post_per_page ) );
if ( $the_query->have_posts() )
{
$string .= '<script type="application/ld+json">
{
"@context":"https://schema.org",
"@type":"ItemList",
"itemListElement":[';
$counter = 0;
while ( $the_query->have_posts() )
{
$counter = $counter + 1;
$string .= '{';
$string .= '"@type":"ListItem",';
$string .= '"position":' . $counter;
$string .= '"url":"' . get_the_permalink() . '"';
$string .= '}';
if($counter != $post_per_page)
{
$string .= ',';
}
}
$string .= ']
}
</script>';
return $string;
/* Restore original Post Data */
wp_reset_postdata();
}
}
}
add_action('wp_head', 'tt_hook_schema_new');
There is one syntax error:
$string .= '<script type="application/ld+json">
should become
$string = '<script type="application/ld+json">
(removing the dot, since $string
wasn't defined before).
And you run into an infinite loop, since you never get the next post. It should be:
while ( $the_query->have_posts() ) {
$the_query->the_post();
// ...
}
And you still have to echo
the contents.
Edit: I fixed some more mistakes and here is a corrected version (look at the comments for the changes):
function tt_hook_schema_new() {
if ( is_category() ) {
$post_per_page = 5;
$the_query = new WP_Query(
array(
'category_name' => 'hovedret',
'posts_per_page' => $post_per_page,
)
);
if ( $the_query->have_posts() ) {
// Here was a `.` too much.
$string = '<script type="application/ld+json">
{
"@context":"https://schema.org",
"@type":"ItemList",
"itemListElement":[';
$counter = 0;
while ( $the_query->have_posts() ) {
// This line was missing.
$the_query->the_post();
$counter++;
$string .= '{';
$string .= '"@type":"ListItem",';
// There was a missing comma.
$string .= '"position":' . $counter . ',';
$string .= '"url":"' . get_the_permalink() . '"';
$string .= '}';
// Having less then `$post_per_page` would still have the last comma.
if ( $counter < $the_query->found_posts ) {
$string .= ',';
}
}
$string .= ']
}
</script>';
// Echoing stuff without escaping can be insecure!
echo $string;
}
// You should reset postdata outside the `if` statement.
/* Restore original Post Data */
wp_reset_postdata();
}
}
add_action( 'wp_head', 'tt_hook_schema_new' );