Video SEO (VideoObject JSON-LD) missing for videos in block-theme templates, template parts, and synced patterns
Summary
GoDAM outputs VideoObject JSON-LD schema correctly for godam/video blocks stored in a
post/page/CPT's own content, but emits nothing when the same block is placed in a
block-theme template, a template part (e.g. header/footer), or a synced pattern
(wp_block). Videos in those locations are valid, user-facing placements and should
produce structured data for search engines.
Type
Bug / Enhancement (SEO structured data coverage gap)
Component
godam core plugin — inc/classes/class-seo.php
Current behavior
The SEO class works in two decoupled phases:
- Save-time:
save_post parses the post's post_content for godam/video blocks and
caches the schema in that post's meta.
- Output-time:
wp_head reads the cached meta of the queried singular object and emits
the JSON-LD.
Because the schema is keyed to the queried post's own content, anything composed into the
page at render time is invisible to it.
| Content source |
Schema emitted? |
| Post / Page / CPT — video in content |
✅ Yes |
| Unsynced pattern (blocks copied into content) |
✅ Yes |
Block-theme template (single, page, query loop, etc.) |
❌ No |
| Template part (header / footer) |
❌ No |
Synced pattern / reusable block (wp_block) |
❌ No |
Steps to reproduce
- Activate a block theme (e.g. Twenty Twenty-Five).
- Add a
godam/video block to a synced pattern, and insert that pattern into a page.
(Or: add a godam/video to the footer template part in the Site Editor.)
- Visit the front end of a page that uses it and view source.
Expected: a <script type="application/ld+json"> VideoObject for the video.
Actual: no schema is output. (The referencing page's godam_video_seo_schema meta is
empty, because the block lives in the wp_block / wp_template_part post, not in the page.)
Root cause
- A synced pattern reference stores only
<!-- wp:block {"ref":N} /--> in content, so
parse_blocks() never sees the inner godam/video.
- Templates and template parts are separate post types (
wp_template, wp_template_part)
that are never the queried singular object whose cached meta is read.
Proposed fix
Add a render-time capture path alongside the existing cached path:
- Hook
render_block to collect godam/video schema from any block actually rendered
on the page (covers templates, template parts, and synced patterns).
- Emit the collected schema once in
wp_footer.
- Share a single schema-builder so both paths produce identical output and fire the same
godam_video_seo_schema filter.
Important ordering detail: in block themes the template renders (firing render_block)
before wp_head. De-duplication (so a video in post content isn't emitted in both
<head> and footer) must therefore happen at flush time (wp_footer), after both the
cached output and the render-time collector have finished — not at collect time.
The existing cached wp_head path is kept unchanged, since it also serves Elementor and
WPBakery content that render_block does not cover.
Scope
- In scope: singular views (post/page/CPT) — templates, template parts, synced patterns.
Compatibility
The godam-for-woo add-on's godam_video_seo_schemas handlers are safe on the footer
path: the VPG ItemList grouping no-ops on empty cached data, per-entry product enrichment
no-ops without product cache, and product-page suppression continues to prevent duplicates.
Acceptance criteria
Verification (tested)
Environment: WP block theme (Twenty Twenty-Five), PHP 8.2, godam + godam-for-woo active.
- Synced-pattern page → 1
VideoObject (footer). ✅
- Footer template-part video on a plain page → 1
VideoObject (footer). ✅
- CPT (
case-studies) with content video + footer-part video → 2 distinct, each once. ✅
- Post-content video → still 1
VideoObject in <head>, no footer duplicate. ✅
Performance
Added cost is one method call per rendered block; non-video blocks do a single blockName
check and return (is_singular() runs only for actual video blocks).
- ~54 ns per block; ~40–80
render_block calls on typical pages, so a heavy 500-block page
adds ~0.027 ms (< 0.01% of a 50–500 ms render).
- Zero new DB queries on pages without template/pattern videos; the
wp_footer callback
early-returns when nothing was collected.
Video SEO (VideoObject JSON-LD) missing for videos in block-theme templates, template parts, and synced patterns
Summary
GoDAM outputs
VideoObjectJSON-LD schema correctly forgodam/videoblocks stored in apost/page/CPT's own content, but emits nothing when the same block is placed in a
block-theme template, a template part (e.g. header/footer), or a synced pattern
(
wp_block). Videos in those locations are valid, user-facing placements and shouldproduce structured data for search engines.
Type
Bug / Enhancement (SEO structured data coverage gap)
Component
godamcore plugin —inc/classes/class-seo.phpCurrent behavior
The SEO class works in two decoupled phases:
save_postparses the post'spost_contentforgodam/videoblocks andcaches the schema in that post's meta.
wp_headreads the cached meta of the queried singular object and emitsthe JSON-LD.
Because the schema is keyed to the queried post's own content, anything composed into the
page at render time is invisible to it.
single,page, query loop, etc.)wp_block)Steps to reproduce
godam/videoblock to a synced pattern, and insert that pattern into a page.(Or: add a
godam/videoto the footer template part in the Site Editor.)Expected: a
<script type="application/ld+json">VideoObjectfor the video.Actual: no schema is output. (The referencing page's
godam_video_seo_schemameta isempty, because the block lives in the
wp_block/wp_template_partpost, not in the page.)Root cause
<!-- wp:block {"ref":N} /-->in content, soparse_blocks()never sees the innergodam/video.wp_template,wp_template_part)that are never the queried singular object whose cached meta is read.
Proposed fix
Add a render-time capture path alongside the existing cached path:
render_blockto collectgodam/videoschema from any block actually renderedon the page (covers templates, template parts, and synced patterns).
wp_footer.godam_video_seo_schemafilter.Important ordering detail: in block themes the template renders (firing
render_block)before
wp_head. De-duplication (so a video in post content isn't emitted in both<head>and footer) must therefore happen at flush time (wp_footer), after both thecached output and the render-time collector have finished — not at collect time.
The existing cached
wp_headpath is kept unchanged, since it also serves Elementor andWPBakery content that
render_blockdoes not cover.Scope
Compatibility
The
godam-for-wooadd-on'sgodam_video_seo_schemashandlers are safe on the footerpath: the VPG ItemList grouping no-ops on empty cached data, per-entry product enrichment
no-ops without product cache, and product-page suppression continues to prevent duplicates.
Acceptance criteria
VideoObject.VideoObject.video exactly once (no duplicates).
Verification (tested)
Environment: WP block theme (Twenty Twenty-Five), PHP 8.2,
godam+godam-for-wooactive.VideoObject(footer). ✅VideoObject(footer). ✅case-studies) with content video + footer-part video → 2 distinct, each once. ✅VideoObjectin<head>, no footer duplicate. ✅Performance
Added cost is one method call per rendered block; non-video blocks do a single
blockNamecheck and return (
is_singular()runs only for actual video blocks).render_blockcalls on typical pages, so a heavy 500-block pageadds ~0.027 ms (< 0.01% of a 50–500 ms render).
wp_footercallbackearly-returns when nothing was collected.