From de07a671da3b0b2d6e49566f75936692d5ee327a Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Tue, 2 Jun 2020 17:08:57 +0200 Subject: [PATCH 1/4] Create new Discovery class --- includes/Discovery.php | 245 ++++++++++++++++++++ includes/Media.php | 75 +++++- includes/Plugin.php | 5 +- includes/REST_API/Stories_Controller.php | 3 +- includes/Story_Post_Type.php | 280 +---------------------- includes/Story_Renderer.php | 2 +- 6 files changed, 329 insertions(+), 281 deletions(-) create mode 100644 includes/Discovery.php diff --git a/includes/Discovery.php b/includes/Discovery.php new file mode 100644 index 000000000000..4fc6e08bf000 --- /dev/null +++ b/includes/Discovery.php @@ -0,0 +1,245 @@ +' . esc_html( wp_get_document_title() ) . '' . "\n"; + }, + 1 + ); + + add_action( 'web_stories_story_head', [ $this, 'print_schemaorg_metadata' ] ); + + // @todo Check if there's something to skip in the new version. + add_action( 'web_stories_story_head', 'rest_output_link_wp_head', 10, 0 ); + add_action( 'web_stories_story_head', 'wp_resource_hints', 2 ); + add_action( 'web_stories_story_head', 'feed_links', 2 ); + add_action( 'web_stories_story_head', 'feed_links_extra', 3 ); + add_action( 'web_stories_story_head', 'rsd_link' ); + add_action( 'web_stories_story_head', 'wlwmanifest_link' ); + add_action( 'web_stories_story_head', 'adjacent_posts_rel_link_wp_head', 10, 0 ); + add_action( 'web_stories_story_head', 'noindex', 1 ); + add_action( 'web_stories_story_head', 'wp_generator' ); + add_action( 'web_stories_story_head', 'rel_canonical' ); + add_action( 'web_stories_story_head', 'wp_shortlink_wp_head', 10, 0 ); + add_action( 'web_stories_story_head', 'wp_site_icon', 99 ); + add_action( 'web_stories_story_head', 'wp_oembed_add_discovery_links' ); + } + + /** + * Prints the schema.org metadata on the single story template. + * + * @return void + */ + public function print_schemaorg_metadata() { + $metadata = $this->get_schemaorg_metadata(); + + ?> + + 'http://schema.org', + 'publisher' => [ + '@type' => 'Organization', + 'name' => $publisher['name'], + 'logo' => $publisher['logo'], + ], + ]; + + /** + * We're expecting a post object. + * + * @var WP_Post $post + */ + $post = get_queried_object(); + + if ( $post instanceof WP_Post ) { + $metadata = array_merge( + $metadata, + [ + '@type' => 'BlogPosting', + 'mainEntityOfPage' => get_permalink(), + 'headline' => get_the_title(), + 'datePublished' => mysql2date( 'c', $post->post_date_gmt, false ), + 'dateModified' => mysql2date( 'c', $post->post_modified_gmt, false ), + ] + ); + + $post_author = get_userdata( (int) $post->post_author ); + + if ( $post_author ) { + $metadata['author'] = [ + '@type' => 'Person', + 'name' => html_entity_decode( $post_author->display_name, ENT_QUOTES, get_bloginfo( 'charset' ) ), + ]; + } + + if ( has_post_thumbnail( $post->ID ) ) { + $metadata['image'] = wp_get_attachment_image_url( (int) get_post_thumbnail_id( $post->ID ), 'full' ); + } + } + + /** + * Filters the schema.org metadata for a given story. + * + * @param array $metadata The structured data. + * @param WP_Post $post The current post object. + */ + return apply_filters( 'web_stories_story_schema_metadata', $metadata, $post ); + } + + /** + * Gets a valid publisher logo URL. Loops through sizes and looks for a square image. + * + * @param integer $image_id Attachment ID. + * + * @return string|false Either the URL or false if error. + */ + private static function get_valid_publisher_image( $image_id ) { + $logo_image_url = false; + + // Get metadata for finding a square image. + $metadata = wp_get_attachment_metadata( $image_id ); + if ( empty( $metadata ) ) { + return $logo_image_url; + } + // First lets check if the image is square by default. + $fullsize_img = wp_get_attachment_image_src( $image_id, 'full', false ); + if ( $metadata['width'] === $metadata['height'] && is_array( $fullsize_img ) ) { + return array_shift( $fullsize_img ); + } + + if ( empty( $metadata['sizes'] ) ) { + return $logo_image_url; + } + + // Loop through other size to find a square image. + foreach ( $metadata['sizes'] as $size ) { + if ( $size['width'] === $size['height'] && $size['width'] >= 96 ) { + $logo_img = wp_get_attachment_image_src( $image_id, [ $size['width'], $size['height'] ], false ); + if ( is_array( $logo_img ) ) { + return array_shift( $logo_img ); + } + } + } + + // If a square image was not found, return the full size nevertheless, + // the editor should take care of warning about incorrect size. + return is_array( $fullsize_img ) ? array_shift( $fullsize_img ) : false; + } + + /** + * Get the publisher logo. + * + * @link https://developers.google.com/search/docs/data-types/article#logo-guidelines + * @link https://amp.dev/documentation/components/amp-story/#publisher-logo-src-guidelines + * + * @return string Publisher logo image URL. WordPress logo if no site icon or custom logo defined, and no logo provided via 'amp_site_icon_url' filter. + */ + public static function get_publisher_logo() { + $logo_image_url = null; + + $publisher_logo_settings = get_option( Stories_Controller::PUBLISHER_LOGOS_OPTION, [] ); + $has_publisher_logo = ! empty( $publisher_logo_settings['active'] ); + if ( $has_publisher_logo ) { + $publisher_logo_id = absint( $publisher_logo_settings['active'] ); + $logo_image_url = self::get_valid_publisher_image( $publisher_logo_id ); + } + + // @todo Once we are enforcing setting publisher logo in the editor, we shouldn't need the fallback options. + // Currently, it's marked as required but that's not actually enforced. + + // Finding fallback image. + $custom_logo_id = get_theme_mod( 'custom_logo' ); + if ( empty( $logo_image_url ) && has_custom_logo() && $custom_logo_id ) { + $logo_image_url = self::get_valid_publisher_image( $custom_logo_id ); + } + + // Try Site Icon, though it is not ideal for non-Story because it should be square. + $site_icon_id = get_option( 'site_icon' ); + if ( empty( $logo_image_url ) && $site_icon_id ) { + $logo_image_url = self::get_valid_publisher_image( $site_icon_id ); + } + + // Fallback to serving the WordPress logo. + if ( empty( $logo_image_url ) ) { + $logo_image_url = WEBSTORIES_PLUGIN_DIR_URL . 'assets/images/fallback-wordpress-publisher-logo.png'; + } + + /** + * Filters the publisher's logo. + * + * This should point to a square image. + * + * @param string $logo_image_url URL to the publisher's logo. + */ + return apply_filters( 'web_stories_publisher_logo', $logo_image_url ); + } + + /** + * Returns the publisher data. + * + * @return array Publisher name and logo. + */ + public static function get_publisher_data() { + $publisher = get_bloginfo( 'name' ); + $publisher_logo = self::get_publisher_logo(); + + return [ + 'name' => $publisher, + 'logo' => $publisher_logo, + ]; + } +} diff --git a/includes/Media.php b/includes/Media.php index 1a344a3673d7..c65c498ad95f 100644 --- a/includes/Media.php +++ b/includes/Media.php @@ -213,7 +213,7 @@ public static function rest_api_init() { 'attachment', 'featured_media_src', [ - 'get_callback' => static function ( $prepared, $field_name, $request ) { + 'get_callback' => static function ( $prepared ) { $id = $prepared['featured_media']; $image = []; @@ -319,4 +319,77 @@ public static function delete_video_poster( $attachment_id ) { wp_delete_attachment( $post_id, true ); } } + + /** + * Returns a list of allowed file types. + * + * @return array List of allowed file types. + */ + public static function get_allowed_file_types() { + $allowed_mime_types = self::get_allowed_mime_types(); + $mime_types = []; + + foreach ( $allowed_mime_types as $mimes ) { + // Otherwise this throws a warning on PHP < 7.3. + if ( ! empty( $mimes ) ) { + array_push( $mime_types, ...$mimes ); + } + } + + $allowed_file_types = []; + $all_mime_types = wp_get_mime_types(); + + foreach ( $all_mime_types as $ext => $mime ) { + if ( in_array( $mime, $mime_types, true ) ) { + array_push( $allowed_file_types, ...explode( '|', $ext ) ); + } + } + sort( $allowed_file_types ); + + return $allowed_file_types; + } + + /** + * Returns a list of allowed mime types per media type (image, audio, video). + * + * @return array List of allowed mime types. + */ + public static function get_allowed_mime_types() { + $default_allowed_mime_types = [ + 'image' => [ + 'image/png', + 'image/jpeg', + 'image/jpg', + 'image/gif', + ], + 'audio' => [], // todo: support audio uploads. + 'video' => [ + 'video/mp4', + 'video/webm', + ], + ]; + + /** + * Filter list of allowed mime types. + * + * This can be used to add additionally supported formats, for example by plugins + * that do video transcoding. + * + * @since 1.3 + * + * @param array $default_allowed_mime_types Associative array of allowed mime types per media type (image, audio, video). + */ + $allowed_mime_types = apply_filters( 'web_stories_allowed_mime_types', $default_allowed_mime_types ); + + foreach ( array_keys( $default_allowed_mime_types ) as $media_type ) { + if ( ! is_array( $allowed_mime_types[ $media_type ] ) || empty( $allowed_mime_types[ $media_type ] ) ) { + $allowed_mime_types[ $media_type ] = $default_allowed_mime_types[ $media_type ]; + } + + // Only add currently supported mime types. + $allowed_mime_types[ $media_type ] = array_values( array_intersect( $allowed_mime_types[ $media_type ], wp_get_mime_types() ) ); + } + + return $allowed_mime_types; + } } diff --git a/includes/Plugin.php b/includes/Plugin.php index f6afaba54fa8..4c938eefe142 100644 --- a/includes/Plugin.php +++ b/includes/Plugin.php @@ -71,7 +71,10 @@ public function register() { $embed_block = new Embed_Block(); add_action( 'init', [ $embed_block, 'init' ] ); - // Integrations. + // Frontend. + $discovery = new Discovery(); + add_action( 'init', [ $discovery, 'init' ] ); + add_filter( 'googlesitekit_amp_gtag_opt', [ $this, 'filter_site_kit_gtag_opt' ] ); } diff --git a/includes/REST_API/Stories_Controller.php b/includes/REST_API/Stories_Controller.php index da0f67183d22..a3eaf200b908 100644 --- a/includes/REST_API/Stories_Controller.php +++ b/includes/REST_API/Stories_Controller.php @@ -26,6 +26,7 @@ namespace Google\Web_Stories\REST_API; +use Google\Web_Stories\Discovery; use Google\Web_Stories\Story_Post_Type; use stdClass; use WP_Query; @@ -108,7 +109,7 @@ public function prepare_item_for_response( $post, $request ) { } if ( in_array( 'publisher_logo_url', $fields, true ) ) { - $data['publisher_logo_url'] = Story_Post_Type::get_publisher_logo(); + $data['publisher_logo_url'] = Discovery::get_publisher_logo(); } if ( in_array( 'style_presets', $fields, true ) ) { diff --git a/includes/Story_Post_Type.php b/includes/Story_Post_Type.php index c5cdf4b59eac..49052a70b76c 100644 --- a/includes/Story_Post_Type.php +++ b/includes/Story_Post_Type.php @@ -145,32 +145,6 @@ public static function init() { // Select the single-web-story.php template for Stories. add_filter( 'template_include', [ __CLASS__, 'filter_template_include' ] ); - add_action( - 'web_stories_story_head', - static function () { - // Theme support for title-tag is implied for stories. See _wp_render_title_tag(). - echo '' . esc_html( wp_get_document_title() ) . '' . "\n"; - }, - 1 - ); - - add_action( 'web_stories_story_head', [ __CLASS__, 'print_schemaorg_metadata' ] ); - - // @todo Check if there's something to skip in the new version. - add_action( 'web_stories_story_head', 'rest_output_link_wp_head', 10, 0 ); - add_action( 'web_stories_story_head', 'wp_resource_hints', 2 ); - add_action( 'web_stories_story_head', 'feed_links', 2 ); - add_action( 'web_stories_story_head', 'feed_links_extra', 3 ); - add_action( 'web_stories_story_head', 'rsd_link' ); - add_action( 'web_stories_story_head', 'wlwmanifest_link' ); - add_action( 'web_stories_story_head', 'adjacent_posts_rel_link_wp_head', 10, 0 ); - add_action( 'web_stories_story_head', 'noindex', 1 ); - add_action( 'web_stories_story_head', 'wp_generator' ); - add_action( 'web_stories_story_head', 'rel_canonical' ); - add_action( 'web_stories_story_head', 'wp_shortlink_wp_head', 10, 0 ); - add_action( 'web_stories_story_head', 'wp_site_icon', 99 ); - add_action( 'web_stories_story_head', 'wp_oembed_add_discovery_links' ); - // @todo Improve AMP plugin compatibility, see https://github.com/google/web-stories-wp/issues/967 add_filter( 'amp_skip_post', @@ -369,8 +343,8 @@ public static function get_editor_settings() { 'autoSaveInterval' => defined( 'AUTOSAVE_INTERVAL' ) ? AUTOSAVE_INTERVAL : null, 'isRTL' => is_rtl(), 'timeFormat' => get_option( 'time_format' ), - 'allowedMimeTypes' => self::get_allowed_mime_types(), - 'allowedFileTypes' => self::get_allowed_file_types(), + 'allowedMimeTypes' => Media::get_allowed_mime_types(), + 'allowedFileTypes' => Media::get_allowed_file_types(), 'postType' => self::POST_TYPE_SLUG, 'storyId' => $story_id, 'previewLink' => get_preview_post_link( $story_id, $preview_query_args ), @@ -388,7 +362,7 @@ public static function get_editor_settings() { 'link' => '/web-stories/v1/link', ], 'metadata' => [ - 'publisher' => self::get_publisher_data(), + 'publisher' => Discovery::get_publisher_data(), 'logoPlaceholder' => self::PUBLISHER_LOGO_PLACEHOLDER, 'fallbackPoster' => plugins_url( 'assets/images/fallback-poster.jpg', WEBSTORIES_PLUGIN_FILE ), ], @@ -407,79 +381,6 @@ public static function get_editor_settings() { return $settings; } - /** - * Returns a list of allowed file types. - * - * @return array List of allowed file types. - */ - protected static function get_allowed_file_types() { - $allowed_mime_types = self::get_allowed_mime_types(); - $mime_types = []; - - foreach ( $allowed_mime_types as $type => $mimes ) { - // Otherwise this throws a warning on PHP < 7.3. - if ( ! empty( $mimes ) ) { - array_push( $mime_types, ...$mimes ); - } - } - - $allowed_file_types = []; - $all_mime_types = wp_get_mime_types(); - - foreach ( $all_mime_types as $ext => $mime ) { - if ( in_array( $mime, $mime_types, true ) ) { - array_push( $allowed_file_types, ...explode( '|', $ext ) ); - } - } - sort( $allowed_file_types ); - - return $allowed_file_types; - } - - /** - * Returns a list of allowed mime types per media type (image, audio, video). - * - * @return array List of allowed mime types. - */ - protected static function get_allowed_mime_types() { - $default_allowed_mime_types = [ - 'image' => [ - 'image/png', - 'image/jpeg', - 'image/jpg', - 'image/gif', - ], - 'audio' => [], // todo: support audio uploads. - 'video' => [ - 'video/mp4', - 'video/webm', - ], - ]; - - /** - * Filter list of allowed mime types. - * - * This can be used to add additionally supported formats, for example by plugins - * that do video transcoding. - * - * @since 1.3 - * - * @param array $default_allowed_mime_types Associative array of allowed mime types per media type (image, audio, video). - */ - $allowed_mime_types = apply_filters( 'web_stories_allowed_mime_types', $default_allowed_mime_types ); - - foreach ( array_keys( $default_allowed_mime_types ) as $media_type ) { - if ( ! is_array( $allowed_mime_types[ $media_type ] ) || empty( $allowed_mime_types[ $media_type ] ) ) { - $allowed_mime_types[ $media_type ] = $default_allowed_mime_types[ $media_type ]; - } - - // Only add currently supported mime types. - $allowed_mime_types[ $media_type ] = array_values( array_intersect( $allowed_mime_types[ $media_type ], wp_get_mime_types() ) ); - } - - return $allowed_mime_types; - } - /** * Filter the list of admin classes. * @@ -648,179 +549,4 @@ public static function filter_template_include( $template ) { return $template; } - - /** - * Gets a valid publisher logo URL. Loops through sizes and looks for a square image. - * - * @param integer $image_id Attachment ID. - * - * @return string|false Either the URL or false if error. - */ - private static function get_valid_publisher_image( $image_id ) { - $logo_image_url = false; - - // Get metadata for finding a square image. - $metadata = wp_get_attachment_metadata( $image_id ); - if ( empty( $metadata ) ) { - return $logo_image_url; - } - // First lets check if the image is square by default. - $fullsize_img = wp_get_attachment_image_src( $image_id, 'full', false ); - if ( $metadata['width'] === $metadata['height'] && is_array( $fullsize_img ) ) { - return array_shift( $fullsize_img ); - } - - if ( empty( $metadata['sizes'] ) ) { - return $logo_image_url; - } - - // Loop through other size to find a square image. - foreach ( $metadata['sizes'] as $size ) { - if ( $size['width'] === $size['height'] && $size['width'] >= 96 ) { - $logo_img = wp_get_attachment_image_src( $image_id, [ $size['width'], $size['height'] ], false ); - if ( is_array( $logo_img ) ) { - return array_shift( $logo_img ); - } - } - } - - // If a square image was not found, return the full size nevertheless, - // the editor should take care of warning about incorrect size. - return is_array( $fullsize_img ) ? array_shift( $fullsize_img ) : false; - } - - /** - * Get the publisher logo. - * - * @link https://developers.google.com/search/docs/data-types/article#logo-guidelines - * @link https://amp.dev/documentation/components/amp-story/#publisher-logo-src-guidelines - * - * @return string Publisher logo image URL. WordPress logo if no site icon or custom logo defined, and no logo provided via 'amp_site_icon_url' filter. - */ - public static function get_publisher_logo() { - $logo_image_url = null; - - $publisher_logo_settings = get_option( Stories_Controller::PUBLISHER_LOGOS_OPTION, [] ); - $has_publisher_logo = ! empty( $publisher_logo_settings['active'] ); - if ( $has_publisher_logo ) { - $publisher_logo_id = absint( $publisher_logo_settings['active'] ); - $logo_image_url = self::get_valid_publisher_image( $publisher_logo_id ); - } - - // @todo Once we are enforcing setting publisher logo in the editor, we shouldn't need the fallback options. - // Currently, it's marked as required but that's not actually enforced. - - // Finding fallback image. - $custom_logo_id = get_theme_mod( 'custom_logo' ); - if ( empty( $logo_image_url ) && has_custom_logo() && $custom_logo_id ) { - $logo_image_url = self::get_valid_publisher_image( $custom_logo_id ); - } - - // Try Site Icon, though it is not ideal for non-Story because it should be square. - $site_icon_id = get_option( 'site_icon' ); - if ( empty( $logo_image_url ) && $site_icon_id ) { - $logo_image_url = self::get_valid_publisher_image( $site_icon_id ); - } - - // Fallback to serving the WordPress logo. - if ( empty( $logo_image_url ) ) { - $logo_image_url = WEBSTORIES_PLUGIN_DIR_URL . 'assets/images/fallback-wordpress-publisher-logo.png'; - } - - /** - * Filters the publisher's logo. - * - * This should point to a square image. - * - * @param string $logo_image_url URL to the publisher's logo. - */ - return apply_filters( 'web_stories_publisher_logo', $logo_image_url ); - } - - /** - * Returns the publisher data. - * - * @return array Publisher name and logo. - */ - private static function get_publisher_data() { - $publisher = get_bloginfo( 'name' ); - $publisher_logo = self::get_publisher_logo(); - - return [ - 'name' => $publisher, - 'logo' => $publisher_logo, - ]; - } - - /** - * Prints the schema.org metadata on the single story template. - * - * @return void - */ - public static function print_schemaorg_metadata() { - $metadata = self::get_schemaorg_metadata(); - - ?> - - 'http://schema.org', - 'publisher' => [ - '@type' => 'Organization', - 'name' => $publisher['name'], - 'logo' => $publisher['logo'], - ], - ]; - - /** - * We're expecting a post object. - * - * @var WP_Post $post - */ - $post = get_queried_object(); - - if ( $post instanceof WP_Post ) { - $metadata = array_merge( - $metadata, - [ - '@type' => 'BlogPosting', - 'mainEntityOfPage' => get_permalink(), - 'headline' => get_the_title(), - 'datePublished' => mysql2date( 'c', $post->post_date_gmt, false ), - 'dateModified' => mysql2date( 'c', $post->post_modified_gmt, false ), - ] - ); - - $post_author = get_userdata( (int) $post->post_author ); - - if ( $post_author ) { - $metadata['author'] = [ - '@type' => 'Person', - 'name' => html_entity_decode( $post_author->display_name, ENT_QUOTES, get_bloginfo( 'charset' ) ), - ]; - } - - if ( has_post_thumbnail( $post->ID ) ) { - $metadata['image'] = wp_get_attachment_image_url( (int) get_post_thumbnail_id( $post->ID ), 'full' ); - } - } - - /** - * Filters the schema.org metadata for a given story. - * - * @param array $metadata The structured data. - * @param WP_Post $post The current post object. - */ - return apply_filters( 'web_stories_story_schema_metadata', $metadata, $post ); - } } diff --git a/includes/Story_Renderer.php b/includes/Story_Renderer.php index 9bd178fd4fd8..c83c5ecef748 100644 --- a/includes/Story_Renderer.php +++ b/includes/Story_Renderer.php @@ -120,7 +120,7 @@ protected function replace_html_head( $content ) { * @return string Filtered markup. */ protected function add_publisher_logo( $content ) { - $publisher_logo = Story_Post_Type::get_publisher_logo(); + $publisher_logo = Discovery::get_publisher_logo(); return str_replace( Story_Post_Type::PUBLISHER_LOGO_PLACEHOLDER, $publisher_logo, $content ); } From aa7652b71017e00fbe2cdb031dca6f20793183dc Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Tue, 2 Jun 2020 17:28:56 +0200 Subject: [PATCH 2/4] Print twitter and open graph metadata --- includes/Discovery.php | 63 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/includes/Discovery.php b/includes/Discovery.php index 4fc6e08bf000..260c0015262e 100644 --- a/includes/Discovery.php +++ b/includes/Discovery.php @@ -51,6 +51,8 @@ static function () { ); add_action( 'web_stories_story_head', [ $this, 'print_schemaorg_metadata' ] ); + add_action( 'web_stories_story_head', [ $this, 'print_open_graph_metadata' ] ); + add_action( 'web_stories_story_head', [ $this, 'print_twitter_metadata' ] ); // @todo Check if there's something to skip in the new version. add_action( 'web_stories_story_head', 'rest_output_link_wp_head', 10, 0 ); @@ -140,6 +142,67 @@ protected function get_schemaorg_metadata() { return apply_filters( 'web_stories_story_schema_metadata', $metadata, $post ); } + /** + * Prints Open Graph metadata. + * + * @return void + */ + public function print_open_graph_metadata() { + ?> + + + + + + + + + + + + + + + + + Date: Wed, 3 Jun 2020 14:22:34 +0200 Subject: [PATCH 3/4] Pass `$post` to `get_permalink()` --- includes/Discovery.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/includes/Discovery.php b/includes/Discovery.php index 260c0015262e..7d1b2501cdaf 100644 --- a/includes/Discovery.php +++ b/includes/Discovery.php @@ -112,8 +112,8 @@ protected function get_schemaorg_metadata() { $metadata, [ '@type' => 'BlogPosting', - 'mainEntityOfPage' => get_permalink(), - 'headline' => get_the_title(), + 'mainEntityOfPage' => get_permalink( $post ), + 'headline' => get_the_title( $post ), 'datePublished' => mysql2date( 'c', $post->post_date_gmt, false ), 'dateModified' => mysql2date( 'c', $post->post_modified_gmt, false ), ] From 667c2953d2e78070bfc44f18e89fa2dcba5ae690 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Wed, 3 Jun 2020 14:27:37 +0200 Subject: [PATCH 4/4] use Article type --- includes/Discovery.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/includes/Discovery.php b/includes/Discovery.php index 7d1b2501cdaf..f3050107f224 100644 --- a/includes/Discovery.php +++ b/includes/Discovery.php @@ -86,6 +86,8 @@ public function print_schemaorg_metadata() { /** * Get schema.org metadata for the current query. * + * @see https://developers.google.com/search/docs/guides/enable-web-stories + * * @return array $metadata All schema.org metadata for the post. */ protected function get_schemaorg_metadata() { @@ -111,7 +113,7 @@ protected function get_schemaorg_metadata() { $metadata = array_merge( $metadata, [ - '@type' => 'BlogPosting', + '@type' => 'Article', 'mainEntityOfPage' => get_permalink( $post ), 'headline' => get_the_title( $post ), 'datePublished' => mysql2date( 'c', $post->post_date_gmt, false ),