on relevant pages. * Skips output when a dedicated SEO plugin is active. * * @package CyyWordpress */ if ( ! class_exists( 'CyyWordpress_Schema' ) ) : /** * Handles JSON-LD output. */ class CyyWordpress_Schema { /** * Register hooks. */ public static function init(): void { // Bail early if a popular SEO plugin already handles schema. if ( defined( 'WPSEO_VERSION' ) || defined( 'RANKMATH_VERSION' ) || class_exists( 'All_in_One_SEO_Pack' ) ) { return; } add_action( 'wp_head', array( static::class, 'output_schema' ) ); } /** * Determine page type and output the correct schema. */ public static function output_schema(): void { $schema = null; if ( is_front_page() || is_home() ) { $schema = self::website_schema(); } elseif ( is_singular( 'post' ) ) { $schema = self::article_schema(); } elseif ( is_author() ) { $schema = self::person_schema(); } if ( $schema ) { // json_encode with JSON_UNESCAPED_UNICODE for readable Chinese output. echo '' . PHP_EOL; } } /** * WebSite schema with SearchAction for Sitelink Search Box. * * @return array */ private static function website_schema(): array { return array( '@context' => 'https://schema.org', '@type' => 'WebSite', 'name' => get_bloginfo( 'name' ), 'url' => home_url( '/' ), 'potentialAction' => array( '@type' => 'SearchAction', 'target' => array( '@type' => 'EntryPoint', 'urlTemplate' => home_url( '/?s={search_term_string}' ), ), 'query-input' => 'required name=search_term_string', ), ); } /** * Article schema for single posts. * * @return array */ private static function article_schema(): array { global $post; $author_id = (int) get_the_author_meta( 'ID' ); $author_name = get_the_author_meta( 'display_name', $author_id ); $author_url = get_author_posts_url( $author_id ); $image_url = ''; if ( has_post_thumbnail() ) { $src = wp_get_attachment_image_src( (int) get_post_thumbnail_id(), 'large' ); if ( $src ) { $image_url = $src[0]; } } $schema = array( '@context' => 'https://schema.org', '@type' => 'Article', 'headline' => get_the_title(), 'url' => (string) get_permalink(), 'datePublished' => get_the_date( DATE_W3C ), 'dateModified' => get_the_modified_date( DATE_W3C ), 'author' => array( '@type' => 'Person', 'name' => $author_name, 'url' => $author_url, ), 'publisher' => array( '@type' => 'Organization', 'name' => get_bloginfo( 'name' ), 'url' => home_url( '/' ), ), 'description' => has_excerpt() ? get_the_excerpt() : wp_trim_words( wp_strip_all_tags( $post->post_content ), 30 ), ); if ( $image_url ) { $schema['image'] = $image_url; } return $schema; } /** * Person schema for author archive pages. * * @return array */ private static function person_schema(): array { $author = get_queried_object(); $author_id = ( $author instanceof WP_User ) ? $author->ID : 0; $author_name = get_the_author_meta( 'display_name', $author_id ); $author_url = get_author_posts_url( $author_id ); $bio = get_the_author_meta( 'description', $author_id ); $schema = array( '@context' => 'https://schema.org', '@type' => 'Person', 'name' => $author_name, 'url' => $author_url, ); if ( $bio ) { $schema['description'] = $bio; } return $schema; } } endif;