14. Schema JSON-LD | SEO Forge - Rank Higher with AI-Powered SEO
Download Log in

14. Schema JSON-LD

Developer Guide

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)

  1. Full manual schema (_seoforge_manual_schema post meta) — raw JSON-LD, output exactly as stored
  2. Manual schema type (_seoforge_schema_type post meta) — generates schema from the chosen type
  3. AI-generated schema (_seoforge_ai_schema post meta) — cached AI detection (PRO)
  4. 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

php
$types = SEOFORGE_Schema::get_available_types();
// Returns: ['Article', 'BlogPosting', 'Product', 'FAQ', 'HowTo', 'Recipe',
//           'Event', 'Review', 'WebPage', 'VideoObject']

Generating Schema Programmatically

php
$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

php
$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:

  1. Explicit [seoforge_step title="..."]Body...[/seoforge_step] shortcodes inside the post body.
  2. 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.

php
// 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.
html
<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):

php
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

php
add_action( 'init', function () {
    if ( ! class_exists( 'SEOFORGE_Schema' ) ) {
        return;
    }
    remove_action( 'wp_head', [ SEOFORGE_Schema::instance(), 'output_schema' ], 5 );
}, 20 );

Forge AI Assistant Online

Hi! I'm the SEO Forge AI assistant. Ask me anything about the plugin — setup, features, troubleshooting, or development.

Just now
Powered by Forge AI · Browse docs