Skip to content

SEO: fix FAQPage schema to read the question from saved <summary> markup#50093

Draft
angelablake wants to merge 1 commit into
trunkfrom
jetpack-1793-faq-schema-faqpage-never-emits-from-real-editor-saved
Draft

SEO: fix FAQPage schema to read the question from saved <summary> markup#50093
angelablake wants to merge 1 commit into
trunkfrom
jetpack-1793-faq-schema-faqpage-never-emits-from-real-editor-saved

Conversation

@angelablake

Copy link
Copy Markdown
Contributor

Fixes JETPACK-1793 (Linear).

Note

Stacked on #50080 (jetpack-1779-…, the @graph refactor that relocated the builder to class-post-schema-node.php). The base branch is set to that PR; please merge #50080 first, after which this will retarget to trunk. The diff here is the single FAQ-fix commit on top.

Proposed changes

FAQ schema (FAQPage) has never emitted from real, editor-saved content since it shipped (JETPACK-1680). The core/details block stores its summary as a source: "rich-text" attribute that lives in the saved <summary>…</summary> markup, not in the <!-- wp:details … --> comment. parse_blocks() doesn't resolve source-based attributes, so $block['attrs']['summary'] is always empty → the question is blank → every item is skipped → build_faq() returns null → no JSON-LD. This affects pages and posts equally.

  • Read the FAQ question from the block's inner HTML (<summary>) instead of the empty comment attribute.
  • Reduce both the question and the answer to decoded plain text via a shared to_plain_text() helper (tags stripped, HTML entities decoded, trimmed) — this also fixes latent entity double-encoding in the answer.
  • Replace the unit-test fixtures that baked the summary into the block comment (which Gutenberg never does) with realistic editor-saved markup, so the regression is genuinely covered. Added cases for rich-text/entity summaries, multiple Details blocks, and an empty <summary>.

Related product discussion/links

Does this pull request change what data or activity we track or use?

No. This only fixes the server-side JSON-LD output for content the author has already opted into (Schema type = FAQ).

Testing instructions

  • Check out this branch and ensure the SEO package autoloader is regenerated (cd projects/packages/seo && composer dump-autoload).
  • Run the package tests: composer phpunit in projects/packages/seo — all green (52 tests). The FAQ tests now use realistic markup; reverting just the src fix makes them fail, confirming they're real regression tests.

On a live site (with the new SEO experience + SEO Tools active):

  • Create a post and a page, each with a Details block (summary = a question, inner content = the answer).
  • Set Schema type = FAQ in the editor sidebar (or the Jetpack → SEO → Content tab); publish.
  • View source on the front end → a FAQPage node now appears in the @graph, with mainEntity[].name = the <summary> text and acceptedAnswer.text = the answer.
  • Before this fix, the same content emitted no FAQPage at all.
@github-actions

github-actions Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Are you an Automattician? Please test your changes on all WordPress.com environments to help mitigate accidental explosions.

  • To test on WoA, go to the Plugins menu on a WoA dev site. Click on the "Upload" button and follow the upgrade flow to be able to upload, install, and activate the Jetpack Beta plugin. Once the plugin is active, go to Jetpack > Jetpack Beta, select your plugin (Jetpack), and enable the jetpack-1793-faq-schema-faqpage-never-emits-from-real-editor-saved branch.
  • To test on Simple, run the following command on your sandbox:
bin/jetpack-downloader test jetpack jetpack-1793-faq-schema-faqpage-never-emits-from-real-editor-saved

Interested in more tips and information?

  • In your local development environment, use the jetpack rsync command to sync your changes to a WoA dev blog.
  • Read more about our development workflow here: PCYsg-eg0-p2
  • Figure out when your changes will be shipped to customers here: PCYsg-eg5-p2
@github-actions

Copy link
Copy Markdown
Contributor

Thank you for your PR!

When contributing to Jetpack, we have a few suggestions that can help us test and review your patch:

  • ✅ Include a description of your PR changes.
  • ✅ Add a "[Status]" label (In Progress, Needs Review, ...).
  • ✅ Add testing instructions.
  • ✅ Specify whether this PR includes any changes to data or privacy.
  • ✅ Add changelog entries to affected projects

This comment will be updated as you work on your PR and make changes. If you think that some of those checks are not needed for your PR, please explain why you think so. Thanks for cooperation 🤖


Follow this PR Review Process:

  1. Ensure all required checks appearing at the bottom of this PR are passing.
  2. Make sure to test your changes on all platforms that it applies to. You're responsible for the quality of the code you ship.
  3. You can use GitHub's Reviewers functionality to request a review.
  4. When it's reviewed and merged, you will be pinged in Slack to deploy the changes to WordPress.com simple once the build is done.

If you have questions about anything, reach out in #jetpack-developers for guidance!

@jp-launch-control

jp-launch-control Bot commented Jun 30, 2026

Copy link
Copy Markdown

Code Coverage Summary

Coverage changed in 1 file.

File Coverage Δ% Δ Uncovered
projects/packages/seo/src/class-post-schema-node.php 61/65 (93.85%) 0.51% 0 💚

Full summary · PHP report · JS report

Base automatically changed from jetpack-1779-schema-site-level-organization-node-multi-node-graph to trunk July 1, 2026 09:42
The core/details block stores its summary as a source:"rich-text" attribute,
which lives in the saved <summary>…</summary> markup, not in the
<!-- wp:details … --> comment. parse_blocks() does not resolve source-based
attributes, so $block['attrs']['summary'] is always empty for real,
editor-saved blocks — the question came back blank, every item was skipped,
and build_faq() returned null. FAQPage JSON-LD has therefore never emitted
from real editor content since it shipped (JETPACK-1680).

Read the summary from the block's inner HTML instead, reduced to decoded
plain text (shared with the answer extraction). Replace the unit-test
fixtures that baked the summary into the block comment — which Gutenberg
never does — with realistic editor-saved markup, so the regression is
actually covered.

JETPACK-1793

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@gmjuhasz gmjuhasz force-pushed the jetpack-1793-faq-schema-faqpage-never-emits-from-real-editor-saved branch from 57f3013 to 8c755e1 Compare July 1, 2026 10:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment