When you add an AI schema generator to a site that already runs Yoast, Rank Math, or any SEO plugin, you get two competing JSON-LD outputs on the same page. Both describe the same Article — often with different data. Google and AI engines see conflict, lower trust, and may discard both. This guide covers detection, consolidation, and the @graph pattern that lets multiple sources coexist cleanly.
application/ld+json. Count occurrences. 3+ blocks warrants investigation.
curl -s https://example.com/blog/post-1 | \
python3 -c "
import json, re, sys
html = sys.stdin.read()
blocks = re.findall(r'<script type=\"application/ld\+json\">(.+?)</script>', html, re.DOTALL)
print(f'Found {len(blocks)} JSON-LD blocks')
types_seen = {}
for i, b in enumerate(blocks):
try:
data = json.loads(b)
items = data if isinstance(data, list) else [data]
for item in items:
graph = item.get('@graph', [item])
for entity in graph if isinstance(graph, list) else [graph]:
t = entity.get('@type', 'unknown')
types_seen.setdefault(str(t), []).append(i)
except:
pass
print('Entity types and which blocks contain them:')
for t, blocks_with in types_seen.items():
marker = ' DUPLICATE' if len(blocks_with) > 1 else ''
print(f' {t}: blocks {blocks_with}{marker}')
"
<!-- Yoast -->
<script type="application/ld+json">
{
"@context":"https://schema.org",
"@type":"Article",
"headline":"How to choose a CRM",
"author":{"@type":"Person","name":"Admin"}
}
</script>
<!-- AI generator -->
<script type="application/ld+json">
{
"@context":"https://schema.org",
"@type":"Article",
"headline":"How to choose a CRM",
"author":{"@type":"Person","name":"Jane Baker","jobTitle":"Sales Lead"}
}
</script>
<!-- Two Articles. Different authors. Google picks one or neither. -->
<!-- Different @type, same entity -->
{"@type":"BlogPosting", "headline":"..."} <!-- from plugin -->
{"@type":"Article", "headline":"..."} <!-- from generator -->
<!-- BlogPosting is subtype of Article. Two entities, one truth. -->
<!-- Plugin -->
{"@type":"Organization","name":"Acme Corp","logo":"https://example.com/logo.png"}
<!-- Generator (no logo) -->
{"@type":"Organization","name":"Acme"}
<!-- Two Organization entities. Trust signal weakens. -->
The simplest fix:
# Yoast: Settings → Search Appearance → Content Types → "Display this content type in search results" + schema toggle # Disable schema for the post type your AI generator handles # Rank Math: Titles & Meta → Post Types → choose type → "Schema Markup" → None # Then AI generator is the only source for that content type
Better for sites needing both site-wide schema (Organization, WebSite) AND content-specific schema:
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@graph": [
{
"@type": "Organization",
"@id": "https://example.com/#organization",
"name": "Acme Corp",
"url": "https://example.com",
"logo": {
"@type": "ImageObject",
"url": "https://example.com/logo.png"
}
},
{
"@type": "WebSite",
"@id": "https://example.com/#website",
"url": "https://example.com",
"name": "Acme",
"publisher": { "@id": "https://example.com/#organization" }
},
{
"@type": "Article",
"@id": "https://example.com/blog/post-1#article",
"headline": "How to choose a CRM",
"datePublished": "2026-01-15T09:00:00Z",
"author": {
"@type": "Person",
"@id": "https://example.com/authors/jane-baker#person",
"name": "Jane Baker"
},
"publisher": { "@id": "https://example.com/#organization" },
"isPartOf": { "@id": "https://example.com/#website" }
},
{
"@type": "BreadcrumbList",
"itemListElement": [
{ "@type": "ListItem", "position": 1, "name": "Home", "item": "https://example.com" },
{ "@type": "ListItem", "position": 2, "name": "Blog", "item": "https://example.com/blog" },
{ "@type": "ListItem", "position": 3, "name": "How to choose a CRM", "item": "https://example.com/blog/post-1" }
]
}
]
}
</script>
One block, multiple entities, explicit relationships via @id references. Both your plugin and AI generator should feed into building this single graph.
Plugin handles site entities, AI generator handles content entities. Each emits only its assigned types:
# Config [plugin] emit_types = ["Organization", "WebSite", "BreadcrumbList"] disable_types = ["Article", "BlogPosting", "Product", "Recipe", "HowTo", "FAQPage"] [ai_generator] emit_types = ["Article", "BlogPosting", "Product", "Recipe", "HowTo", "FAQPage"] disable_types = ["Organization", "WebSite", "BreadcrumbList"] # Each source emits only what it's assigned # Reference the other's entities by @id # Multiple JSON-LD blocks but no duplicate entities
// In your theme's functions.php
// Disable Yoast Article schema, keep its Organization
add_filter('wpseo_schema_graph_pieces', function($pieces, $context) {
return array_filter($pieces, function($piece) {
$class = get_class($piece);
// Remove Article-related pieces
return !preg_match('/Article|BlogPosting/i', $class);
});
}, 10, 2);
// Then your AI-generated schema is the only Article source