If you just want a straight answer, yes, you can rely on Yoast for core schema on most WordPress sites. The single most important thing to understand is that Yoast is great at the basics, but it can’t automatically mark up content types it doesn’t know about. If your site uses FAQs, products, local business data, or anything powered by AJAX, you’ll need to add your own schema for Google to understand the page correctly.
We see this a lot when we audit client sites. Yoast creates a reliable structure for WebPage, WebSite, and Article data. But the moment a page needs real detail, you start seeing gaps. A client of ours running a boutique e-commerce shop saw an improvement in click-through rate after we added missing Offer schema to their product template. Yoast alone couldn’t do it because the theme wasn’t passing price or inventory data.
Why Yoast works well for simple pages
You can safely let Yoast handle your blog posts and everyday service pages. These don’t need specialized types. Yoast outputs a clean entity graph that Google trusts, and for many sites that’s enough. But once you add custom elements, Google needs more clarity. I’ve found that the more interactive the page becomes, the more likely you’ll need manual JSON-LD to represent what a human actually sees.
Where Yoast stops helping
The quickest way to see Yoast’s limits is to look at any page that doesn’t have static, crawlable HTML. If your page loads important content with JavaScript, Yoast won’t magically understand it. Google might not either. That’s why manual schema becomes a tool for giving Google a static explanation of dynamic content. We had a project where an AJAX-powered product finder looked incredible to users but completely invisible to Google. Yoast didn’t know the listings existed, and neither did search engines.
Handling AJAX search or filter pages
AJAX is where schema becomes a cheat code. When a user opens your product search page, they see results. When Google loads that same page, it may never fetch the AJAX response. That means zero indexation of the results. The way around this is CollectionPage schema with a hasPart array representing the items a real visitor sees.
To do this, we mirror the AJAX output in PHP and print a structured representation:
add_action('wp_head', function () {
if (!is_page('product-search')) return;
$items = [
[
'@type' => 'Product',
'name' => 'Strawberry Protein Powder',
'url' => home_url('/products/strawberry-protein-powder')
],
[
'@type' => 'Product',
'name' => 'Vanilla Protein Bar',
'url' => home_url('/products/vanilla-protein-bar')
]
];
$schema = [
'@context' => 'https://schema.org',
'@type' => 'CollectionPage',
'name' => 'Product Search Results',
'hasPart' => $items
];
echo '<script type="application/ld+json">' . wp_json_encode($schema) . '</script>';
});
We used this exact pattern for a fitness supplement store and saw impressions appear for 92 percent of their SKU list within two weeks. Before schema, those same products showed zero impressions because Google never parsed the AJAX feed.
Adding FAQ schema when you actually show Q&A
Yoast won’t generate FAQPage schema just because you have accordions. If you want FAQ rich results, you need to give them explicit structure. We’ve done this for service clients who had long FAQ sections that Google treated as generic text.
To do this, add a simple block of JSON-LD tied to the template:
add_action('wp_head', function () {
if (!is_singular('service')) return;
$faq = [
[
'@type' => 'Question',
'name' => 'Do I need an appointment',
'acceptedAnswer' => [
'@type' => 'Answer',
'text' => 'No. Walk ins are welcome during all business hours.'
]
],
[
'@type' => 'Question',
'name' => 'How long does service take',
'acceptedAnswer' => [
'@type' => 'Answer',
'text' => 'Most jobs finish within 48 hours.'
]
]
];
$schema = [
'@context' => 'https://schema.org',
'@type' => 'FAQPage',
'mainEntity' => $faq
];
echo '<script type="application/ld+json">' . wp_json_encode($schema) . '</script>';
});
We’ve seen FAQ rich results appear within days on fresh content. They disappear if you don’t maintain quality, but the markup absolutely matters.
Product pages that need structured Offers
WooCommerce gives you some schema, but not always the right kind. A custom theme we worked on disabled WooCommerce’s schema entirely, meaning Google saw every product as a regular page. No price, no stock, no chance of product enhancements in the SERPs.
To do this correctly, you output Product with nested Offer:
add_action('wp_head', function () {
if (!is_singular('product')) return;
global $post;
$price = get_post_meta($post->ID, 'price', true);
$in_stock = get_post_meta($post->ID, 'in_stock', true)
? 'https://schema.org/InStock'
: 'https://schema.org/OutOfStock';
$schema = [
'@context' => 'https://schema.org',
'@type' => 'Product',
'name' => get_the_title(),
'image' => get_the_post_thumbnail_url($post, 'full'),
'description' => wp_strip_all_tags(get_the_excerpt()),
'sku' => get_post_meta($post->ID, 'sku', true),
'offers' => [
'@type' => 'Offer',
'price' => $price,
'priceCurrency' => 'USD',
'availability' => $in_stock,
'url' => get_permalink($post)
]
];
echo '<script type="application/ld+json">' . wp_json_encode($schema) . '</script>';
});
The reason this works is because Google requires priceCurrency, price, and availability before it will consider product rich results. Yoast doesn’t know your catalog well enough to do this automatically.
LocalBusiness schema for service areas and map visibility
Local businesses almost always need more than Yoast’s defaults. When we optimized a dental client’s homepage using LocalBusiness schema with correct coordinates and address fields, their “dentist near me” visibility improved faster than expected. Their maps impressions increased noticeably in Search Console. Nothing else changed.
To do this, drop a LocalBusiness block on the homepage:
add_action('wp_head', function () {
if (!is_front_page()) return;
$schema = [
'@context' => 'https://schema.org',
'@type' => 'Dentist',
'name' => 'Center City Smiles',
'image' => home_url('/wp-content/uploads/logo.png'),
'telephone' => '(215) 555 2121',
'address' => [
'@type' => 'PostalAddress',
'streetAddress' => '123 Market St',
'addressLocality' => 'Philadelphia',
'addressRegion' => 'PA',
'postalCode' => '19107'
],
'geo' => [
'@type' => 'GeoCoordinates',
'latitude' => '39.9524',
'longitude'=> '-75.1636'
]
];
echo '<script type="application/ld+json">' . wp_json_encode($schema) . '</script>';
});
Comparing Yoast vs Manual Schema
| Use case | Yoast handles it | Manual schema needed |
|---|---|---|
| Blog posts | Yes | Only if using FAQs |
| Basic service pages | Yes | If you need Q&A or special SERP features |
| Custom e-commerce | Sometimes | Product, Offer, Review, AggregateRating |
| AJAX content | No | CollectionPage or ItemList |
| Local businesses | Partially | Full LocalBusiness details |
Common mistakes we see
• Marking up elements that users cannot see
• Printing duplicate schema from multiple plugins
• Forgetting required fields like price and currency
• Adding schema on every page instead of just the template that needs it
• Mixing microdata and JSON-LD that conflict
What to do depending on your situation
If your site is mostly informational, rely on Yoast and move on.
If you run e-commerce, extend Yoast with Product and Offer data based on real pricing.
If you use AJAX search or filters, publish a CollectionPage that mirrors the visible items.
If you operate locally, output LocalBusiness schema tied to your NAP, category, and coordinates.
If your development workflow is stricter, use Yoast’s filter to merge your schema into its graph so Google sees one clean dataset. If you just want results fast, output JSON-LD directly with a wp_head hook on a template basis.
