Rank Math Schema Customization Guide: Enhance Your SEO with Structured Data
Rank Math schema customization allows WordPress developers to fully control structured data output using PHP hooks and filters. In this complete technical guide, you will learn how to add, modify, and debug custom schema using real-world Rank Math JSON-LD code examples.

Rank Math already outputs schema automatically based on the type you select per post (Article, Product, etc.) under its Schema Markup settings and the per-post SEO meta box. What it doesn’t give you is a UI for anything beyond that default output — modifying a specific field, adding FAQ schema dynamically from custom fields, or injecting a type Rank Math doesn’t natively support. That’s what the rank_math/json_ld filter is for. All of the following goes in a small site-specific plugin (not functions.php, so it survives theme changes), hooked on init or loaded directly.
1️⃣ Modify Existing Schema Output (Main Hook)
This is the core filter to modify Rank Math JSON-LD:
add_filter( 'rank_math/json_ld', function( $data, $jsonld ) {
if ( is_singular() ) {
// Example: Modify Article headline
if ( isset( $data['Article'] ) ) {
$data['Article']['headline'] = get_the_title() . ' - Updated by WP Insightful';
}
}
return $data;
}, 99, 2 );2️⃣ Add Custom FAQ Schema (Dynamic From ACF / Custom Fields)
add_filter( 'rank_math/json_ld', function( $data ) {
if ( is_singular( 'post' ) ) {
$data['FAQPage'] = [
'@type' => 'FAQPage',
'mainEntity' => [
[
'@type' => 'Question',
'name' => 'What is Rank Math Schema?',
'acceptedAnswer' => [
'@type' => 'Answer',
'text' => 'Rank Math schema helps search engines understand your content better and generate rich snippets.',
],
],
[
'@type' => 'Question',
'name' => 'Can I customize schema in Rank Math?',
'acceptedAnswer' => [
'@type' => 'Answer',
'text' => 'Yes, you can fully customize Rank Math schema using PHP filters and JSON-LD hooks.',
],
],
],
];
}
return $data;
}, 99 );3️⃣ Add Custom Product Schema (WooCommerce / Custom Product Pages)
add_filter( 'rank_math/json_ld', function( $data ) {
if ( is_singular( 'product' ) ) {
global $product;
if ( ! $product ) return $data;
$data['Product'] = [
'@type' => 'Product',
'name' => $product->get_name(),
'image' => wp_get_attachment_url( $product->get_image_id() ),
'description' => wp_strip_all_tags( $product->get_description() ),
'sku' => $product->get_sku(),
'brand' => [
'@type' => 'Brand',
'name' => get_bloginfo('name')
],
'offers' => [
'@type' => 'Offer',
'url' => get_permalink(),
'priceCurrency' => get_woocommerce_currency(),
'price' => $product->get_price(),
'availability' => 'https://schema.org/' . ( $product->is_in_stock() ? 'InStock' : 'OutOfStock' )
]
];
}
return $data;
}, 99 );4️⃣ Add Custom Local Business / Location Schema
add_filter( 'rank_math/json_ld', function( $data ) {
if ( is_singular( 'location' ) ) {
$data['LocalBusiness'] = [
'@type' => 'LocalBusiness',
'name' => get_the_title(),
'image' => get_the_post_thumbnail_url(),
'url' => get_permalink(),
'telephone' => get_post_meta( get_the_ID(), 'phone', true ),
'address' => [
'@type' => 'PostalAddress',
'streetAddress' => get_post_meta( get_the_ID(), 'address', true ),
'addressLocality' => get_post_meta( get_the_ID(), 'city', true ),
'addressRegion' => get_post_meta( get_the_ID(), 'state', true ),
'postalCode' => get_post_meta( get_the_ID(), 'zip', true ),
'addressCountry' => 'US'
]
];
}
return $data;
}, 99 );5️⃣ Remove Default Rank Math Schema (When Needed)
add_filter( 'rank_math/json_ld', function( $data ) {
unset( $data['Article'] );
unset( $data['BreadcrumbList'] );
return $data;
}, 99 );6️⃣ Debug Schema Output (For Development)
add_filter( 'rank_math/json_ld', function( $data ) {
if ( current_user_can( 'manage_options' ) ) {
echo '<pre>';
print_r( $data );
echo '</pre>';
}
return $data;
}, 99 );7️⃣ Advanced: Inject Custom JSON-LD Manually
add_action( 'wp_head', function() {
if ( ! is_singular('post') ) return;
$schema = [
'@context' => 'https://schema.org',
'@type' => 'HowTo',
'name' => get_the_title(),
'description' => get_the_excerpt(),
];
echo '<script type="application/ld+json">' . wp_json_encode( $schema ) . '</script>';
});Note that wp_head injection like this runs independently of Rank Math’s own schema output — if Rank Math is already outputting a schema type for the same page (e.g. it’s already generating Article schema and you manually inject a second Article block), you’ll get duplicate or conflicting @type entries in the page’s JSON-LD graph, which validators will flag. Use this approach only for types Rank Math genuinely doesn’t cover, and check the rendered output (view source, search for application/ld+json) to confirm you don’t have two schema blocks competing.
Testing your schema
Two tools, used together: Google’s Rich Results Test tells you whether a page is eligible for Google’s supported rich-result types — useful, but it only checks the subset of schema Google currently surfaces as a visible feature. The Schema.org validator checks the full JSON-LD graph against the Schema.org vocabulary regardless of whether Google does anything visible with it, so it’ll catch structural errors the Rich Results Test won’t flag. Re-test the live URL after any change to the filter code, and check Search Console’s Enhancements reports after Google has had a chance to recrawl.
Common problems
- Duplicate schema from another SEO plugin. If you’re migrating from Yoast or another SEO plugin, check that its schema output is actually disabled — a leftover schema generator running alongside Rank Math is the most common source of duplicate/conflicting JSON-LD.
- Your filter runs but nothing changes. Check the priority argument on
add_filter()— if another filter (a plugin, a theme function) also hooksrank_math/json_ldat a higher priority and runs after yours, it can overwrite your changes. Use a high priority number (99, as in the examples above) to run late, or debug with the manual output check below. - Missing required fields for a type. Each Schema.org type has required and recommended properties (Article needs
headline,author,datePublished; Product needs anoffersblock, etc.) — the validators above will tell you exactly which ones are missing rather than guessing.
Structured data is verification-driven work — there’s no substitute for actually checking the rendered JSON-LD in the validators above after every change, rather than assuming the filter did what you expect.
If you want a quick read on how your current schema and on-page SEO setup looks before making changes, our free SEO Checker runs a combined check.


