SEO Forge automatically generates and outputs JSON-LD structured data for all singular pages. The schema system supports multiple types, a priority cascade, manual overrides, AI-powered detection, and extensibility via hooks.
Schema Output Priority (Cascade)
- Full manual schema (
_seoforge_manual_schemapost meta) — raw JSON-LD, output exactly as stored - Manual schema type (
_seoforge_schema_typepost meta) — generates schema from the chosen type - AI-generated schema (
_seoforge_ai_schemapost meta) — cached AI detection (PRO) - Auto-detected type — based on post type (
post= Article,product= Product, default = WebPage)
Additionally: BreadcrumbList schema on every page (except front page), Organization schema on the front page.
Supported Schema Types
$types = SEOFORGE_Schema::get_available_types();
// Returns: ['Article', 'BlogPosting', 'Product', 'FAQ', 'HowTo', 'Recipe',
// 'Event', 'Review', 'WebPage', 'VideoObject']Generating Schema Programmatically
$schema = SEOFORGE_Schema::instance();
// Generate schema for a specific type
$article_schema = $schema->generate( $post_id, 'Article' );
// Auto-detect the best schema type
$type = $schema->auto_detect_type( $post_id );
// Trigger AI detection (PRO only)
$ai_result = $schema->ai_detect_and_generate( $post_id, true );Manual Schema Override
$recipe_schema = [
'@context' => 'https://schema.org',
'@type' => 'Recipe',
'name' => 'Chocolate Cake',
'author' => [ '@type' => 'Person', 'name' => 'Jane Baker' ],
'prepTime' => 'PT15M',
'cookTime' => 'PT30M',
'recipeIngredient' => [ '2 cups flour', '1 cup sugar', '3/4 cup cocoa' ],
'recipeInstructions' => [
[ '@type' => 'HowToStep', 'text' => 'Preheat oven to 350F.' ],
[ '@type' => 'HowToStep', 'text' => 'Mix dry ingredients.' ],
],
];
update_post_meta( $post_id, '_seoforge_manual_schema', wp_json_encode( $recipe_schema ) );HowTo Schema — Steps Required
When the user manually selects HowTo in the Schema Builder (_seoforge_schema_type = 'HowTo'), SEO Forge needs at least one extractable step or it will skip emitting the schema entirely. Step extraction priority:
- Explicit
[seoforge_step title="..."]Body...[/seoforge_step]shortcodes inside the post body. - H2/H3 headings used as step names (fallback).
If neither produces a step, the block for HowTo is suppressed — Google Search Console flags HowTo schemas with empty step arrays as invalid, so SEO Forge degrades to no schema rather than ship a broken one. BreadcrumbList still renders normally.
// Custom HowTo via _seoforge_manual_schema (bypasses the step requirement
// — full manual JSON-LD ships as-is).
$howto_schema = [
'@context' => 'https://schema.org',
'@type' => 'HowTo',
'name' => 'How to brew espresso',
'step' => [
[ '@type' => 'HowToStep', 'name' => 'Grind beans', 'text' => 'Grind 18g of beans medium-fine.' ],
[ '@type' => 'HowToStep', 'name' => 'Tamp', 'text' => 'Tamp the puck evenly with 30lb of pressure.' ],
[ '@type' => 'HowToStep', 'name' => 'Pull', 'text' => 'Pull a 25-second shot.' ],
],
];
update_post_meta( $post_id, '_seoforge_manual_schema', wp_json_encode( $howto_schema ) );FAQ Schema from Content
SEO Forge auto-parses H2/H3 headings followed by paragraphs as FAQ Question/Answer pairs and emits an additional FAQPage JSON-LD block alongside the main Article schema. To trigger automatic detection, headings must:
- End with a question mark (
?or full-width?). - Be followed by a non-empty paragraph (the answer).
- There must be at least two Q/A pairs on the page — one heading-with-question is treated as a section title, not a FAQ.
<h3>What is SEO?</h3>
<p>SEO stands for Search Engine Optimization...</p>
<h3>How long does SEO take?</h3>
<p>Results typically appear within 3-6 months...</p>To opt out site-wide, hook the seoforge_auto_faq_schema filter and return null (or an array with empty mainEntity):
add_filter( 'seoforge_auto_faq_schema', function ( $faq, $post_id ) {
if ( has_term( 'no-faq', 'category', $post_id ) ) {
return null;
}
return $faq;
}, 10, 2 );When the user manually picks FAQ in the Schema Builder (_seoforge_schema_type = 'FAQ'), SEO Forge falls back to a more permissive parser that treats every H2/H3 + paragraph pair as Q/A regardless of question marks — useful for long-form FAQ pages where authors didn’t add ? to every heading.
Removing or Replacing Schema Output
add_action( 'init', function () {
if ( ! class_exists( 'SEOFORGE_Schema' ) ) {
return;
}
remove_action( 'wp_head', [ SEOFORGE_Schema::instance(), 'output_schema' ], 5 );
}, 20 );—