diff --git a/docs/features/schema/schema-aggregator/api-reference.md b/docs/features/schema/schema-aggregator/api-reference.md new file mode 100644 index 00000000..50976070 --- /dev/null +++ b/docs/features/schema/schema-aggregator/api-reference.md @@ -0,0 +1,281 @@ +--- +id: api-reference +title: "Schema Aggregator: API Reference" +sidebar_label: API Reference +description: REST API endpoints and CLI commands for the Schema Aggregator feature. +--- + +This document provides a complete reference for the Schema Aggregator REST API endpoints and CLI commands. + +## REST API Endpoints + +### Get Schema for Post Type (JSON-L) + +Retrieve aggregated schema pieces for a specific post type in JSON-L format. + +**Endpoint:** +``` +GET /wp-json/yoast/v1/schema-aggregator/get-schema/{post_type}[/{page}] +``` + +**Parameters:** + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `post_type` | string | Yes | - | The post type to aggregate (e.g., `post`, `page`, `product`) | +| `page` | integer | No | 1 | Page number for pagination | +| `debug` | boolean | No | false | Disables cache when set to true (add `?debug=1` to URL) | + +**Pagination:** + +- Standard post types: 1000 items per page +- Big schema post types (e.g., `product`): 100 items per page + +You can customize pagination using filters: +- `wpseo_schema_aggregator_per_page`: Default items per page (1000) +- `wpseo_schema_aggregator_per_page_big`: Items per page for big schema post types (100) +- `wpseo_schema_aggregator_big_schema_post_types`: Define which post types use big pagination (default: `['product']`) + +**Response Format:** + +```json lines +{ + "@context": "https://schema.org", + "@type": "Article", + "@id": "https://example.com/hello-world/#article", + "headline": "Hello World", + "description": "A brief description of the article", + "articleBody": "The full article content...", + "keywords": ["hello", "world"], + "datePublished": "2024-01-15T10:30:00+00:00", + "dateModified": "2024-01-20T14:45:00+00:00", + "author": { + "@id": "https://example.com/#/schema/person/1" + }, + "publisher": { + "@id": "https://example.com/#organization" + } + +} +``` + +**Cache Headers:** + +Responses include cache control headers with a 5-minute (300 seconds) cache duration: + +``` +Cache-Control: max-age=300 +``` + +**Example Request (cURL):** + +```bash +# Get first page of posts +curl https://example.com/wp-json/yoast/v1/schema-aggregator/get-schema/post + +# Get second page +curl https://example.com/wp-json/yoast/v1/schema-aggregator/get-schema/post/2 + +# Debug mode (bypass cache) +curl "https://example.com/wp-json/yoast/v1/schema-aggregator/get-schema/post?debug=1" +``` + +--- + +### Get XML Schema Map + +Retrieve an XML sitemap of all available schema endpoints. + +**Endpoint:** +``` +GET /wp-json/yoast/v1/schema-aggregator/get-xml +``` + +**Parameters:** + +None. + +**Response Format:** + +```xml + + + + https://exampple.com/wp-json/yoast/v1/schema-aggregator/get-schema/page + 2026-01-01T14:03:56Z + daily + 0.8 + + + https://exampple.com/wp-json/yoast/v1/schema-aggregator/get-schema/post + 2026-01-01T14:03:56Z + daily + 0.8 + + +``` + + +**Cache Headers:** + +Responses include cache control headers matching the dynamic TTL strategy: +- Small sites (< 100 posts): 24 hours +- Medium sites (100-1000 posts): 12 hours +- Large sites (> 1000 posts): 6 hours + +**robots.txt Integration:** + +The schema map is automatically referenced in your site's `robots.txt`: + +``` +Sitemap: https://example.com/wp-json/yoast/v1/schema-aggregator/get-xml +``` + +**Example Request:** + +```bash +curl https://example.com/wp-json/yoast/v1/schema-aggregator/get-xml +``` + +**Customizing Post Types:** + +By default, the schema map includes all public post types. You can customize this using the `wpseo_schema_aggregator_post_types` filter: + +```php +add_filter( 'wpseo_schema_aggregator_post_types', 'customize_schema_post_types' ); + +/** + * Customize which post types appear in schema aggregator. + * + * @link https://developer.yoast.com/features/schema/schema-aggregator/api-reference/#get-schema-map-xml + * + * @param array $post_types Array of post type names. + * + * @return array Modified array of post type names. + */ +function customize_schema_post_types( $post_types ) { + // Only include posts and pages. + return [ 'post', 'page' ]; +} +``` + +--- + +## CLI Commands + +### Aggregate Site Schema + +Retrieve aggregated schema for a post type via WP-CLI. + +**Command:** +```bash +wp yoast aggregate_site_schema [--page=] +``` + +**Arguments:** + +| Argument | Type | Required | Default | Description | +|----------|------|----------|---------|-------------| +| `` | string | Yes | - | The post type to aggregate | +| `--page` | integer | No | 1 | Page number for pagination | + +**Output Format:** + +JSON-LD output is printed to stdout. + +**Example Usage:** + +```bash +# Get first page of posts +wp yoast aggregate_site_schema post + +# Get second page of products +wp yoast aggregate_site_schema product --page=2 +``` +--- + +### Clear Schema Cache + +Invalidate cached schema data for all or specific post types. + +**Command:** +```bash +wp yoast clear_schema_aggregator_cache [] +``` + +**Arguments:** + +| Argument | Type | Required | Default | Description | +|----------|------|----------|---------|-------------| +| `` | string | No | - | Optional post type to clear cache for | + +**Example Usage:** + +```bash +# Clear all schema caches +wp yoast clear_schema_aggregator_cache + +# Clear cache for posts only +wp yoast clear_schema_aggregator_cache post + +# Clear cache for products only +wp yoast clear_schema_aggregator_cache product +``` + + + +## Filtering and Enhancement + +### What Gets Filtered Out + +By default, the Schema Aggregator removes schema pieces in the following categories: + +- **Actions**: Potential actions (e.g., `SearchAction`, `ReadAction`) +- **Enumerations**: Type definitions (e.g., `ItemAvailability`, `OfferItemCondition`) +- **Meta**: Schema.org metadata (e.g., `DataType`, `Class`) +- **Website**: Site structure elements (e.g., `WebSite`, `WebPage` when not the main entity) + +This filtering reduces noise and focuses on meaningful content entities. + +**Customize filtering:** + +### What Gets Enhanced + +The Schema Aggregator enhances certain schema types with additional data: + +#### Article Enhancement + +Articles (and subtypes like `BlogPosting`, `NewsArticle`) are enhanced with: + +1. **articleBody**: Full post content (configurable max length, default: 5000 characters) +2. **description**: Post excerpt (configurable max length, default: 320 characters) +3. **keywords**: Post tags as keyword array + +**Configuration:** + +```php +// Adjust article body length. +add_filter( 'wpseo_article_enhance_config_max_article_body_length', function() { + return 10000; // Increase to 10,000 characters. +} ); + +// Adjust description length. +add_filter( 'wpseo_article_enhance_config_max_description_length', function() { + return 500; // Increase to 500 characters. +} ); + +// Disable article body enhancement. +add_filter( 'wpseo_article_enhance_config_add_article_body', '__return_false' ); + +// Disable description enhancement. +add_filter( 'wpseo_article_enhance_config_add_description', '__return_false' ); + +// Disable keywords enhancement. +add_filter( 'wpseo_article_enhance_config_add_keywords', '__return_false' ); +``` + +## See Also + +- [Overview](overview.md): Introduction to Schema Aggregator +- [Schema.org documentation](https://schema.org/) +- [JSON-LD specification](https://json-ld.org/) diff --git a/docs/features/schema/schema-aggregator/filters.md b/docs/features/schema/schema-aggregator/filters.md new file mode 100644 index 00000000..341e4ecc --- /dev/null +++ b/docs/features/schema/schema-aggregator/filters.md @@ -0,0 +1,808 @@ +--- +id: filters +title: "Schema Aggregator: Filters" +sidebar_label: Filters +description: WordPress filters to customize the Schema Aggregator feature behavior and output. +--- + +The Schema Aggregator provides 18 WordPress filters that allow you to customize its behavior, from cache configuration to content enhancement. This document provides a complete reference with practical examples for each filter. + +## Quick Reference + +| Filter | Category | Purpose | +|--------|----------|---------| +| [`wpseo_schema_aggregator_post_types`](#post-type-configuration) | Post Types | Control which post types to aggregate | +| [`wpseo_schema_aggregator_per_page`](#pagination-configuration) | Pagination | Set default items per page (1000) | +| [`wpseo_schema_aggregator_per_page_big`](#pagination-configuration) | Pagination | Set items per page for big schema post types (100) | +| [`wpseo_schema_aggregator_big_schema_post_types`](#pagination-configuration) | Pagination | Define which post types have large schema | +| [`wpseo_schema_aggregator_cache_enabled`](#cache-configuration) | Cache | Enable/disable caching | +| [`wpseo_schema_aggregator_cache_ttl`](#cache-configuration) | Cache | Set cache duration (dynamic by default) | +| [`wpseo_schema_aggregator_schemamap_changefreq`](#schema-map-configuration) | Schema Map | Set XML sitemap update frequency | +| [`wpseo_schema_aggregator_schemamap_priority`](#schema-map-configuration) | Schema Map | Set XML sitemap priority | +| [`wpseo_schema_aggregator_filtering_strategy`](#filtering-strategy) | Filtering | Implement custom filtering logic | +| [`wpseo_schema_aggregator_elements_context_map`](#elements-context-map) | Context Map | Override complete context map | +| [`wpseo_schema_aggregator_elements_context_map_{context}`](#wpseo_schema_aggregator_elements_context_map_context) | Context Map | Customize elements for specific context | +| [`wpseo_article_enhance_config_{key}`](#article-enhancement-configuration) | Article Enhancement | Configure article enhancement settings | +| [`wpseo_article_enhance_{enhancement}`](#article-enhancement-toggles) | Article Enhancement | Toggle specific article enhancements | +| [`wpseo_article_enhance_body_when_excerpt_exists`](#article-body-with-excerpt) | Article Enhancement | Include body when excerpt exists | +| [`wpseo_article_enhance_article_body_fallback`](#article-body-fallback) | Article Enhancement | Include body when no excerpt | +| [`wpseo_person_enhance_config_{key}`](#person-enhancement-configuration) | Person Enhancement | Configure person enhancement settings | +| [`wpseo_person_enhance_{enhancement}`](#person-enhancement-toggles) | Person Enhancement | Toggle specific person enhancements | +| [`wpseo_disable_robots_schemamap`](#robotstxt-integration) | Robots.txt | Disable schema map in robots.txt | + +## Post Type Configuration + +### wpseo_schema_aggregator_post_types + +Control which post types are included in the schema aggregation. + +**Parameters:** + +| Parameter | Type | Description | +|-----------|------|-------------| +| `$post_types` | array | Array of post type names to aggregate | + +**Default Value:** All public post types + +**Example: Include Only Specific Post Types** + +```php +add_filter( 'wpseo_schema_aggregator_post_types', 'limit_aggregated_post_types' ); + +/** + * Limit schema aggregation to posts and pages only. + * + * This is useful when you have custom post types that don't need + * structured data or when you want to improve performance. + * + * @link https://developer.yoast.com/features/schema/schema-aggregator/filters/#wpseo_schema_aggregator_post_types + * + * @param array $post_types Array of post type names. + * + * @return array Modified array of post type names. + */ +function limit_aggregated_post_types( $post_types ) { + // Only aggregate posts and pages. + return [ 'post', 'page' ]; +} +``` + +**Example: Exclude Specific Post Types** + +```php +add_filter( 'wpseo_schema_aggregator_post_types', 'exclude_custom_post_types' ); + +/** + * Exclude internal post types from schema aggregation. + * + * Remove post types that are used for internal purposes and + * should not appear in structured data output. + * + * @link https://developer.yoast.com/features/schema/schema-aggregator/filters/#wpseo_schema_aggregator_post_types + * + * @param array $post_types Array of post type names. + * + * @return array Modified array of post type names. + */ +function exclude_custom_post_types( $post_types ) { + // Remove internal post types. + $excluded = [ 'acf-field', 'acf-field-group', 'custom_css' ]; + + return array_diff( $post_types, $excluded ); +} +``` + +## Pagination Configuration + +The Schema Aggregator uses different pagination limits based on the size of schema pieces. Some post types (like WooCommerce products) generate large schema objects and need smaller page sizes. + +### wpseo_schema_aggregator_per_page + +Set the default number of items per page for schema aggregation. + +**Parameters:** + +| Parameter | Type | Description | +|-----------|------|-------------| +| `$per_page` | int | Number of items per page | + +**Default Value:** 1000 + +**Example:** + +```php +add_filter( 'wpseo_schema_aggregator_per_page', 'custom_default_per_page' ); + +/** + * Reduce default items per page for better performance. + * + * Lower pagination can help with memory limits on shared hosting + * or when dealing with post types that have moderate schema sizes. + * + * @link https://developer.yoast.com/features/schema/schema-aggregator/filters/#wpseo_schema_aggregator_per_page + * + * @param int $per_page Number of items per page. + * + * @return int Modified number of items per page. + */ +function custom_default_per_page( $per_page ) { + return 500; // Reduce from 1000 to 500. +} +``` + +### wpseo_schema_aggregator_per_page_big + +Set the number of items per page for post types with large schema pieces. + +**Parameters:** + +| Parameter | Type | Description | +|-----------|------|-------------| +| `$per_page_big` | int | Number of items per page for big schema post types | + +**Default Value:** 100 + +**Example:** + +```php +add_filter( 'wpseo_schema_aggregator_per_page_big', 'custom_big_per_page' ); + +/** + * Adjust pagination for post types with large schema. + * + * Increase or decrease based on your server's memory limits + * and the actual size of your schema pieces. + * + * @link https://developer.yoast.com/features/schema/schema-aggregator/filters/#wpseo_schema_aggregator_per_page_big + * + * @param int $per_page_big Number of items per page for big schema. + * + * @return int Modified number of items per page. + */ +function custom_big_per_page( $per_page_big ) { + return 50; // Reduce from 100 to 50 for very large schemas. +} +``` + +### wpseo_schema_aggregator_big_schema_post_types + +Define which post types should use the "big schema" pagination limit. + +**Parameters:** + +| Parameter | Type | Description | +|-----------|------|-------------| +| `$big_schema_post_types` | array | Array of post type names with large schema pieces | + +**Default Value:** `[ 'product' ]` + +**Example:** + +```php +add_filter( 'wpseo_schema_aggregator_big_schema_post_types', 'add_big_schema_post_types' ); + +/** + * Mark custom post types as having large schema pieces. + * + * Post types with extensive custom fields, galleries, or complex + * relationships should use the lower pagination limit. + * + * @link https://developer.yoast.com/features/schema/schema-aggregator/filters/#wpseo_schema_aggregator_big_schema_post_types + * + * @param array $big_schema_post_types Array of post type names. + * + * @return array Modified array of post type names. + */ +function add_big_schema_post_types( $big_schema_post_types ) { + // Add custom post types with large schemas. + $big_schema_post_types[] = 'property'; // Real estate listings. + $big_schema_post_types[] = 'event'; // Events with extensive details. + + return $big_schema_post_types; +} +``` + +## Cache Configuration + +The Schema Aggregator implements intelligent caching to balance performance and freshness. Cache automatically clears when posts are updated. + +### wpseo_schema_aggregator_cache_enabled + +Enable or disable the cache system entirely. + +**Parameters:** + +| Parameter | Type | Description | +|-----------|------|-------------| +| `$enabled` | bool | Whether caching is enabled | + +**Default Value:** `true` + +**Example:** + +```php +add_filter( 'wpseo_schema_aggregator_cache_enabled', 'disable_schema_cache_in_dev' ); + +/** + * Disable caching in development environment. + * + * This ensures you always see fresh data during development + * without needing to manually clear the cache. + * + * @link https://developer.yoast.com/features/schema/schema-aggregator/filters/#wpseo_schema_aggregator_cache_enabled + * + * @param bool $enabled Whether caching is enabled. + * + * @return bool Modified cache enabled status. + */ +function disable_schema_cache_in_dev( $enabled ) { + // Disable cache in local/staging environments. + if ( defined( 'WP_ENV' ) && in_array( WP_ENV, [ 'development', 'staging' ], true ) ) { + return false; + } + + return $enabled; +} +``` + +### wpseo_schema_aggregator_cache_ttl + +Set the cache time-to-live (TTL) in seconds. + +**Parameters:** + +| Parameter | Type | Description | +|-----------|------|-------------| +| `$ttl` | int | Cache duration in seconds | +| `$post_type` | string | The post type being cached | +| `$post_count` | int | Number of posts for this post type | + +**Default Value:** Dynamic based on site size: +- Small sites (< 100 posts): 86400 seconds (24 hours) +- Medium sites (100-1000 posts): 43200 seconds (12 hours) +- Large sites (> 1000 posts): 21600 seconds (6 hours) + +**Example: Fixed TTL** + +```php +add_filter( 'wpseo_schema_aggregator_cache_ttl', 'custom_cache_ttl' ); + +/** + * Set a fixed cache duration for all post types. + * + * Use this when you want consistent cache behavior regardless + * of site size or post type. + * + * @link https://developer.yoast.com/features/schema/schema-aggregator/filters/#wpseo_schema_aggregator_cache_ttl + * + * @param int $ttl Cache duration in seconds. + * @param string $post_type Post type being cached. + * @param int $post_count Number of posts. + * + * @return int Modified cache duration. + */ +function custom_cache_ttl( $ttl, $post_type, $post_count ) { + // Cache for 1 hour (3600 seconds) regardless of size. + return 3600; +} +``` + +**Example: Post Type Specific TTL** + +```php +add_filter( 'wpseo_schema_aggregator_cache_ttl', 'post_type_specific_ttl', 10, 3 ); + +/** + * Set different cache durations for different post types. + * + * Frequently updated content gets shorter cache times, + * while static content can be cached longer. + * + * @link https://developer.yoast.com/features/schema/schema-aggregator/filters/#wpseo_schema_aggregator_cache_ttl + * + * @param int $ttl Cache duration in seconds. + * @param string $post_type Post type being cached. + * @param int $post_count Number of posts. + * + * @return int Modified cache duration. + */ +function post_type_specific_ttl( $ttl, $post_type, $post_count ) { + $custom_ttls = [ + 'post' => 1800, // 30 minutes for frequently updated posts. + 'page' => 86400, // 24 hours for static pages. + 'product' => 3600, // 1 hour for product catalog. + ]; + + return $custom_ttls[ $post_type ] ?? $ttl; +} +``` + +## Schema Map Configuration + +The schema map is an XML sitemap that lists all available schema endpoints. It's automatically referenced in your site's `robots.txt`. + +### wpseo_schema_aggregator_schemamap_changefreq + +Set the change frequency for schema map entries. + +**Parameters:** + +| Parameter | Type | Description | +|-----------|------|-------------| +| `$changefreq` | string | Change frequency (always, hourly, daily, weekly, monthly, yearly, never) | + +**Default Value:** `'daily'` + +**Example:** + +```php +add_filter( 'wpseo_schema_aggregator_schemamap_changefreq', 'custom_schemamap_changefreq' ); + +/** + * Set schema map change frequency to weekly. + * + * Use this to indicate how often search engines should check + * for updated schema data. + * + * @link https://developer.yoast.com/features/schema/schema-aggregator/filters/#wpseo_schema_aggregator_schemamap_changefreq + * + * @param string $changefreq Change frequency value. + * + * @return string Modified change frequency. + */ +function custom_schemamap_changefreq( $changefreq ) { + return 'weekly'; // Change from daily to weekly. +} +``` + +### wpseo_schema_aggregator_schemamap_priority + +Set the priority value for schema map entries. + +**Parameters:** + +| Parameter | Type | Description | +|-----------|------|-------------| +| `$priority` | float | Priority value between 0.0 and 1.0 | + +**Default Value:** `0.8` + +**Example:** + +```php +add_filter( 'wpseo_schema_aggregator_schemamap_priority', 'custom_schemamap_priority' ); + +/** + * Increase schema map priority to indicate importance. + * + * Higher priority suggests to search engines that this content + * is important relative to other URLs on your site. + * + * @link https://developer.yoast.com/features/schema/schema-aggregator/filters/#wpseo_schema_aggregator_schemamap_priority + * + * @param float $priority Priority value (0.0 to 1.0). + * + * @return float Modified priority value. + */ +function custom_schemamap_priority( $priority ) { + return 1.0; // Maximum priority. +} +``` + +## Filtering Strategy + +The filtering strategy determines which schema pieces are included or excluded from aggregation. By default, the aggregator filters out Actions, Enumerations, Meta types, and Website elements. + +### wpseo_schema_aggregator_filtering_strategy + +Implement a custom filtering strategy by providing your own strategy class. + +**Parameters:** + +| Parameter | Type | Description | +|-----------|------|-------------| +| `$strategy` | object\|null | Custom filtering strategy instance | + +**Default Value:** `null` (uses default strategy) + +**Example:** + +```php +add_filter( 'wpseo_schema_aggregator_filtering_strategy', 'custom_filtering_strategy' ); + +/** + * Implement custom schema filtering logic. + * + * Use this to create advanced filtering rules beyond the default + * context-based filtering. Your strategy class should implement + * the filtering logic in its filter() method. + * + * @link https://developer.yoast.com/features/schema/schema-aggregator/filters/#wpseo_schema_aggregator_filtering_strategy + * + * @param object|null $strategy Custom filtering strategy instance. + * + * @return object Custom filtering strategy. + */ +function custom_filtering_strategy( $strategy ) { + // Return custom strategy that only includes Article types. + return new class { + /** + * Filter schema pieces to only include Articles. + * + * @param array $schema_piece Schema piece to filter. + * + * @return bool Whether to include this schema piece. + */ + public function filter( $schema_piece ) { + // Only include Article types and their subtypes. + $article_types = [ 'Article', 'BlogPosting', 'NewsArticle', 'ScholarlyArticle' ]; + + if ( isset( $schema_piece['@type'] ) ) { + $type = $schema_piece['@type']; + + // Handle array of types. + if ( is_array( $type ) ) { + return ! empty( array_intersect( $type, $article_types ) ); + } + + return in_array( $type, $article_types, true ); + } + + return false; + } + }; +} +``` + +## Elements Context Map + +The context map categorizes schema.org types into contexts like Content, Commerce, Entity, etc. This is used by the default filtering strategy. + +### wpseo_schema_aggregator_elements_context_map + +Override the complete elements context map. + +**Parameters:** + +| Parameter | Type | Description | +|-----------|------|-------------| +| `$context_map` | array | Complete mapping of schema types to contexts | + +**Default Value:** Comprehensive map of 1000+ schema.org types + +**Example:** + +```php +add_filter( 'wpseo_schema_aggregator_elements_context_map', 'custom_context_map' ); + +/** + * Provide a completely custom context map. + * + * This replaces the entire default mapping. Use this when you need + * complete control over which types belong to which contexts. + * + * @link https://developer.yoast.com/features/schema/schema-aggregator/filters/#wpseo_schema_aggregator_elements_context_map + * + * @param array $context_map Complete context map. + * + * @return array Custom context map. + */ +function custom_context_map( $context_map ) { + // Define a simplified context map. + return [ + 'content' => [ + 'Article', + 'BlogPosting', + 'NewsArticle', + ], + 'commerce' => [ + 'Product', + 'Offer', + ], + 'entity' => [ + 'Person', + 'Organization', + ], + ]; +} +``` + +### wpseo_schema_aggregator_elements_context_map_\{context\} + +Modify elements for a specific context. Available contexts: `content`, `commerce`, `entity`, `event`, `data`, `medical`, `action`, `enumeration`, `meta`, `website`. + +**Parameters:** + +| Parameter | Type | Description | +|-----------|------|-------------| +| `$elements` | array | Array of schema types in this context | + +**Example: Add Custom Types to Content Context** + +```php +add_filter( 'wpseo_schema_aggregator_elements_context_map_content', 'add_custom_content_types' ); + +/** + * Add custom schema types to the content context. + * + * This is useful when you have custom schema types that should + * be treated as content entities. + * + * @link https://developer.yoast.com/features/schema/schema-aggregator/filters/#wpseo_schema_aggregator_elements_context_map_context + * + * @param array $elements Schema types in the content context. + * + * @return array Modified array of schema types. + */ +function add_custom_content_types( $elements ) { + // Add custom types to content context. + $elements[] = 'Recipe'; + $elements[] = 'HowTo'; + $elements[] = 'FAQPage'; + + return $elements; +} +``` + +**Example: Remove Types from Action Context** + +```php +add_filter( 'wpseo_schema_aggregator_elements_context_map_action', 'remove_action_types' ); + +/** + * Remove specific action types from the action context. + * + * This can help further refine which actions are filtered out. + * + * @link https://developer.yoast.com/features/schema/schema-aggregator/filters/#wpseo_schema_aggregator_elements_context_map_context + * + * @param array $elements Schema types in the action context. + * + * @return array Modified array of schema types. + */ +function remove_action_types( $elements ) { + // Remove SearchAction from action context. + // This means it won't be filtered out anymore. + return array_diff( $elements, [ 'SearchAction' ] ); +} +``` + +## Article Enhancement + +Articles and their subtypes (BlogPosting, NewsArticle, etc.) can be enhanced with additional properties like `articleBody`, `description`, and `keywords`. + +### Article Enhancement Configuration + +Use the `wpseo_article_enhance_config_{key}` filter pattern to configure enhancement behavior. Available keys: + +- `max_article_body_length` - Maximum length for articleBody (default: 5000) +- `max_description_length` - Maximum length for description (default: 320) +- `add_article_body` - Whether to add articleBody (default: true) +- `add_description` - Whether to add description (default: true) +- `add_keywords` - Whether to add keywords (default: true) + +**Example: Adjust Maximum Lengths** + +```php +add_filter( 'wpseo_article_enhance_config_max_article_body_length', 'custom_article_body_length' ); + +/** + * Increase maximum article body length. + * + * Useful for long-form content where you want to include + * more of the article text in the schema. + * + * @link https://developer.yoast.com/features/schema/schema-aggregator/filters/#article-enhancement-configuration + * + * @param int $max_length Maximum length in characters. + * + * @return int Modified maximum length. + */ +function custom_article_body_length( $max_length ) { + return 10000; // Increase from 5000 to 10000 characters. +} +``` + +```php +add_filter( 'wpseo_article_enhance_config_max_description_length', 'custom_description_length' ); + +/** + * Adjust maximum description length. + * + * @link https://developer.yoast.com/features/schema/schema-aggregator/filters/#article-enhancement-configuration + * + * @param int $max_length Maximum length in characters. + * + * @return int Modified maximum length. + */ +function custom_description_length( $max_length ) { + return 500; // Increase from 320 to 500 characters. +} +``` + +**Example: Disable Specific Enhancements** + +```php +add_filter( 'wpseo_article_enhance_config_add_article_body', '__return_false' ); +``` + +### Article Enhancement Toggles + +Use the `wpseo_article_enhance_{enhancement}` filter pattern to enable or disable enhancements dynamically. Available enhancements match the configuration keys: `article_body`, `description`, `keywords`. + +**Example: Conditional Article Body** + +```php +add_filter( 'wpseo_article_enhance_article_body', 'conditional_article_body', 10, 2 ); + +/** + * Only include article body for certain post types. + * + * This allows fine-grained control over which content types + * receive full body enhancement. + * + * @link https://developer.yoast.com/features/schema/schema-aggregator/filters/#article-enhancement-toggles + * + * @param bool $enabled Whether enhancement is enabled. + * @param array $schema_piece The schema piece being enhanced. + * + * @return bool Modified enabled status. + */ +function conditional_article_body( $enabled, $schema_piece ) { + // Only add article body for blog posts, not news articles. + if ( isset( $schema_piece['@type'] ) && $schema_piece['@type'] === 'NewsArticle' ) { + return false; + } + + return $enabled; +} +``` + +### Article Body with Excerpt + +Control whether to include article body when an excerpt already exists. + +**Filter:** `wpseo_article_enhance_body_when_excerpt_exists` + +**Parameters:** + +| Parameter | Type | Description | +|-----------|------|-------------| +| `$include_body` | bool | Whether to include body when excerpt exists | +| `$schema_piece` | array | The schema piece being enhanced | + +**Default Value:** `false` + +**Example:** + +```php +add_filter( 'wpseo_article_enhance_body_when_excerpt_exists', '__return_true'); +``` + +### Article Body Fallback + +Control whether to include article body when no excerpt exists. + +**Filter:** `wpseo_article_enhance_article_body_fallback` + +**Parameters:** + +| Parameter | Type | Description | +|-----------|------|-------------| +| `$use_fallback` | bool | Whether to use body as fallback | +| `$schema_piece` | array | The schema piece being enhanced | + +**Default Value:** `true` + +**Example:** + +```php +add_filter( 'wpseo_article_enhance_article_body_fallback', '__return_false' ); +``` + +## Person Enhancement + +Person schema pieces can be enhanced with additional properties based on WordPress user data. + +### Person Enhancement Configuration + +Use the `wpseo_person_enhance_config_{key}` filter pattern to configure person enhancement. The exact available keys depend on your implementation. + +**Example:** + +```php +add_filter( 'wpseo_person_enhance_config_include_social_profiles', '__return_true' ); +``` + +### Person Enhancement Toggles + +Use the `wpseo_person_enhance_\{enhancement\}` filter pattern to enable or disable specific person enhancements dynamically. + +**Example:** + +```php +add_filter( 'wpseo_person_enhance_bio', 'conditional_person_bio', 10, 2 ); + +/** + * Only include person bio for authors with posts. + * + * @link https://developer.yoast.com/features/schema/schema-aggregator/filters/#person-enhancement-toggles + * + * @param bool $enabled Whether enhancement is enabled. + * @param array $schema_piece The schema piece being enhanced. + * + * @return bool Modified enabled status. + */ +function conditional_person_bio( $enabled, $schema_piece ) { + // Extract user ID from schema piece if available. + if ( isset( $schema_piece['@id'] ) ) { + // Parse user ID from the @id. + preg_match( '/person\/(\d+)/', $schema_piece['@id'], $matches ); + + if ( ! empty( $matches[1] ) ) { + $user_id = (int) $matches[1]; + $post_count = count_user_posts( $user_id ); + + // Only include bio if user has published posts. + return $post_count > 0; + } + } + + return $enabled; +} +``` + +## Robots.txt Integration + +By default, the schema map is automatically referenced in your site's `robots.txt` file. You can disable this integration if needed. + +### wpseo_disable_robots_schemamap + +Disable the schema map reference in robots.txt. + +**Parameters:** + +| Parameter | Type | Description | +|-----------|------|-------------| +| `$disable` | bool | Whether to disable robots.txt integration | + +**Default Value:** `false` + +**Example:** + +```php +add_filter( 'wpseo_disable_robots_schemamap', '__return_true' ); +``` + +### Development Environment Configuration + +Disable caching and adjust settings for easier development: + +```php +/** + * Schema Aggregator configuration for development. + */ + +// Disable caching in development. +add_filter( 'wpseo_schema_aggregator_cache_enabled', function( $enabled ) { + return defined( 'WP_DEBUG' ) && WP_DEBUG ? false : $enabled; +} ); + +// Smaller pagination for faster testing. +add_filter( 'wpseo_schema_aggregator_per_page', function() { + return defined( 'WP_DEBUG' ) && WP_DEBUG ? 10 : 1000; +} ); + +// Don't add schema map to robots.txt in development. +add_filter( 'wpseo_disable_robots_schemamap', function() { + return defined( 'WP_DEBUG' ) && WP_DEBUG; +} ); +``` + +## Related Documentation + +- [Schema Aggregator Overview](overview.md) - Introduction and key features +- [API Reference](api-reference.md) - REST API endpoints and CLI commands +- [Schema.org Documentation](https://schema.org/) - Schema types reference +- [JSON-LD Specification](https://json-ld.org/) - Format specification +- [Yoast Schema API](../api.md) - Main Schema output API diff --git a/docs/features/schema/schema-aggregator/overview.md b/docs/features/schema/schema-aggregator/overview.md new file mode 100644 index 00000000..6bfa4f12 --- /dev/null +++ b/docs/features/schema/schema-aggregator/overview.md @@ -0,0 +1,159 @@ +--- +id: overview +title: "Schema Aggregator: Overview" +sidebar_label: Overview +description: An introduction to the Schema Aggregator feature in Yoast SEO. +--- + +The Schema Aggregator is a powerful feature in Yoast SEO that collects and serves structured data (schema.org markup) for all content across your WordPress site. + +### What gets aggregated + +By default, the Schema Aggregator processes: + +- All **public post types** (posts, pages, custom post types) + +You can customize which post types are included using the `wpseo_schema_aggregator_post_types` filter. + +### Schema types + +The aggregator handles schema.org types, categorized into 10 contexts: + +- **Website**: Site information +- **Content**: Articles, blog posts, creative works +- **Commerce**: Products, offers, orders +- **Entity**: Organizations, persons, places +- **Event**: Events, schedules +- **Data**: Datasets, statistical information +- **Medical**: Medical conditions, therapies +- **Action**: Potential actions (filtered by default) +- **Enumeration**: Type definitions (filtered by default) +- **Meta**: Schema.org metadata (filtered by default) +- **Website Meta**: Site structure elements, breadcrumbs (filtered by default) + +The specific schema types that get filtered can be found at the [source](https://github.com/Yoast/wordpress-seo/blob/trunk/src/schema-aggregator/infrastructure/elements-context-map/default-elements-context-map.php). +## Key features + +### REST API endpoints + +Access aggregated schema through clean REST endpoints: + +``` +GET /wp-json/yoast/v1/schema-aggregator/get-schema/{post_type}[/{page}] +GET /wp-json/yoast/v1/schema-aggregator/get-xml +``` + +### CLI commands + +Automate schema aggregation with WP-CLI: + +```bash +wp yoast aggregate_site_schema [--page=] +wp yoast clear_schema_aggregator_cache [] +``` + +### Caching + +The Schema Aggregator implements a dynamic caching strategy: + +- **Dynamic TTL**: Cache duration adapts to site size + - Small sites (< 100 posts): 24 hours + - Medium sites (100-1000 posts): 12 hours + - Large sites (> 1000 posts): 6 hours +- **Automatic invalidation**: Cache clears when posts are updated +- **Per-post-type caching**: Each post type has its own cache +- **Debug mode**: Bypass cache with `?debug=1` parameter + +### Schema map (XML sitemap for structured data) + +The schema map provides a XML index of all available schema endpoints: + +```xml + + + + https://example.com/wp-json/yoast/v1/schema-aggregator/get-schema/post + + + https://example.com/wp-json/yoast/v1/schema-aggregator/get-schema/page + + +``` + +The schema map is automatically referenced in your site's `robots.txt`: + +``` +Sitemap: https://example.com/wp-json/yoast/v1/schema-aggregator/get-xml +``` + +### External source support + +The Schema Aggregator seamlessly integrates with: + +- **WooCommerce**: Product schema automatically included +- **Easy Digital Downloads**: Download schema automatically included +- **Custom sources**: Extend with your own external schema repositories + +## Getting started + +### Enable the feature + +The Schema Aggregator is disabled by default in Yoast SEO. If you need to enable it, you can do so programmatically: + +```php +WPSEO_Options::set( 'enable_schema_aggregation_endpoint', true ); +``` +Or by enabling it via the Yoast SEO settings in the WordPress admin. + +### Example aggregated schema in JSON-L format + +Fetch schema for the `post` post type: + +```bash +curl https://example.com/wp-json/yoast/v1/schema-aggregator/get-schema/post +``` + +Response: + +```json lines +{ + "@context": "https://schema.org", + "@type": "Article", + "@id": "https://example.com/hello-world/#article", + "headline": "Hello World", + "datePublished": "2026-01-15T10:30:00+00:00", + "author": { + "@id": "https://example.com/#/schema/person/1" + } +} +{ + "@context": "https://schema.org", + + "@type": "Article", + "@id": "https://example.com/your-second-post/#article", + "headline": "The second post", + "datePublished": "2026-01-15T10:30:00+00:00", + "author": { + "@id": "https://example.com/#/schema/person/1" + } +} +``` + +### Clear cache + +Clear all cached schema: + +```bash +wp yoast clear_schema_aggregator_cache +``` + +Clear cache for specific post type: + +```bash +wp yoast clear_schema_aggregator_cache post +``` +## Learn more + +- [Schema.org documentation](https://schema.org/) +- [JSON-LD specification](https://json-ld.org/) +- [Google structured data guidelines](https://developers.google.com/search/docs/appearance/structured-data/intro-structured-data) diff --git a/docs/overview.md b/docs/overview.md index cc5ac380..eb7622b5 100644 --- a/docs/overview.md +++ b/docs/overview.md @@ -32,6 +32,7 @@ Learn how our features work, how to customize the outputs, and how best to integ - [Schema.org markup](features/schema/) - [Schema pieces](/features/schema/pieces/) - [Output per plugin](/features/schema/plugins/) + - [Schema aggregator](/features/schema/schema-aggregator/) ## Integrating Want to integrate Yoast SEO into your platform? Check out our documentation on [integrating](/development/integrating.md), and familiarize yourself with all of our features and controls. diff --git a/sidebars.js b/sidebars.js index 94b05661..40d83442 100644 --- a/sidebars.js +++ b/sidebars.js @@ -262,6 +262,20 @@ module.exports = { "features/schema/plugins/yoast-seo-shopify", ], }, + { + type: "category", + label: "Schema Aggregator", + link: { + type: "generated-index", + description: "The Schema Aggregator collects and serves structured data for all content across your WordPress site through REST API endpoints and CLI commands.", + slug: "/features/schema/schema-aggregator", + }, + items: [ + "features/schema/schema-aggregator/overview", + "features/schema/schema-aggregator/api-reference", + "features/schema/schema-aggregator/filters", + ], + }, ], }, {