Skip to content

BlogPosting JSON-LD calls the_content() which duplicates the post content #5

Description

@zerosonesfun

In templates/sections/entry-post.php, the BlogPosting structured data includes:

"articleBody": "<?php the_content(); ?>"

the_content() echoes the rendered post HTML. It does not return a string suitable for embedding in JSON. Because this runs after the normal content block (which already calls the_content()), the full post body is output a second time which some plugins and other systems do not like. Once in the article, and again inside the JSON-LD script. The main issue is that the_content() could output characters that make the JSON invalid.

Adverse effects:

  1. Duplicate content — the post body renders twice (visible to users at least in code and definitely crawlers and confusing certain plugins).
  2. Broken JSON-LD — HTML/quotes in the body corrupt the script, so Google may ignore or flag the BlogPosting markup.
  3. SEO / rich-result risk — invalid or duplicate structured data can hurt eligibility for article rich results and look like thin/duplicate content.
  4. Side effects from filters — the_content runs a second time (shortcodes, embeds, analytics hooks), which can inflate scripts, fire tracking twice, or break layout.

Affected file:

templates/sections/entry-post.php (around the application/ld+json block)

Steps to reproduce:

  1. View a single blog post that has body content.
  2. View page source / inspect the DOM below the article.
  3. Observe the post content appearing again near the JSON-LD block (and/or broken JSON in the script tag).

Expected:

  1. Post content renders once including behind the scenes.
  2. JSON-LD is valid JSON.

Actual:

  1. Post content appears twice (not visibly but in the source).
  2. articleBody often produces invalid JSON (unescaped quotes, HTML tags, etc.).

Suggested fix:

Build the schema with non-echoing getters and wp_json_encode(), and avoid the_content() in the schema. Either omit articleBody, or use something like wp_strip_all_tags(get_the_content(null, false)) / get_post_field('post_content', …) if you still want a plain-text body field.

Example approach:

<script type="application/ld+json">
<?php
$schema = [
  '@context' => 'https://schema.org',
  '@type' => 'BlogPosting',
  'headline' => wp_strip_all_tags(get_the_title()),
  // ... other fields using get_* helpers ...
  'mainEntityOfPage' => get_permalink(),
];
echo wp_json_encode(array_filter($schema), JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
?>
</script>

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions