/** * Add Schema.org Microdata in the footer. * * Mainly used to embed microdata to front page, posts index page and archives. */ function amt_add_jsonld_schemaorg_metadata_head($post, $attachments, $embedded_media, $options) { if (apply_filters('amt_exclude_schemaorg_metadata', false)) { return array(); } $do_auto_schemaorg = $options["auto_schemaorg"] == "1" ? true : false; if (!$do_auto_schemaorg) { return array(); } // Check if the microdata or the JSON-LD schema.org generator should be used. if ($options["schemaorg_force_jsonld"] == "0") { // Here we check for AMP page https://www.ampproject.org/ // For AMP pages, if the Schema.org microdata generator has been enabled, // we enforce the JSON+LD form instead of microdata. if ($do_auto_schemaorg && function_exists('is_amp_endpoint') && is_amp_endpoint()) { // Do nothing and let it proceed with forced generation of JSON+LD Schema.org metadata. } else { return array(); } } $metadata_arr = array(); // Context $metadata_arr['@context'] = 'http://schema.org'; // TODO: Check if this is_paged() check is needed. If removed, make sure that titles and descriptions are passed through multipage function. if (is_paged()) { // // Currently we do not support adding Schema.org metadata on // paged archives, if page number is >=2 // // NOTE: This refers to an archive or the main page being split up over // several pages, this does not refer to a Post or Page whose content // has been divided into pages using the <!--nextpage--> QuickTag. // // Multipage content IS processed below. // return array(); } // Custom content override if (amt_is_custom($post, $options)) { // Return metadata with: // add_filter( 'amt_custom_metadata_jsonld_schemaorg', 'my_function', 10, 5 ); // Return an array of meta tags. Array item format: ['key_can_be_whatever'] = '<meta name="foo" content="bar" />' $metadata_arr = apply_filters('amt_custom_metadata_jsonld_schemaorg', $metadata_arr, $post, $options, $attachments, $embedded_media); // Default fron tpage displaying the latest posts. } elseif (amt_is_default_front_page()) { // On the front page we are adding two top level entities, so we remove // the existing context, as the entities need to be in an array and each // array item needs its own context. unset($metadata_arr['@context']); // Organization // // NOTICE: // Even if the front page has been set as the source of profile, this // this does not work with the default front page with the latest posts. // This is becuase this page does not have an author, which is essential // for the generated metadata on a page that is supposed to be a profile. // Therefore, an Organization object is always generated on the default // front page and it is never treated as a profile page by Add-Meta-Tags. // $organization_arr = array(); // Context $organization_arr['@context'] = 'http://schema.org'; // ID $organization_arr['@id'] = amt_get_schemaorg_entity_id('organization'); $organization_arr = array_merge($organization_arr, amt_get_jsonld_schemaorg_publisher_array($options)); // mainEntityOfPage $organization_arr['mainEntityOfPage'] = esc_url(trailingslashit(get_bloginfo('url'))); // Get publisher/mainEntity metatags // $metadata_arr = array_merge( $metadata_arr, amt_get_schemaorg_publisher_metatags( $options ) ); // WebSite $website_arr = array(); // Context $website_arr['@context'] = 'http://schema.org'; // ID $website_arr['@id'] = amt_get_schemaorg_entity_id('website'); // Type $website_arr['@type'] = 'WebSite'; // name $website_arr['name'] = esc_attr(get_bloginfo('name')); // headline - contains title information $website_arr['headline'] = esc_attr(amt_get_title_for_metadata($options, $post)); // alternateName (The WordPress tag line is used.) // TODO: use tag line. Needs feedback! // url $website_arr['url'] = esc_url_raw(trailingslashit(get_bloginfo('url'))); // publisher // $website_arr['publisher'] = array( '@id' => esc_attr(amt_get_schemaorg_entity_id('organization') ) ); // SearchAction // Scope BEGIN: SearchAction: http://schema.org/SearchAction // $metadata_arr[] = '<!-- Scope BEGIN: SearchAction -->'; // $metadata_arr[] = '<span itemprop="potentialAction" itemscope itemtype="http://schema.org/SearchAction">'; $website_arr['potentialAction'] = array(); $website_arr['potentialAction']['@type'] = 'SearchAction'; // target // Scope BEGIN: EntryPoint: http://schema.org/EntryPoint $website_arr['potentialAction']['target'] = array(); $website_arr['potentialAction']['target']['@type'] = 'EntryPoint'; // urlTemplate $website_arr['potentialAction']['target']['urlTemplate'] = esc_url_raw(trailingslashit(get_bloginfo('url'))) . '?s={search_term}'; // Scope END: EntryPoint // $metadata_arr[] = '</span> <!-- Scope END: EntryPoint -->'; // query-input // Scope BEGIN: PropertyValueSpecification: http://schema.org/PropertyValueSpecification //$metadata_arr[] = '<span itemprop="query-input" itemscope itemtype="http://schema.org/PropertyValueSpecification">'; $website_arr['potentialAction']['query-input'] = array(); $website_arr['potentialAction']['query-input']['@type'] = 'PropertyValueSpecification'; // valueRequired $website_arr['potentialAction']['query-input']['valueRequired'] = 'True'; // valueName $website_arr['potentialAction']['query-input']['valueName'] = 'search_term'; // Scope END: PropertyValueSpecification // $metadata_arr[] = '</span> <!-- Scope END: PropertyValueSpecification -->'; // Scope END: SearchAction // $metadata_arr[] = '</span> <!-- Scope END: SearchAction -->'; // Scope END: WebSite // $metadata_arr[] = '</span> <!-- Scope END: WebSite -->'; $metadata_arr = array($organization_arr, $website_arr); // Front page using a static page } elseif (amt_is_static_front_page()) { // On the front page we are adding two top level entities, so we remove // the existing context, as the entities need to be in an array and each // array item needs its own context. unset($metadata_arr['@context']); $main_entity_arr = array(); // Context $main_entity_arr['@context'] = 'http://schema.org'; if ($options['author_profile_source'] == 'frontpage') { // ID $main_entity_arr['@id'] = amt_get_schemaorg_entity_id('person'); // Author // Scope BEGIN: Person: http://schema.org/Person // $metadata_arr[] = '<!-- Scope BEGIN: Person -->'; // $metadata_arr[] = '<span itemprop="author" itemscope itemtype="http://schema.org/Person"' . amt_get_schemaorg_itemref('person_author') . '>'; // Get author metatags $main_entity_arr = array_merge($main_entity_arr, amt_get_jsonld_schemaorg_author_array($post->post_author, $options)); // mainEntityOfPage $main_entity_arr['mainEntityOfPage'] = esc_url(trailingslashit(get_bloginfo('url'))); // Scope END: Person // $metadata_arr[] = '</span> <!-- Scope END: Person -->'; } else { // ID $main_entity_arr['@id'] = amt_get_schemaorg_entity_id('organization'); // Organization $main_entity_arr = array_merge($main_entity_arr, amt_get_jsonld_schemaorg_publisher_array($options)); // mainEntityOfPage $main_entity_arr['mainEntityOfPage'] = esc_url(trailingslashit(get_bloginfo('url'))); // Get publisher/mainEntity metatags // $metadata_arr = array_merge( $metadata_arr, amt_get_schemaorg_publisher_metatags( $options ) ); } // WebSite $website_arr = array(); // Context $website_arr['@context'] = 'http://schema.org'; // ID $website_arr['@id'] = amt_get_schemaorg_entity_id('website'); // Type $website_arr['@type'] = 'WebSite'; // name $website_arr['name'] = esc_attr(get_bloginfo('name')); // headline - contains title information $website_arr['headline'] = esc_attr(amt_get_title_for_metadata($options, $post)); // alternateName (The WordPress tag line is used.) // TODO: use tag line. Needs feedback! // url $website_arr['url'] = esc_url_raw(trailingslashit(get_bloginfo('url'))); // if ( $options['author_profile_source'] == 'frontpage' ) { // author //$website_arr['author'] = array( '@id' => esc_attr(amt_get_schemaorg_entity_id('person') ) ); // } else { // publisher //$website_arr['publisher'] = array( '@id' => esc_attr(amt_get_schemaorg_entity_id('organization') ) ); // } // SearchAction // Scope BEGIN: SearchAction: http://schema.org/SearchAction // $metadata_arr[] = '<!-- Scope BEGIN: SearchAction -->'; // $metadata_arr[] = '<span itemprop="potentialAction" itemscope itemtype="http://schema.org/SearchAction">'; $website_arr['potentialAction'] = array(); $website_arr['potentialAction']['@type'] = 'SearchAction'; // target // Scope BEGIN: EntryPoint: http://schema.org/EntryPoint $website_arr['potentialAction']['target'] = array(); $website_arr['potentialAction']['target']['@type'] = 'EntryPoint'; // urlTemplate $website_arr['potentialAction']['target']['urlTemplate'] = esc_url_raw(trailingslashit(get_bloginfo('url'))) . '?s={search_term}'; // Scope END: EntryPoint // $metadata_arr[] = '</span> <!-- Scope END: EntryPoint -->'; // query-input // Scope BEGIN: PropertyValueSpecification: http://schema.org/PropertyValueSpecification //$metadata_arr[] = '<span itemprop="query-input" itemscope itemtype="http://schema.org/PropertyValueSpecification">'; $website_arr['potentialAction']['query-input'] = array(); $website_arr['potentialAction']['query-input']['@type'] = 'PropertyValueSpecification'; // valueRequired $website_arr['potentialAction']['query-input']['valueRequired'] = 'True'; // valueName $website_arr['potentialAction']['query-input']['valueName'] = 'search_term'; // Scope END: PropertyValueSpecification // $metadata_arr[] = '</span> <!-- Scope END: PropertyValueSpecification -->'; // Scope END: SearchAction // $metadata_arr[] = '</span> <!-- Scope END: SearchAction -->'; // Scope END: WebSite // $metadata_arr[] = '</span> <!-- Scope END: WebSite -->'; $metadata_arr = array($main_entity_arr, $website_arr); // Author archive } elseif (is_author()) { // Author object // NOTE: Inside the author archives `$post->post_author` does not contain the author object. // In this case the $post (get_queried_object()) contains the author object itself. // We also can get the author object with the following code. Slug is what WP uses to construct urls. // $author = get_user_by( 'slug', get_query_var( 'author_name' ) ); // Also, ``get_the_author_meta('....', $author)`` returns nothing under author archives. // Access user meta with: $author->description, $author->user_email, etc // $author = get_queried_object(); $author = $post; // Person // Scope BEGIN: Person: http://schema.org/Person // $metadata_arr[] = '<!-- Scope BEGIN: Person -->'; // $metadata_arr[] = '<span itemscope itemtype="http://schema.org/Person"' . amt_get_schemaorg_itemref('person_author') . '>'; $metadata_arr['@type'] = 'Person'; // headline - contains title information // NOTE: Not supported for person //$metadata_arr['headline'] = esc_attr( amt_get_title_for_metadata($options, $author) ); // Get author metatags // $metadata_arr = array_merge( $metadata_arr, amt_get_schemaorg_author_metatags( $author->ID, $options ) ); $metadata_arr = array_merge($metadata_arr, amt_get_jsonld_schemaorg_author_array($author->ID, $options)); // mainEntityOfPage $metadata_arr['mainEntityOfPage'] = esc_url(get_author_posts_url($author->ID)); // Scope END: Person // $metadata_arr[] = '</span> <!-- Scope END: Person -->'; } elseif (amt_is_product()) { // Scope BEGIN: Product: http://schema.org/Product // $metadata_arr[] = '<!-- Scope BEGIN: Product -->'; // $metadata_arr[] = '<div itemscope itemtype="http://schema.org/Product"' . amt_get_schemaorg_itemref('product') . '>'; // Schema.org type $metadata_arr['@type'] = 'Product'; // ID $metadata_arr['@id'] = amt_get_schemaorg_entity_id('product'); // URL - Uses amt_get_permalink_for_multipage() $metadata_arr['url'] = esc_url_raw(amt_get_permalink_for_multipage($post)); // mainEntityOfPage $metadata_arr['mainEntityOfPage'] = esc_url(amt_get_permalink_for_multipage($post)); // name // Note: Contains multipage information through amt_process_paged() $metadata_arr['name'] = esc_attr(amt_process_paged(strip_tags(get_the_title($post->ID)))); // headline - contains title information //$metadata_arr['headline'] = esc_attr( amt_get_title_for_metadata($options, $post) ); // Description - We use the description defined by Add-Meta-Tags // Note: Contains multipage information through amt_process_paged() $content_desc = amt_get_content_description($post); //if ( empty($content_desc) ) { // // Use the post body as the description. Product objects do not support body text. // // TODO: ERROR here $post_body var does not exist // $content_desc = sanitize_text_field( amt_sanitize_description( $post_body ) ); //} if (!empty($content_desc)) { $metadata_arr['description'] = esc_attr(amt_process_paged($content_desc)); } // Dates $metadata_arr['releaseDate'] = esc_attr(amt_iso8601_date($post->post_date)); // Images $metadata_arr['image'] = array(); // First check if a global image override URL has been entered. // If yes, use this image URL and override all other images. $image_data = amt_get_image_data(amt_get_post_meta_image_url($post->ID)); if (!empty($image_data)) { $image_size = apply_filters('amt_image_size_product', 'full'); $image_meta_array = amt_get_jsonld_schemaorg_image_array($options, $image_data, $size = $image_size); if (!empty($image_meta_array)) { $metadata_arr['image'] = array(); $metadata_arr['image'][] = $image_meta_array; } //$global_image_override_url = amt_get_post_meta_image_url($post->ID); //if ( ! empty( $global_image_override_url ) ) { // $metadata_arr[] = '<!-- Scope BEGIN: ImageObject -->'; // $metadata_arr[] = '<span itemprop="image" itemscope itemtype="http://schema.org/ImageObject">'; // $current_image_obj = array(); // $current_image_obj['@type'] = 'ImageObject'; // $current_image_obj['url'] = esc_url_raw( $global_image_override_url ); // $current_image_obj['contentUrl'] = esc_url_raw( $global_image_override_url ); // $metadata_arr['image'][] = $current_image_obj; // $metadata_arr[] = '</span> <!-- Scope END: ImageObject -->'; // Further image processing } else { // Set to true if any image attachments are found. Use to finally add the default image // if no image attachments have been found. $has_images = false; // Scope BEGIN: ImageObject: http://schema.org/ImageObject // Image - Featured image is checked first, so that it can be the first associated image. if (function_exists('has_post_thumbnail') && has_post_thumbnail($post->ID)) { // Get the image attachment object $image = get_post(get_post_thumbnail_id($post->ID)); // metadata BEGIN // $metadata_arr[] = '<!-- Scope BEGIN: ImageObject -->'; // $metadata_arr[] = '<span itemprop="image" itemscope itemtype="http://schema.org/ImageObject">'; // Allow filtering of the image size. $image_size = apply_filters('amt_image_size_product', 'full'); // Get image metatags. $metadata_arr['image'][] = amt_get_jsonld_schemaorg_image_array($options, $image, $size = $image_size); // metadata END // $metadata_arr[] = '</span> <!-- Scope END: ImageObject -->'; // Images have been found. $has_images = true; } // Scope END: ImageObject // If no images have been found so far use the default image, if set. // Scope BEGIN: ImageObject: http://schema.org/ImageObject if ($has_images === false) { $image_data = amt_get_default_image_data(); if (!empty($image_data)) { $image_size = apply_filters('amt_image_size_product', 'full'); $image_meta_array = amt_get_jsonld_schemaorg_image_array($options, $image_data, $size = $image_size); if (!empty($image_meta_array)) { $metadata_arr['image'] = array(); $metadata_arr['image'][] = $image_meta_array; } } // $metadata_arr[] = '<!-- Scope BEGIN: ImageObject -->'; // $metadata_arr[] = '<span itemprop="image" itemscope itemtype="http://schema.org/ImageObject">'; //$current_image_obj = array(); //$current_image_obj['@type'] = 'ImageObject'; //$current_image_obj['url'] = esc_url_raw( $options["default_image_url"] ); //$current_image_obj['contentUrl'] = esc_url_raw( $options["default_image_url"] ); //$metadata_arr['image'][] = $current_image_obj; // $metadata_arr[] = '</span> <!-- Scope END: ImageObject -->'; } // Scope END: ImageObject } // Extend the current metadata with properties of the Product object. // See: http://schema.org/Product $metadata_arr = apply_filters('amt_product_data_jsonld_schemaorg', $metadata_arr, $post); // Scope END: Product // $metadata_arr[] = '</div> <!-- Scope END: Product -->'; // Filtering of the generated Schema.org metadata $metadata_arr = apply_filters('amt_jsonld_schemaorg_metadata_product', $metadata_arr); // Add post body // Remove last closing '</div>' tag, add post body and re-add the closing div afterwards. // $closing_product_tag = array_pop($metadata_arr); // Product objects do not support a 'text' itemprop. We just add a div for now // for consistency with Article objects. // TODO: it should allow filtering '<div>' // $metadata_arr[] = '<div> <!-- Product text body: BEGIN -->'; // $metadata_arr[] = $post_body; // $metadata_arr[] = '</div> <!-- Product text body: END -->'; // Now add closing tag for Article // $metadata_arr[] = $closing_product_tag; // Attachemnts } elseif (is_attachment()) { $mime_type = get_post_mime_type($post->ID); //$attachment_type = strstr( $mime_type, '/', true ); // See why we do not use strstr(): http://www.codetrax.org/issues/1091 $attachment_type = preg_replace('#\\/[^\\/]*$#', '', $mime_type); // Early metatags - Scope starts if ('image' == $attachment_type) { // Scope BEGIN: ImageObject: http://schema.org/ImageObject // $metadata_arr[] = '<!-- Scope BEGIN: ImageObject -->'; // $metadata_arr[] = '<div itemscope itemtype="http://schema.org/ImageObject"' . amt_get_schemaorg_itemref('attachment_image') . '>'; } elseif ('video' == $attachment_type) { // Scope BEGIN: VideoObject: http://schema.org/VideoObject // $metadata_arr[] = '<!-- Scope BEGIN: VideoObject -->'; // $metadata_arr[] = '<div itemscope itemtype="http://schema.org/VideoObject"' . amt_get_schemaorg_itemref('attachment_video') . '>'; // Schema.org type $metadata_arr['@type'] = 'VideoObject'; } elseif ('audio' == $attachment_type) { // Scope BEGIN: AudioObject: http://schema.org/AudioObject // $metadata_arr[] = '<!-- Scope BEGIN: AudioObject -->'; // $metadata_arr[] = '<div itemscope itemtype="http://schema.org/AudioObject"' . amt_get_schemaorg_itemref('attachment_audio') . '>'; // Schema.org type $metadata_arr['@type'] = 'AudioObject'; } else { // we do not currently support other attachment types, so we stop processing here return array(); } // Metadata common to all attachments // Do not add a publisher on personal websites (static front page is source of author profile). if ($options['author_profile_source'] != 'frontpage' || !amt_has_page_on_front()) { // Publisher // Scope BEGIN: Organization: http://schema.org/Organization // $metadata_arr[] = '<!-- Scope BEGIN: Organization -->'; // $metadata_arr[] = '<span itemprop="publisher" itemscope itemtype="http://schema.org/Organization"' . amt_get_schemaorg_itemref('organization') . '>'; // Get publisher metatags // $metadata_arr = array_merge( $metadata_arr, amt_get_schemaorg_publisher_metatags( $options, $post->post_author ) ); $metadata_arr['publisher'] = amt_get_jsonld_schemaorg_publisher_array($options, $post->post_author); // Scope END: Organization // $metadata_arr[] = '</span> <!-- Scope END: Organization -->'; } // Author // Scope BEGIN: Person: http://schema.org/Person // $metadata_arr[] = '<!-- Scope BEGIN: Person -->'; // $metadata_arr[] = '<span itemprop="author" itemscope itemtype="http://schema.org/Person"' . amt_get_schemaorg_itemref('person_author') . '>'; // Get author metatags $metadata_arr['author'] = amt_get_jsonld_schemaorg_author_array($post->post_author, $options); // Scope END: Person // $metadata_arr[] = '</span> <!-- Scope END: Person -->'; // name $metadata_arr['name'] = esc_attr(strip_tags(get_the_title($post->ID))); // headline - contains title information $metadata_arr['headline'] = esc_attr(amt_get_title_for_metadata($options, $post)); // Description - We use the description defined by Add-Meta-Tags $content_desc = amt_get_content_description($post); if (!empty($content_desc)) { $metadata_arr['description'] = esc_attr($content_desc); } // Dates $metadata_arr['datePublished'] = esc_attr(amt_iso8601_date($post->post_date)); $metadata_arr['dateModified'] = esc_attr(amt_iso8601_date($post->post_modified)); $metadata_arr['copyrightYear'] = esc_attr(mysql2date('Y', $post->post_date)); // Language $metadata_arr['inLanguage'] = esc_attr(str_replace('-', '_', amt_get_language_content($options, $post))); // Thumbnail // A featured image is supported by video and audio attachments. // If one is set, then it is set as the thumbnail of the video/audio object. if ('video' == $attachment_type || 'audio' == $attachment_type) { if (function_exists('has_post_thumbnail') && has_post_thumbnail($post->ID)) { // Thumbnail URL of the featured image $image_size = apply_filters('amt_image_size_attachment', 'full'); $thumbnail_info = wp_get_attachment_image_src(get_post_thumbnail_id($post->ID), $image_size); $metadata_arr['thumbnailUrl'] = esc_url_raw($thumbnail_info[0]); // Currently we do not add a full ImageObject for the attachment's featured image. // TODO: future } } // mainEntityOfPage $metadata_arr['mainEntityOfPage'] = esc_url(get_permalink($post->ID)); // Metadata specific to each attachment type if ('image' == $attachment_type) { // Allow filtering of the image size. $image_size = apply_filters('amt_image_size_attachment', 'full'); // Get image metatags. $post is an image object. $metadata_arr = array_merge($metadata_arr, amt_get_jsonld_schemaorg_image_array($options, $post, $size = $image_size, $is_representative = true)); // Add the post body here // $metadata_arr[] = $post_body; // Scope END: ImageObject // $metadata_arr[] = '</div> <!-- Scope END: ImageObject -->'; } elseif ('video' == $attachment_type) { // Video specific metatags // URL (links to image file) //$metadata_arr['url'] = esc_url_raw( get_permalink( $post->ID ) ); $metadata_arr['url'] = esc_url_raw(wp_get_attachment_url($post->ID)); // sameAs (links to attachment page) $metadata_arr['sameAs'] = esc_url_raw(get_permalink($post->ID)); $metadata_arr['contentUrl'] = esc_url_raw(wp_get_attachment_url($post->ID)); $metadata_arr['encodingFormat'] = esc_attr($mime_type); // Required by Google $metadata_arr['uploadDate'] = esc_attr(amt_iso8601_date($post->post_date)); // Add the post body here // $metadata_arr[] = $post_body; // Scope END: VideoObject // $metadata_arr[] = '</div> <!-- Scope END: VideoObject -->'; } elseif ('audio' == $attachment_type) { // Audio specific metatags // URL (links to image file) //$metadata_arr['url'] = esc_url_raw( get_permalink( $post->ID ) ); $metadata_arr['url'] = esc_url_raw(wp_get_attachment_url($post->ID)); // sameAs (links to attachment page) $metadata_arr['sameAs'] = esc_url_raw(get_permalink($post->ID)); $metadata_arr['contentUrl'] = esc_url_raw(wp_get_attachment_url($post->ID)); $metadata_arr['encodingFormat'] = esc_attr($mime_type); // Add the post body here // $metadata_arr[] = $post_body; // Scope END: AudioObject // $metadata_arr[] = '</div> <!-- Scope END: AudioObject -->'; } // Filtering of the generated Schema.org metadata $metadata_arr = apply_filters('amt_jsonld_schemaorg_metadata_attachment', $metadata_arr); // Content // Posts, pages, custom content types (attachments excluded, caught in previous clause) // Note: content might be multipage. Process with amt_process_paged() wherever needed. } elseif (is_singular()) { // Set main metadata entity. By default this set to Article. $main_content_object = 'Article'; // Check for Page // Main entity is set to WebPage on pages // DEV NOTE: Since many themes already set the WebPage itemscope on the // body element of the web page, set it to WebPage automatically would // result in duplicate entities. So this has to be done manually via // a filtering function. // if ( is_page() ) { // $main_content_object = 'WebPage'; // } // Check for Review $review_data = amt_get_review_data($post); if (!empty($review_data)) { $main_content_object = 'Review'; } // Allow filtering the main metadata object for content. $main_content_object = apply_filters('amt_schemaorg_object_main', $main_content_object); // Scope BEGIN: Article: http://schema.org/Article // $metadata_arr[] = '<!-- Scope BEGIN: ' . esc_attr($main_content_object) . ' -->'; // $metadata_arr[] = '<div itemscope itemtype="http://schema.org/' . esc_attr($main_content_object) . '"' . amt_get_schemaorg_itemref('content') . '>'; // Schema.org type $metadata_arr['@type'] = esc_attr($main_content_object); // Do not add a publisher on personal websites (static front page is source of author profile). if ($options['author_profile_source'] != 'frontpage' || !amt_has_page_on_front()) { // Publisher // Scope BEGIN: Organization: http://schema.org/Organization // $metadata_arr[] = '<!-- Scope BEGIN: Organization -->'; // $metadata_arr[] = '<span itemprop="publisher" itemscope itemtype="http://schema.org/Organization"' . amt_get_schemaorg_itemref('organization') . '>'; // Get publisher metatags // $metadata_arr = array_merge( $metadata_arr, amt_get_schemaorg_publisher_metatags( $options, $post->post_author ) ); $metadata_arr['publisher'] = amt_get_jsonld_schemaorg_publisher_array($options, $post->post_author); // Scope END: Organization // $metadata_arr[] = '</span> <!-- Scope END: Organization -->'; } // Author // Scope BEGIN: Person: http://schema.org/Person // $metadata_arr[] = '<!-- Scope BEGIN: Person -->'; // $metadata_arr[] = '<span itemprop="author" itemscope itemtype="http://schema.org/Person"' . amt_get_schemaorg_itemref('person_author') . '>'; // Get author metatags // $metadata_arr = array_merge( $metadata_arr, amt_get_schemaorg_author_metatags( $post->post_author, $options ) ); $metadata_arr['author'] = amt_get_jsonld_schemaorg_author_array($post->post_author, $options); // Scope END: Person // $metadata_arr[] = '</span> <!-- Scope END: Person -->'; // URL - Uses amt_get_permalink_for_multipage() $metadata_arr['url'] = esc_url_raw(amt_get_permalink_for_multipage($post)); // mainEntityOfPage $metadata_arr['mainEntityOfPage'] = esc_url(amt_get_permalink_for_multipage($post)); // Dates $metadata_arr['datePublished'] = esc_attr(amt_iso8601_date($post->post_date)); $metadata_arr['dateModified'] = esc_attr(amt_iso8601_date($post->post_modified)); $metadata_arr['copyrightYear'] = esc_attr(mysql2date('Y', $post->post_date)); // Language $metadata_arr['inLanguage'] = esc_attr(str_replace('-', '_', amt_get_language_content($options, $post))); // name // Note: Contains multipage information through amt_process_paged() $metadata_arr['name'] = esc_attr(amt_process_paged(strip_tags(get_the_title($post->ID)))); // headline - contains title information $metadata_arr['headline'] = esc_attr(amt_get_title_for_metadata($options, $post)); // Description - We use the description defined by Add-Meta-Tags // Note: Contains multipage information through amt_process_paged() $content_desc = amt_get_content_description($post); if (!empty($content_desc)) { $metadata_arr['description'] = esc_attr(amt_process_paged($content_desc)); } /* // Section: We use the first category as the section $first_cat = sanitize_text_field( amt_sanitize_keywords( amt_get_first_category($post) ) ); if (!empty($first_cat)) { $metadata_arr[] = '<meta itemprop="articleSection" content="' . esc_attr( $first_cat ) . '" />'; } */ // Add articleSection in Article object only. if ($main_content_object == 'Article') { $categories = get_the_category($post->ID); $categories = apply_filters('amt_post_categories_for_schemaorg', $categories); foreach ($categories as $cat) { $section = trim($cat->cat_name); if (!empty($section) && $cat->slug != 'uncategorized') { $metadata_arr['articleSection'] = esc_attr($section); } } } // Add review properties if Review if ($main_content_object == 'Review') { // $metadata_arr[] = '<!-- Review Information BEGIN -->'; // $metadata_arr[] = amt_get_review_info_box( $review_data ); // $metadata_arr[] = '<!-- Review Information END -->'; // Reviewed Item $metadata_arr['itemReviewed'] = array(); $metadata_arr['itemReviewed']['@type'] = esc_attr($review_data['object']); $metadata_arr['itemReviewed']['name'] = esc_attr($review_data['name']); $metadata_arr['itemReviewed']['sameAs'] = esc_url_raw($review_data['sameAs']); // Extra properties of reviewed item foreach ($review_data['extra'] as $key => $value) { if (is_array($value)) { // Add sub entity // If it is an array, the 'object' property is mandatory if (!array_key_exists('object', $value)) { continue; } $metadata_arr['itemReviewed'][esc_attr($key)] = array(); $metadata_arr['itemReviewed'][esc_attr($key)]['@type'] = esc_attr($value['object']); foreach ($value as $subkey => $subvalue) { if ($subkey != 'object') { if (in_array($subkey, array('url', 'sameAs'))) { $metadata_arr['itemReviewed'][esc_attr($key)][esc_attr($subkey)] = esc_url_raw($subvalue); } else { $metadata_arr['itemReviewed'][esc_attr($key)][esc_attr($subkey)] = esc_attr($subvalue); } } } } else { // Add simple meta element $metadata_arr['itemReviewed'][esc_attr($key)] = esc_attr($value); } } // Rating $metadata_arr['reviewRating'] = array(); $metadata_arr['reviewRating']['@type'] = 'Rating'; $metadata_arr['reviewRating']['ratingValue'] = esc_attr($review_data['ratingValue']); $bestrating = apply_filters('amt_schemaorg_review_bestrating', '5'); $metadata_arr['reviewRating']['bestRating'] = esc_attr($bestrating); } // Keywords - We use the keywords defined by Add-Meta-Tags $keywords = amt_get_content_keywords($post); if (!empty($keywords)) { $metadata_arr['keywords'] = esc_attr($keywords); } // Referenced Items $referenced_url_list = amt_get_referenced_items($post); if (!empty($referenced_url_list)) { $metadata_arr['referencedItem'] = array(); foreach ($referenced_url_list as $referenced_url) { $referenced_url = trim($referenced_url); if (!empty($referenced_url)) { $metadata_arr['referencedItem'][] = esc_url_raw($referenced_url); } } } // Images $metadata_arr['image'] = array(); // First check if a global image override URL has been entered. // If yes, use this image URL and override all other images. $image_data = amt_get_image_data(amt_get_post_meta_image_url($post->ID)); if (!empty($image_data)) { $image_size = apply_filters('amt_image_size_content', 'full'); $image_meta_array = amt_get_jsonld_schemaorg_image_array($options, $image_data, $size = $image_size); if (!empty($image_meta_array)) { $metadata_arr['image'] = array(); $metadata_arr['image'][] = $image_meta_array; } //$global_image_override_url = amt_get_post_meta_image_url($post->ID); //if ( ! empty( $global_image_override_url ) ) { // $metadata_arr[] = '<!-- Scope BEGIN: ImageObject -->'; // $metadata_arr[] = '<span itemprop="image" itemscope itemtype="http://schema.org/ImageObject">'; // $current_image_obj = array(); // $current_image_obj['@type'] = 'ImageObject'; // $current_image_obj['url'] = esc_url_raw( $global_image_override_url ); // $current_image_obj['contentUrl'] = esc_url_raw( $global_image_override_url ); // $metadata_arr['image'][] = $current_image_obj; // $metadata_arr[] = '<meta itemprop="contentUrl" content="' . esc_url_raw( $global_image_override_url ) . '" />'; // $metadata_arr[] = '</span> <!-- Scope END: ImageObject -->'; // Further image processing } else { // Media Limits $image_limit = amt_metadata_get_image_limit($options); $video_limit = amt_metadata_get_video_limit($options); $audio_limit = amt_metadata_get_audio_limit($options); // Counters $ic = 0; // image counter $vc = 0; // video counter $ac = 0; // audio counter // We store the featured image ID in this variable so that it can easily be excluded // when all images are parsed from the $attachments array. $featured_image_id = 0; // Set to true if any image attachments are found. Use to finally add the default image // if no image attachments have been found. $has_images = false; // Scope BEGIN: ImageObject: http://schema.org/ImageObject // Image - Featured image is checked first, so that it can be the first associated image. if (function_exists('has_post_thumbnail') && has_post_thumbnail($post->ID)) { // Thumbnail URL // First add the thumbnail URL of the featured image $thumbnail_info = wp_get_attachment_image_src(get_post_thumbnail_id($post->ID), 'thumbnail'); $metadata_arr['thumbnailUrl'] = esc_url_raw($thumbnail_info[0]); // Add full image object for featured image. // Get the image attachment object $image = get_post(get_post_thumbnail_id($post->ID)); // metadata BEGIN // $metadata_arr[] = '<!-- Scope BEGIN: ImageObject -->'; // $metadata_arr[] = '<span itemprop="image" itemscope itemtype="http://schema.org/ImageObject">'; // Allow filtering of the image size. $image_size = apply_filters('amt_image_size_content', 'full'); // Get image metatags. // $metadata_arr = array_merge( $metadata_arr, amt_get_schemaorg_image_metatags( $options, $image, $size=$image_size ) ); $metadata_arr['image'][] = amt_get_jsonld_schemaorg_image_array($options, $image, $size = $image_size); // metadata END // $metadata_arr[] = '</span> <!-- Scope END: ImageObject -->'; // Finally, set the $featured_image_id $featured_image_id = get_post_thumbnail_id($post->ID); // Images have been found. $has_images = true; // Increase image counter $ic++; } // Scope END: ImageObject // Process all attachments and add metatags (featured image will be excluded) foreach ($attachments as $attachment) { // Excluded the featured image since if ($attachment->ID != $featured_image_id) { $mime_type = get_post_mime_type($attachment->ID); //$attachment_type = strstr( $mime_type, '/', true ); // See why we do not use strstr(): http://www.codetrax.org/issues/1091 $attachment_type = preg_replace('#\\/[^\\/]*$#', '', $mime_type); if ('image' == $attachment_type && $ic < $image_limit) { // metadata BEGIN // $metadata_arr[] = '<!-- Scope BEGIN: ImageObject -->'; // $metadata_arr[] = '<span itemprop="image" itemscope itemtype="http://schema.org/ImageObject">'; // Allow filtering of the image size. $image_size = apply_filters('amt_image_size_content', 'full'); // Get image metatags. // $metadata_arr = array_merge( $metadata_arr, amt_get_schemaorg_image_metatags( $options, $attachment, $size=$image_size ) ); $metadata_arr['image'][] = amt_get_jsonld_schemaorg_image_array($options, $attachment, $size = $image_size); // metadata END // $metadata_arr[] = '</span> <!-- Scope END: ImageObject -->'; // Images have been found. $has_images = true; // Increase image counter $ic++; } elseif ('video' == $attachment_type && $vc < $video_limit) { // Scope BEGIN: VideoObject: http://schema.org/VideoObject // $metadata_arr[] = '<!-- Scope BEGIN: VideoObject -->'; // $metadata_arr[] = '<span itemprop="video" itemscope itemtype="http://schema.org/VideoObject">'; // Video specific metatags // URL (for attachments: links to attachment page) $current_video_obj = array(); $current_video_obj['@type'] = 'VideoObject'; // URL (links to image file) //$current_video_obj['url'] = esc_url_raw( get_permalink( $attachment->ID ) ); $current_video_obj['url'] = esc_url_raw(wp_get_attachment_url($attachment->ID)); // sameAs (links to attachment page) $current_video_obj['sameAs'] = esc_url_raw(get_permalink($attachment->ID)); $current_video_obj['contentUrl'] = esc_url_raw(wp_get_attachment_url($attachment->ID)); $current_video_obj['encodingFormat'] = esc_attr($mime_type); // name $current_video_obj['name'] = esc_attr(strip_tags(get_the_title($attachment->ID))); // Description - We use the description defined by Add-Meta-Tags $content_desc = amt_get_content_description($attachment); if (!empty($content_desc)) { $current_video_obj['description'] = esc_attr($content_desc); } // Thumbnail // A featured image is supported by video and audio attachments. // If one is set, then it is set as the thumbnail of the video/audio object. if (function_exists('has_post_thumbnail') && has_post_thumbnail($attachment->ID)) { // Thumbnail URL of the featured image $image_size = apply_filters('amt_image_size_content', 'full'); $thumbnail_info = wp_get_attachment_image_src(get_post_thumbnail_id($attachment->ID), $image_size); $current_video_obj['thumbnailUrl'] = esc_url_raw($thumbnail_info[0]); // Currently we do not add a full ImageObject for the attachment's featured image. // TODO: future } // uploadDate $current_video_obj['uploadDate'] = esc_attr(amt_iso8601_date($attachment->post_date)); $metadata_arr['video'][] = $current_video_obj; // Scope END: VideoObject // $metadata_arr[] = '</span> <!-- Scope END: VideoObject -->'; // Increase video counter $vc++; } elseif ('audio' == $attachment_type && $ac < $audio_limit) { // Scope BEGIN: AudioObject: http://schema.org/AudioObject // $metadata_arr[] = '<!-- Scope BEGIN: AudioObject -->'; // $metadata_arr[] = '<span itemprop="audio" itemscope itemtype="http://schema.org/AudioObject">'; // Audio specific metatags // URL (for attachments: links to attachment page) $current_audio_obj = array(); $current_audio_obj['@type'] = 'AudioObject'; // URL (links to image file) //$current_audio_obj['url'] = esc_url_raw( get_permalink( $attachment->ID ) ); $current_audio_obj['url'] = esc_url_raw(wp_get_attachment_url($attachment->ID)); // sameAs (links to attachment page) $current_audio_obj['sameAs'] = esc_url_raw(get_permalink($attachment->ID)); $current_audio_obj['contentUrl'] = esc_url_raw(wp_get_attachment_url($attachment->ID)); $current_audio_obj['encodingFormat'] = esc_attr($mime_type); // name $current_audio_obj['name'] = esc_attr(strip_tags(get_the_title($attachment->ID))); // Description - We use the description defined by Add-Meta-Tags $content_desc = amt_get_content_description($attachment); if (!empty($content_desc)) { $current_audio_obj['description'] = esc_attr($content_desc); } // Thumbnail // A featured image is supported by video and audio attachments. // If one is set, then it is set as the thumbnail of the video/audio object. if (function_exists('has_post_thumbnail') && has_post_thumbnail($attachment->ID)) { // Thumbnail URL of the featured image $image_size = apply_filters('amt_image_size_content', 'full'); $thumbnail_info = wp_get_attachment_image_src(get_post_thumbnail_id($attachment->ID), $image_size); $current_audio_obj['thumbnailUrl'] = esc_url_raw($thumbnail_info[0]); // Currently we do not add a full ImageObject for the attachment's featured image. // TODO: future } // uploadDate $current_audio_obj['uploadDate'] = esc_attr(amt_iso8601_date($attachment->post_date)); $metadata_arr['audio'][] = $current_audio_obj; // Scope END: AudioObject // $metadata_arr[] = '</span> <!-- Scope END: AudioObject -->'; // Increase audio counter $ac++; } } } // Embedded Media foreach ($embedded_media['images'] as $embedded_item) { if ($ic == $image_limit) { break; } // Scope BEGIN: ImageObject: http://schema.org/ImageObject // $metadata_arr[] = '<!-- Scope BEGIN: ImageObject -->'; // $metadata_arr[] = '<span itemprop="image" itemscope itemtype="http://schema.org/ImageObject">'; $current_image_obj = array(); $current_image_obj['@type'] = 'ImageObject'; // name (title) $current_image_obj['name'] = esc_attr($embedded_item['alt']); // caption $current_image_obj['caption'] = esc_attr($embedded_item['alt']); // alt $current_image_obj['text'] = esc_attr($embedded_item['alt']); // URL (links to image file) //$current_image_obj['url'] = esc_url_raw( $embedded_item['page'] ); $current_image_obj['url'] = esc_url_raw($embedded_item['image']); // sameAs (links to attachment page) $current_image_obj['sameAs'] = esc_url_raw($embedded_item['page']); // thumbnail url $current_image_obj['thumbnailUrl'] = esc_url_raw($embedded_item['thumbnail']); // main image $current_image_obj['contentUrl'] = esc_url_raw($embedded_item['image']); if (apply_filters('amt_extended_image_tags', true)) { $current_image_obj['width'] = esc_attr($embedded_item['width']); $current_image_obj['height'] = esc_attr($embedded_item['height']); $current_image_obj['encodingFormat'] = 'image/jpeg'; } // embedURL $current_image_obj['embedURL'] = esc_url_raw($embedded_item['player']); $metadata_arr['image'][] = $current_image_obj; // Scope END: ImageObject // $metadata_arr[] = '</span> <!-- Scope END: ImageObject -->'; // Images have been found. $has_images = true; // Increase image counter $ic++; } foreach ($embedded_media['videos'] as $embedded_item) { if ($vc == $video_limit) { break; } // Scope BEGIN: VideoObject: http://schema.org/VideoObject // See: http://googlewebmastercentral.blogspot.gr/2012/02/using-schemaorg-markup-for-videos.html // See: https://support.google.com/webmasters/answer/2413309?hl=en // $metadata_arr[] = '<!-- Scope BEGIN: VideoObject -->'; // $metadata_arr[] = '<span itemprop="video" itemscope itemtype="http://schema.org/VideoObject">'; $current_video_obj = array(); // Video Embed URL $current_video_obj['embedURL'] = esc_url_raw($embedded_item['player']); // playerType $current_video_obj['playerType'] = 'application/x-shockwave-flash'; // size $current_video_obj['width'] = esc_attr($embedded_item['width']); $current_video_obj['height'] = esc_attr($embedded_item['height']); $metadata_arr['video'][] = $current_video_obj; // Scope END: VideoObject // $metadata_arr[] = '</span> <!-- Scope END: VideoObject -->'; // Increase video counter $vc++; } foreach ($embedded_media['sounds'] as $embedded_item) { if ($ac == $audio_limit) { break; } // Scope BEGIN: AudioObject: http://schema.org/AudioObject // $metadata_arr[] = '<!-- Scope BEGIN: AudioObject -->'; // $metadata_arr[] = '<span itemprop="audio" itemscope itemtype="http://schema.org/AudioObject">'; $current_audio_obj = array(); // Audio Embed URL $current_audio_obj['embedURL'] = esc_url_raw($embedded_item['player']); // playerType $current_audio_obj['playerType'] = 'application/x-shockwave-flash'; $metadata_arr['audio'][] = $current_audio_obj; // Scope END: AudioObject // $metadata_arr[] = '</span> <!-- Scope END: AudioObject -->'; // Increase audio counter $ac++; } // If no images have been found so far use the default image, if set. // Scope BEGIN: ImageObject: http://schema.org/ImageObject if ($has_images === false) { $image_data = amt_get_default_image_data(); if (!empty($image_data)) { $image_size = apply_filters('amt_image_size_content', 'full'); $image_meta_array = amt_get_jsonld_schemaorg_image_array($options, $image_data, $size = $image_size); if (!empty($image_meta_array)) { $metadata_arr['image'] = array(); $metadata_arr['image'][] = $image_meta_array; } } // $metadata_arr[] = '<!-- Scope BEGIN: ImageObject -->'; // $metadata_arr[] = '<span itemprop="image" itemscope itemtype="http://schema.org/ImageObject">'; $current_image_obj = array(); $current_image_obj['@type'] = 'ImageObject'; $current_image_obj['url'] = esc_url_raw($options["default_image_url"]); $current_image_obj['contentUrl'] = esc_url_raw($options["default_image_url"]); $metadata_arr['image'][] = $current_image_obj; // $metadata_arr[] = '<meta itemprop="contentUrl" content="' . esc_url_raw( $options["default_image_url"] ) . '" />'; // $metadata_arr[] = '</span> <!-- Scope END: ImageObject -->'; } // Scope END: ImageObject } // Article Body // The article body is added after filtering the generated microdata below. // TODO: also check: comments, contributor, copyrightHolder, , creator, dateCreated, discussionUrl, editor, version (use post revision if possible) // Scope END: Article // $metadata_arr[] = '</div> <!-- Scope END: ' . esc_attr($main_content_object) . ' -->'; // Filtering of the generated Schema.org metadata $metadata_arr = apply_filters('amt_jsonld_schemaorg_metadata_content', $metadata_arr); // Add articleBody to Artice // Now add the article. Remove last closing '</span>' tag, add articleBody and re-add the closing span afterwards. // $closing_article_tag = array_pop($metadata_arr); // Use the 'text' itemprop by default for the main text body of the CreativeWork, // so it can be used by more subtypes than Article. // But set it explicitly to 'articleBody if the main entiry is 'Article' // or 'reviewBody' if the main entity is a 'Review'. $main_text_property = 'text'; if ($main_content_object == 'Article') { $main_text_property = 'articleBody'; } elseif ($main_content_object == 'Review') { $main_text_property = 'reviewBody'; } // Allow filtering of the main text property. $main_text_property = apply_filters('amt_schemaorg_property_main_text', $main_text_property); // $metadata_arr[] = '<div itemprop="' . esc_attr($main_text_property) . '">'; // Add main content //$metadata_arr[ esc_attr($main_text_property) ] = $post->post_content; // $metadata_arr[] = $post_body; // $metadata_arr[] = '</div> <!-- Itemprop END: ' . esc_attr($main_text_property) . ' -->'; // Now add closing tag for Article // $metadata_arr[] = $closing_article_tag; } // Add our comment // if ( count( $metadata_arr ) > 0 ) { // array_unshift( $metadata_arr, "<!-- BEGIN Schema.org microdata added by Add-Meta-Tags WordPress plugin -->" ); // array_unshift( $metadata_arr, "" ); // Intentionaly left empty // array_push( $metadata_arr, "<!-- END Schema.org microdata added by Add-Meta-Tags WordPress plugin -->" ); // array_push( $metadata_arr, "" ); // Intentionaly left empty // } //return $post_body; // return implode( PHP_EOL, $metadata_arr ); // Filtering of the generated microdata for footer $metadata_arr = apply_filters('amt_jsonld_schemaorg_metadata_head', $metadata_arr); // if ( count( $metadata_arr ) > 0 ) { // array_unshift( $metadata_arr, '<script type="application/ld+json">' ); // array_unshift( $metadata_arr, "" ); // Intentionaly left empty // array_push( $metadata_arr, '</script>' ); // array_push( $metadata_arr, "" ); // Intentionaly left empty // } // return $metadata_arr; if (count($metadata_arr) > 1) { // contains @context by default return array('<script type="application/ld+json">', 'json+ld_data' => json_encode($metadata_arr), '</script>'); } else { return array(); } }
/** * Generates basic metadata for the head area. * */ function amt_add_basic_metadata_head($post, $attachments, $embedded_media, $options) { $do_description = $options["auto_description"] == "1" ? true : false; $do_keywords = $options["auto_keywords"] == "1" ? true : false; $do_noodp_description = $options["noodp_description"] == "1" ? true : false; // Array to store metadata $metadata_arr = array(); // Robots Meta Tag. $robots_content = ''; if ($do_noodp_description && (is_front_page() || is_singular())) { // Add NOODP on posts and pages $robots_content = 'NOODP,NOYDIR'; // Allow filtering of the robots meta tag content. $robots_content = apply_filters('amt_robots_data', $robots_content); } // Add a robots meta tag if its content is not empty. if (!empty($robots_content)) { $metadata_arr[] = '<meta name="robots" content="' . $robots_content . '" />'; } // hreflang link element if ($options['generate_hreflang_links'] == '1') { if (is_singular()) { $locale = amt_get_language_content($options, $post); $hreflang = amt_get_the_hreflang($locale, $options); $hreflang_url = amt_get_permalink_for_multipage($post); } else { $locale = amt_get_language_site($options); $hreflang = amt_get_the_hreflang($locale, $options); $hreflang_url = ''; if (amt_is_default_front_page()) { $hreflang_url = trailingslashit(get_bloginfo('url')); } elseif (is_category() || is_tag() || is_tax()) { // $post is a term object $hreflang_url = get_term_link($post); } elseif (is_author()) { // $post is an author object $hreflang_url = get_author_posts_url($post->ID); } elseif (is_year()) { $archive_year = get_the_time('Y'); $hreflang_url = get_year_link($archive_year); } elseif (is_month()) { $archive_year = get_the_time('Y'); $archive_month = get_the_time('m'); $hreflang_url = get_month_link($archive_year, $archive_month); } elseif (is_day()) { $archive_year = get_the_time('Y'); $archive_month = get_the_time('m'); $archive_day = get_the_time('d'); $hreflang_url = get_day_link($archive_year, $archive_month, $archive_day); } // If paged information is available if (is_paged()) { //$hreflang_url = trailingslashit( $hreflang_url ) . get_query_var('paged') . '/'; $hreflang_url = get_pagenum_link(get_query_var('paged')); } } // hreflang links array $hreflang_arr = array(); // Add link element if (!empty($hreflang) && !empty($hreflang_url)) { $hreflang_arr[] = '<link rel="alternate" hreflang="' . esc_attr($hreflang) . '" href="' . esc_url_raw($hreflang_url) . '" />'; } // Allow filtering of the hreflang array $hreflang_arr = apply_filters('amt_hreflang_links', $hreflang_arr, $hreflang, $hreflang_url); // Add to to metadata array foreach ($hreflang_arr as $hreflang_link) { $metadata_arr[] = $hreflang_link; } } // Basic Meta Tags // Default front page displaying latest posts if (amt_is_default_front_page()) { // Description and Keywords from the Add-Meta-Tags settings override // default behaviour. // Description if ($do_description) { // Use the site description from the Add-Meta-Tags settings. // Fall back to the blog description. $site_description = amt_get_site_description($options); if (empty($site_description)) { // Alternatively, use the blog description // Here we sanitize the provided description for safety $site_description = sanitize_text_field(amt_sanitize_description(get_bloginfo('description'))); } // If we have a description, use it in the description meta-tag of the front page if (!empty($site_description)) { // Note: Contains multipage information through amt_process_paged() $metadata_arr[] = '<meta name="description" content="' . esc_attr(amt_process_paged($site_description)) . '" />'; } } // Keywords if ($do_keywords) { // Use the site keywords from the Add-Meta-Tags settings. // Fall back to the blog categories. $site_keywords = amt_get_site_keywords($options); if (empty($site_keywords)) { // Alternatively, use the blog categories // Here we sanitize the provided keywords for safety $site_keywords = sanitize_text_field(amt_sanitize_keywords(amt_get_all_categories())); } // If we have keywords, use them in the keywords meta-tag of the front page if (!empty($site_keywords)) { $metadata_arr[] = '<meta name="keywords" content="' . esc_attr($site_keywords) . '" />'; } } // Attachments } elseif (is_attachment()) { // has to be before is_singular() since is_singular() is true for attachments. // Description if ($do_description) { $description = amt_get_content_description($post, $auto = $do_description); if (!empty($description)) { // Note: Contains multipage information through amt_process_paged() $metadata_arr[] = '<meta name="description" content="' . esc_attr(amt_process_paged($description)) . '" />'; } } // No keywords // Content pages and static pages used as "front page" and "posts page" // This also supports products via is_singular() } elseif (is_singular() || amt_is_static_front_page() || amt_is_static_home()) { // Description if ($do_description) { $description = amt_get_content_description($post, $auto = $do_description); if (!empty($description)) { // Note: Contains multipage information through amt_process_paged() $metadata_arr[] = '<meta name="description" content="' . esc_attr(amt_process_paged($description)) . '" />'; } } // Keywords if ($do_keywords) { $keywords = amt_get_content_keywords($post, $auto = $do_keywords); if (!empty($keywords)) { $metadata_arr[] = '<meta name="keywords" content="' . esc_attr($keywords) . '" />'; // Static Posts Index Page // If no keywords have been set in the metabox and this is the static page, // which displayes the latest posts, use the categories of the posts in the loop. } elseif (amt_is_static_home()) { // Here we sanitize the provided keywords for safety $cats_from_loop = sanitize_text_field(amt_sanitize_keywords(implode(', ', amt_get_categories_from_loop()))); if (!empty($cats_from_loop)) { $metadata_arr[] = '<meta name="keywords" content="' . esc_attr($cats_from_loop) . '" />'; } } } // 'news_keywords' $newskeywords = amt_get_post_meta_newskeywords($post->ID); if (!empty($newskeywords)) { $metadata_arr[] = '<meta name="news_keywords" content="' . esc_attr($newskeywords) . '" />'; } // per post full meta tags $full_metatags_for_content = amt_get_post_meta_full_metatags($post->ID); if (!empty($full_metatags_for_content)) { $metadata_arr[] = html_entity_decode(stripslashes($full_metatags_for_content)); } // Category based archives } elseif (is_category()) { if ($do_description) { // If set, the description of the category is used in the 'description' metatag. // Otherwise, a generic description is used. // Here we sanitize the provided description for safety $description_content = sanitize_text_field(amt_sanitize_description(category_description())); // Note: Contains multipage information through amt_process_paged() if (empty($description_content)) { // Add a filtered generic description. $generic_description = apply_filters('amt_generic_description_category_archive', __('Content filed under the %s category.', 'add-meta-tags')); $generic_description = sprintf($generic_description, single_cat_title($prefix = '', $display = false)); $metadata_arr[] = '<meta name="description" content="' . esc_attr(amt_process_paged($generic_description)) . '" />'; } else { $metadata_arr[] = '<meta name="description" content="' . esc_attr(amt_process_paged($description_content)) . '" />'; } } if ($do_keywords) { // The category name alone is included in the 'keywords' metatag // Here we sanitize the provided keywords for safety $cur_cat_name = sanitize_text_field(amt_sanitize_keywords(single_cat_title($prefix = '', $display = false))); if (!empty($cur_cat_name)) { $metadata_arr[] = '<meta name="keywords" content="' . esc_attr($cur_cat_name) . '" />'; } } } elseif (is_tag()) { if ($do_description) { // If set, the description of the tag is used in the 'description' metatag. // Otherwise, a generic description is used. // Here we sanitize the provided description for safety $description_content = sanitize_text_field(amt_sanitize_description(tag_description())); // Note: Contains multipage information through amt_process_paged() if (empty($description_content)) { // Add a filtered generic description. $generic_description = apply_filters('amt_generic_description_tag_archive', __('Content tagged with %s.', 'add-meta-tags')); $generic_description = sprintf($generic_description, single_tag_title($prefix = '', $display = false)); $metadata_arr[] = '<meta name="description" content="' . esc_attr(amt_process_paged($generic_description)) . '" />'; } else { $metadata_arr[] = '<meta name="description" content="' . esc_attr(amt_process_paged($description_content)) . '" />'; } } if ($do_keywords) { // The tag name alone is included in the 'keywords' metatag // Here we sanitize the provided keywords for safety $cur_tag_name = sanitize_text_field(amt_sanitize_keywords(single_tag_title($prefix = '', $display = false))); if (!empty($cur_tag_name)) { $metadata_arr[] = '<meta name="keywords" content="' . esc_attr($cur_tag_name) . '" />'; } } // Custom taxonomies - Should be after is_category() and is_tag(), as it would catch those taxonomies as well. // This also supports product groups via is_tax(). Only product groups that are WordPress custom taxonomies are supported. } elseif (is_tax()) { // Taxonomy term object. // When viewing taxonomy archives, the $post object is the taxonomy term object. Check with: var_dump($post); $tax_term_object = $post; //var_dump($tax_term_object); if ($do_description) { // If set, the description of the custom taxonomy term is used in the 'description' metatag. // Otherwise, a generic description is used. // Here we sanitize the provided description for safety $description_content = sanitize_text_field(amt_sanitize_description(term_description($tax_term_object->term_id, $tax_term_object->taxonomy))); // Note: Contains multipage information through amt_process_paged() if (empty($description_content)) { // Add a filtered generic description. // Construct the filter name. Template: ``amt_generic_description_TAXONOMYSLUG_archive`` $taxonomy_description_filter_name = sprintf('amt_generic_description_%s_archive', $tax_term_object->taxonomy); // var_dump($taxonomy_description_filter_name); $generic_description = apply_filters($taxonomy_description_filter_name, __('Content filed under the %s taxonomy.', 'add-meta-tags')); $generic_description = sprintf($generic_description, single_term_title($prefix = '', $display = false)); $metadata_arr[] = '<meta name="description" content="' . esc_attr(amt_process_paged($generic_description)) . '" />'; } else { $metadata_arr[] = '<meta name="description" content="' . esc_attr(amt_process_paged($description_content)) . '" />'; } } if ($do_keywords) { // The taxonomy term name alone is included in the 'keywords' metatag. // Here we sanitize the provided keywords for safety. $cur_tax_term_name = sanitize_text_field(amt_sanitize_keywords(single_term_title($prefix = '', $display = false))); if (!empty($cur_tax_term_name)) { $metadata_arr[] = '<meta name="keywords" content="' . esc_attr($cur_tax_term_name) . '" />'; } } } elseif (is_author()) { // Author object // NOTE: Inside the author archives `$post->post_author` does not contain the author object. // In this case the $post (get_queried_object()) contains the author object itself. // We also can get the author object with the following code. Slug is what WP uses to construct urls. // $author = get_user_by( 'slug', get_query_var( 'author_name' ) ); // Also, ``get_the_author_meta('....', $author)`` returns nothing under author archives. // Access user meta with: $author->description, $author->user_email, etc // $author = get_queried_object(); $author = $post; // If a bio has been set in the user profile, use it in the description metatag of the // first page of the author archive *ONLY*. The other pages of the author archive use a generic description. // This happens because the 1st page of the author archive is considered the profile page // by the other metadata modules. // Otherwise use a generic meta tag. if ($do_description) { // Here we sanitize the provided description for safety $author_description = sanitize_text_field(amt_sanitize_description($author->description)); if (empty($author_description) || is_paged()) { // Note: Contains multipage information through amt_process_paged() // Add a filtered generic description. $generic_description = apply_filters('amt_generic_description_author_archive', __('Content published by %s.', 'add-meta-tags')); $generic_description = sprintf($generic_description, $author->display_name); $metadata_arr[] = '<meta name="description" content="' . esc_attr(amt_process_paged($generic_description)) . '" />'; } else { $metadata_arr[] = '<meta name="description" content="' . esc_attr($author_description) . '" />'; } } // For the keywords metatag use the categories of the posts the author has written and are displayed in the current page. if ($do_keywords) { // Here we sanitize the provided keywords for safety $cats_from_loop = sanitize_text_field(amt_sanitize_keywords(implode(', ', amt_get_categories_from_loop()))); if (!empty($cats_from_loop)) { $metadata_arr[] = '<meta name="keywords" content="' . esc_attr($cats_from_loop) . '" />'; } } } // Add site wide meta tags if (!empty($options["site_wide_meta"])) { $metadata_arr[] = html_entity_decode(stripslashes($options["site_wide_meta"])); } // On every page print the copyright head link $copyright_url = amt_get_site_copyright_url($options); //if ( empty($copyright_url)) { // $copyright_url = trailingslashit( get_bloginfo('url') ); //} if (!empty($copyright_url)) { $metadata_arr[] = '<link rel="copyright" type="text/html" title="' . esc_attr(get_bloginfo('name')) . ' Copyright Information" href="' . esc_url_raw($copyright_url) . '" />'; } // Filtering of the generated basic metadata $metadata_arr = apply_filters('amt_basic_metadata_head', $metadata_arr); return $metadata_arr; }
/** * Generates Opengraph metadata. * * Currently for: * - home page * - author archive * - content */ function amt_add_opengraph_metadata_head($post, $attachments, $embedded_media, $options) { if (apply_filters('amt_exclude_opengraph_metadata', false)) { return array(); } $do_auto_opengraph = $options["auto_opengraph"] == "1" ? true : false; if (!$do_auto_opengraph) { return array(); } $metadata_arr = array(); // fb:app_id & fb:admins // We currently let users add the full meta tags for fb:app_id and fb:admins in the site wide meta tags box. // fb:app_id appears everywhere //if ( ! empty($options['social_main_facebook_app_id']) ) { // $metadata_arr[] = '<meta property="fb:app_id" content="' . esc_attr( $options['social_main_facebook_app_id'] ) . '" />'; //} // fb:admins appear everywhere //if ( ! empty($options['social_main_facebook_admins']) ) { // $fb_admins_arr = explode(',', $options['social_main_facebook_admins']); // foreach ( $fb_admins_arr as $fb_admin ) { // $metadata_arr[] = '<meta property="fb:admins" content="' . esc_attr( trim($fb_admin) ) . '" />'; // } //} // no publisher meta tag for facebook, unless it is content // Custom content override if (amt_is_custom($post, $options)) { // Return metadata with: // add_filter( 'amt_custom_metadata_opengraph', 'my_function', 10, 5 ); // Return an array of meta tags. Array item format: ['key_can_be_whatever'] = '<meta name="foo" content="bar" />' $metadata_arr = apply_filters('amt_custom_metadata_opengraph', $metadata_arr, $post, $options, $attachments, $embedded_media); // Default front page displaying the latest posts } elseif (amt_is_default_front_page()) { // Type $metadata_arr[] = '<meta property="og:type" content="website" />'; // Site Name $metadata_arr[] = '<meta property="og:site_name" content="' . esc_attr(get_bloginfo('name')) . '" />'; // Title - Note: Contains multipage information $metadata_arr['og:title'] = '<meta property="og:title" content="' . esc_attr(amt_get_title_for_metadata($options, $post)) . '" />'; // URL - Note: different method to get the permalink on paged archives if (is_paged()) { $metadata_arr[] = '<meta property="og:url" content="' . esc_url_raw(get_pagenum_link(get_query_var('paged'))) . '" />'; } else { $metadata_arr[] = '<meta property="og:url" content="' . esc_url_raw(trailingslashit(get_bloginfo('url'))) . '" />'; } // Site description - Note: Contains multipage information through amt_process_paged() $site_description = amt_get_site_description($options); if (empty($site_description)) { $site_description = get_bloginfo('description'); } if (!empty($site_description)) { $metadata_arr[] = '<meta property="og:description" content="' . esc_attr(amt_process_paged($site_description)) . '" />'; } // Locale $metadata_arr[] = '<meta property="og:locale" content="' . esc_attr(str_replace('-', '_', amt_get_language_site($options))) . '" />'; // Site Image // Use the default image, if one has been set. $image_data = amt_get_default_image_data(); if (!empty($image_data)) { $image_size = apply_filters('amt_image_size_index', 'full'); $image_meta_tags = amt_get_opengraph_image_metatags($options, $image_data, $size = $image_size); if (!empty($image_meta_tags)) { $metadata_arr = array_merge($metadata_arr, $image_meta_tags); } } // Front page using a static page // Note: might also contain a listing of posts which may be paged, so use amt_process_paged() } elseif (amt_is_static_front_page()) { // Type if ($options['author_profile_source'] == 'frontpage') { // The front page is treated as the profile page. $metadata_arr[] = '<meta property="og:type" content="profile" />'; } else { $metadata_arr[] = '<meta property="og:type" content="website" />'; } // Site Name $metadata_arr[] = '<meta property="og:site_name" content="' . esc_attr(get_bloginfo('name')) . '" />'; // Title - Note: Contains multipage information $metadata_arr['og:title'] = '<meta property="og:title" content="' . esc_attr(amt_get_title_for_metadata($options, $post)) . '" />'; // URL - Note: different method to get the permalink on paged archives if (is_paged()) { $metadata_arr[] = '<meta property="og:url" content="' . esc_url_raw(get_pagenum_link(get_query_var('paged'))) . '" />'; } else { $metadata_arr[] = '<meta property="og:url" content="' . esc_url_raw(trailingslashit(get_bloginfo('url'))) . '" />'; } // Site Description - Note: Contains multipage information through amt_process_paged() $content_desc = amt_get_content_description($post); if (!empty($content_desc)) { // Use the pages custom description $metadata_arr[] = '<meta property="og:description" content="' . esc_attr(amt_process_paged($content_desc)) . '" />'; } elseif (get_bloginfo('description')) { // Alternatively use the blog's description $metadata_arr[] = '<meta property="og:description" content="' . esc_attr(amt_process_paged(get_bloginfo('description'))) . '" />'; } // Locale $metadata_arr[] = '<meta property="og:locale" content="' . esc_attr(str_replace('-', '_', amt_get_language_content($options, $post))) . '" />'; // Site Image // First check if a global image override URL has been entered. // If yes, use this image URL and override all other images. $image_data = amt_get_image_attributes_array(amt_get_post_meta_image_url($post->ID)); if (!empty($image_data)) { $image_size = apply_filters('amt_image_size_index', 'full'); $image_meta_tags = amt_get_opengraph_image_metatags($options, $image_data, $size = $image_size); if (!empty($image_meta_tags)) { $metadata_arr = array_merge($metadata_arr, $image_meta_tags); } //$global_image_override_url = amt_get_post_meta_image_url($post->ID); //if ( ! empty( $global_image_override_url ) ) { // $metadata_arr[] = '<meta property="og:image" content="' . esc_url_raw( $global_image_override_url ) . '" />'; // if ( is_ssl() || ( ! is_ssl() && $options["has_https_access"] == "1" ) ) { // $metadata_arr[] = '<meta property="og:image:secure_url" content="' . esc_url_raw( str_replace('http:', 'https:', $global_image_override_url ) ) . '" />'; // } // Then try the featured image, if exists. } elseif (function_exists('has_post_thumbnail') && has_post_thumbnail($post->ID)) { // Allow filtering of the image size. $image_size = apply_filters('amt_image_size_index', 'full'); $metadata_arr = array_merge($metadata_arr, amt_get_opengraph_image_metatags($options, get_post_thumbnail_id($post->ID), $size = $image_size)); } else { // Use the default image, if one has been set. $image_data = amt_get_default_image_data(); if (!empty($image_data)) { $image_size = apply_filters('amt_image_size_index', 'full'); $image_meta_tags = amt_get_opengraph_image_metatags($options, $image_data, $size = $image_size); if (!empty($image_meta_tags)) { $metadata_arr = array_merge($metadata_arr, $image_meta_tags); } } // Alternatively, use default image //$metadata_arr[] = '<meta property="og:image" content="' . esc_url_raw( $options["default_image_url"] ) . '" />'; //if ( is_ssl() || ( ! is_ssl() && $options["has_https_access"] == "1" ) ) { // $metadata_arr[] = '<meta property="og:image:secure_url" content="' . esc_url_raw( str_replace('http:', 'https:', $options["default_image_url"] ) ) . '" />'; //} } // Profile data (only if the front page has been set as the source of profile.) if ($options['author_profile_source'] == 'frontpage') { // Profile first and last name $last_name = get_the_author_meta('last_name', $post->post_author); if (!empty($last_name)) { $metadata_arr[] = '<meta property="profile:last_name" content="' . esc_attr($last_name) . '" />'; } $first_name = get_the_author_meta('first_name', $post->post_author); if (!empty($first_name)) { $metadata_arr[] = '<meta property="profile:first_name" content="' . esc_attr($first_name) . '" />'; } } // The posts index page - a static page displaying the latest posts } elseif (amt_is_static_home()) { // Type $metadata_arr[] = '<meta property="og:type" content="website" />'; // Site Name $metadata_arr[] = '<meta property="og:site_name" content="' . esc_attr(get_bloginfo('name')) . '" />'; // Title - Note: Contains multipage information $metadata_arr['og:title'] = '<meta property="og:title" content="' . esc_attr(amt_get_title_for_metadata($options, $post)) . '" />'; // URL - Note: different method to get the permalink on paged archives if (is_paged()) { $metadata_arr[] = '<meta property="og:url" content="' . esc_url_raw(get_pagenum_link(get_query_var('paged'))) . '" />'; } else { $metadata_arr[] = '<meta property="og:url" content="' . esc_url_raw(get_permalink($post->ID)) . '" />'; } // Site Description - Note: Contains multipage information through amt_process_paged() $content_desc = amt_get_content_description($post); if (!empty($content_desc)) { // Use the pages custom description $metadata_arr[] = '<meta property="og:description" content="' . esc_attr(amt_process_paged($content_desc)) . '" />'; } elseif (get_bloginfo('description')) { // Alternatively use a generic description $metadata_arr[] = '<meta property="og:description" content="' . amt_process_paged("An index of the latest content.") . '" />'; } // Locale $metadata_arr[] = '<meta property="og:locale" content="' . esc_attr(str_replace('-', '_', amt_get_language_content($options, $post))) . '" />'; // Site Image // First check if a global image override URL has been entered. // If yes, use this image URL and override all other images. $image_data = amt_get_image_attributes_array(amt_get_post_meta_image_url($post->ID)); if (!empty($image_data)) { $image_size = apply_filters('amt_image_size_index', 'full'); $image_meta_tags = amt_get_opengraph_image_metatags($options, $image_data, $size = $image_size); if (!empty($image_meta_tags)) { $metadata_arr = array_merge($metadata_arr, $image_meta_tags); } //$global_image_override_url = amt_get_post_meta_image_url($post->ID); //if ( ! empty( $global_image_override_url ) ) { // $metadata_arr[] = '<meta property="og:image" content="' . esc_url_raw( $global_image_override_url ) . '" />'; // if ( is_ssl() || ( ! is_ssl() && $options["has_https_access"] == "1" ) ) { // $metadata_arr[] = '<meta property="og:image:secure_url" content="' . esc_url_raw( str_replace('http:', 'https:', $global_image_override_url ) ) . '" />'; // } // Then try the featured image, if exists. } elseif (function_exists('has_post_thumbnail') && has_post_thumbnail($post->ID)) { // Allow filtering of the image size. $image_size = apply_filters('amt_image_size_index', 'full'); $metadata_arr = array_merge($metadata_arr, amt_get_opengraph_image_metatags($options, get_post_thumbnail_id($post->ID), $size = $image_size)); } else { // Use the default image, if one has been set. $image_data = amt_get_default_image_data(); if (!empty($image_data)) { $image_size = apply_filters('amt_image_size_index', 'full'); $image_meta_tags = amt_get_opengraph_image_metatags($options, $image_data, $size = $image_size); if (!empty($image_meta_tags)) { $metadata_arr = array_merge($metadata_arr, $image_meta_tags); } } // Alternatively, use default image //$metadata_arr[] = '<meta property="og:image" content="' . esc_url_raw( $options["default_image_url"] ) . '" />'; //if ( is_ssl() || ( ! is_ssl() && $options["has_https_access"] == "1" ) ) { // $metadata_arr[] = '<meta property="og:image:secure_url" content="' . esc_url_raw( str_replace('http:', 'https:', $options["default_image_url"] ) ) . '" />'; //} } // Category, Tag, Taxonomy archives // Note: product groups should pass the is_tax() validation, so no need for // amt_is_product_group(). We do not support other product groups. // amt_is_product_group() is used below to set the og:type to product.group. } elseif (is_category() || is_tag() || is_tax()) { // Taxonomy term object. // When viewing taxonomy archives, the $post object is the taxonomy term object. Check with: var_dump($post); $tax_term_object = $post; //var_dump($tax_term_object); // Type // In case of a product group taxonomy, we set the og:type to product.group if (amt_is_product_group()) { $metadata_arr[] = '<meta property="og:type" content="product.group" />'; } else { $metadata_arr[] = '<meta property="og:type" content="website" />'; } // Site Name $metadata_arr[] = '<meta property="og:site_name" content="' . esc_attr(get_bloginfo('name')) . '" />'; // Title - Note: Contains multipage information $metadata_arr['og:title'] = '<meta property="og:title" content="' . esc_attr(amt_get_title_for_metadata($options, $post)) . '" />'; // URL - Note: different method to get the permalink on paged archives $url = get_term_link($tax_term_object); if (is_paged()) { $url = trailingslashit($url) . get_query_var('paged') . '/'; } $metadata_arr[] = '<meta property="og:url" content="' . esc_url_raw($url) . '" />'; // Description // If set, the description of the custom taxonomy term is used in the 'description' metatag. // Otherwise, a generic description is used. // Here we sanitize the provided description for safety $description_content = sanitize_text_field(amt_sanitize_description(term_description($tax_term_object->term_id, $tax_term_object->taxonomy))); // Note: Contains multipage information through amt_process_paged() if (empty($description_content)) { // Add a filtered generic description. // Filter name if (is_category()) { $generic_description = apply_filters('amt_generic_description_category_archive', __('Content filed under the %s category.', 'add-meta-tags')); } elseif (is_tag()) { $generic_description = apply_filters('amt_generic_description_tag_archive', __('Content tagged with %s.', 'add-meta-tags')); } elseif (is_tax()) { // Construct the filter name. Template: ``amt_generic_description_TAXONOMYSLUG_archive`` $taxonomy_description_filter_name = sprintf('amt_generic_description_%s_archive', $tax_term_object->taxonomy); // var_dump($taxonomy_description_filter_name); // Generic description $generic_description = apply_filters($taxonomy_description_filter_name, __('Content filed under the %s taxonomy.', 'add-meta-tags')); } // Final generic description $generic_description = sprintf($generic_description, single_term_title($prefix = '', $display = false)); $metadata_arr[] = '<meta property="og:description" content="' . esc_attr(amt_process_paged($generic_description)) . '" />'; } else { $metadata_arr[] = '<meta property="og:description" content="' . esc_attr(amt_process_paged($description_content)) . '" />'; } // Locale $metadata_arr[] = '<meta property="og:locale" content="' . esc_attr(str_replace('-', '_', amt_get_language_site($options))) . '" />'; // Image // Use an image from the 'Global image override' field. // Otherwise, use a user defined image via filter. // Otherwise use default image. $image_data = amt_get_image_attributes_array(amt_get_term_meta_image_url($tax_term_object->term_id)); if (!empty($image_data)) { $image_size = apply_filters('amt_image_size_index', 'full'); $image_meta_tags = amt_get_opengraph_image_metatags($options, $image_data, $size = $image_size); if (!empty($image_meta_tags)) { $metadata_arr = array_merge($metadata_arr, $image_meta_tags); } } else { // First filter using a term/taxonomy agnostic filter name. $taxonomy_image_url = apply_filters('amt_taxonomy_force_image_url', '', $tax_term_object); if (empty($taxonomy_image_url)) { // Second filter (term/taxonomy dependent). // Construct the filter name. Template: ``amt_taxonomy_image_url_TAXONOMYSLUG_TERMSLUG`` $taxonomy_image_url_filter_name = sprintf('amt_taxonomy_image_url_%s_%s', $tax_term_object->taxonomy, $tax_term_object->slug); //var_dump($taxonomy_image_url_filter_name); // The default image, if set, is used by default. $taxonomy_image_url = apply_filters($taxonomy_image_url_filter_name, $options["default_image_url"]); } if (!empty($taxonomy_image_url)) { $image_data = amt_get_image_attributes_array($taxonomy_image_url); if (!empty($image_data)) { $image_size = apply_filters('amt_image_size_index', 'full'); $image_meta_tags = amt_get_opengraph_image_metatags($options, $image_data, $size = $image_size); if (!empty($image_meta_tags)) { $metadata_arr = array_merge($metadata_arr, $image_meta_tags); } } //$metadata_arr[] = '<meta property="og:image" content="' . esc_url_raw( $taxonomy_image_url ) . '" />'; //if ( is_ssl() || ( ! is_ssl() && $options["has_https_access"] == "1" ) ) { // $metadata_arr[] = '<meta property="og:image:secure_url" content="' . esc_url_raw( str_replace('http:', 'https:', $taxonomy_image_url ) ) . '" />'; //} } } // Author archive. First page is considered a profile page. } elseif (is_author()) { // Author object // NOTE: Inside the author archives `$post->post_author` does not contain the author object. // In this case the $post (get_queried_object()) contains the author object itself. // We also can get the author object with the following code. Slug is what WP uses to construct urls. // $author = get_user_by( 'slug', get_query_var( 'author_name' ) ); // Also, ``get_the_author_meta('....', $author)`` returns nothing under author archives. // Access user meta with: $author->description, $author->user_email, etc // $author = get_queried_object(); $author = $post; // Type if (!is_paged() && $options['author_profile_source'] == 'default') { // We treat the first page of the archive as a profile, only if // the profile source has been set to 'default' $metadata_arr[] = '<meta property="og:type" content="profile" />'; } else { $metadata_arr[] = '<meta property="og:type" content="website" />'; } // Site Name $metadata_arr[] = '<meta property="og:site_name" content="' . esc_attr(get_bloginfo('name')) . '" />'; // Title - Note: Contains multipage information //if ( ! is_paged() ) { // // We treat the first page of the archive as a profile // $metadata_arr[] = '<meta property="og:title" content="' . esc_attr( $author->display_name ) . ' profile page" />'; //} else { // $metadata_arr[] = '<meta property="og:title" content="' . esc_attr( amt_process_paged( "Content published by " . $author->display_name ) ) . '" />'; //} $metadata_arr['og:title'] = '<meta property="og:title" content="' . esc_attr(amt_get_title_for_metadata($options, $post)) . ' profile page" />'; // URL - Note: different method to get the permalink on paged archives // If a Facebook author profile URL has been provided, it has priority, // Otherwise fall back to the WordPress author archive. $fb_author_url = $author->amt_facebook_author_profile_url; if (!empty($fb_author_url)) { $metadata_arr[] = '<meta property="og:url" content="' . esc_url_raw($fb_author_url, array('http', 'https')) . '" />'; } else { if (is_paged()) { $metadata_arr[] = '<meta property="og:url" content="' . esc_url_raw(get_pagenum_link(get_query_var('paged'))) . '" />'; } else { $metadata_arr[] = '<meta property="og:url" content="' . esc_url_raw(get_author_posts_url($author->ID)) . '" />'; // The following makes no sense here. 'get_author_posts_url( $author->ID )' will do in all cases. //$metadata_arr[] = '<meta property="og:url" content="' . esc_url_raw( amt_get_local_author_profile_url( $author->ID, $options ) ) . '" />'; } } // description - Note: Contains multipage information through amt_process_paged() if (is_paged()) { $metadata_arr[] = '<meta property="og:description" content="' . esc_attr(amt_process_paged("Content published by " . $author->display_name)) . '" />'; } else { // Here we sanitize the provided description for safety // We treat the first page of the archive as a profile $author_description = sanitize_text_field(amt_sanitize_description($author->description)); if (empty($author_description)) { $metadata_arr[] = '<meta property="og:description" content="' . esc_attr("Content published by " . $author->display_name) . '" />'; } else { $metadata_arr[] = '<meta property="og:description" content="' . esc_attr($author_description) . '" />'; } } // Locale $metadata_arr[] = '<meta property="og:locale" content="' . esc_attr(str_replace('-', '_', amt_get_language_site($options))) . '" />'; // Profile Image // First use the global image override URL $image_data = amt_get_image_attributes_array(amt_get_user_meta_image_url($author->ID)); if (!empty($image_data)) { $image_size = apply_filters('amt_image_size_index', 'full'); $image_meta_tags = amt_get_opengraph_image_metatags($options, $image_data, $size = $image_size); if (!empty($image_meta_tags)) { $metadata_arr = array_merge($metadata_arr, $image_meta_tags); } } else { $author_email = sanitize_email($author->user_email); $avatar_size = apply_filters('amt_avatar_size', 128); $avatar_url = ''; // First try to get the avatar link by using get_avatar(). // Important: for this to work the "Show Avatars" option should be enabled in Settings > Discussion. $avatar_img = get_avatar(get_the_author_meta('ID', $author->ID), $avatar_size, '', get_the_author_meta('display_name', $author->ID)); if (!empty($avatar_img)) { if (preg_match("#src=['\"]([^'\"]+)['\"]#", $avatar_img, $matches)) { $avatar_url = $matches[1]; } } elseif (!empty($author_email)) { // If the user has provided an email, we use it to construct a gravatar link. $avatar_url = "http://www.gravatar.com/avatar/" . md5($author_email) . "?s=" . $avatar_size; } if (!empty($avatar_url)) { //$avatar_url = html_entity_decode($avatar_url, ENT_NOQUOTES, 'UTF-8'); $metadata_arr[] = '<meta property="og:image" content="' . esc_url_raw($avatar_url) . '" />'; // Add an og:imagesecure_url if the image URL uses HTTPS if (strpos($avatar_url, 'https://') !== false) { $metadata_arr[] = '<meta property="og:imagesecure_url" content="' . esc_url_raw($avatar_url) . '" />'; } if (apply_filters('amt_extended_image_tags', true)) { $metadata_arr[] = '<meta property="og:image:width" content="' . esc_attr($avatar_size) . '" />'; $metadata_arr[] = '<meta property="og:image:height" content="' . esc_attr($avatar_size) . '" />'; // Since we do not have a way to determine the image type, the following meta tag is commented out // TODO: make a function that detects the image type from the file extension (if a file extension is available) //$metadata_arr[] = '<meta property="og:image:type" content="image/jpeg" />'; } } } // Profile data (only on the 1st page of the archive) if (!is_paged() && $options['author_profile_source'] == 'default') { // Profile first and last name $last_name = $author->last_name; if (!empty($last_name)) { $metadata_arr[] = '<meta property="profile:last_name" content="' . esc_attr($last_name) . '" />'; } $first_name = $author->first_name; if (!empty($first_name)) { $metadata_arr[] = '<meta property="profile:first_name" content="' . esc_attr($first_name) . '" />'; } } // Custom Post Type archives } elseif (is_post_type_archive()) { // Custom post type object. // When viewing custom post type archives, the $post object is the custom post type object. Check with: var_dump($post); $post_type_object = $post; //var_dump($post_type_object); // Type $metadata_arr[] = '<meta property="og:type" content="website" />'; // Site Name $metadata_arr[] = '<meta property="og:site_name" content="' . esc_attr(get_bloginfo('name')) . '" />'; // Title - Note: Contains multipage information $metadata_arr['og:title'] = '<meta property="og:title" content="' . esc_attr(amt_get_title_for_metadata($options, $post)) . '" />'; // URL - Note: different method to get the permalink on paged archives $url = get_post_type_archive_link($post_type_object->name); if (is_paged()) { $url = trailingslashit($url) . get_query_var('paged') . '/'; } $metadata_arr[] = '<meta property="og:url" content="' . esc_url_raw($url) . '" />'; // Description // Note: Contains multipage information through amt_process_paged() // Add a filtered generic description. // Construct the filter name. Template: ``amt_generic_description_posttype_POSTTYPESLUG_archive`` $custom_post_type_description_filter_name = sprintf('amt_generic_description_posttype_%s_archive', $post_type_object->name); // var_dump($custom_post_type_description_filter_name); // Generic description $generic_description = apply_filters($custom_post_type_description_filter_name, __('%s archive.', 'add-meta-tags')); // Final generic description $generic_description = sprintf($generic_description, post_type_archive_title($prefix = '', $display = false)); $metadata_arr[] = '<meta property="og:description" content="' . esc_attr(amt_process_paged($generic_description)) . '" />'; // Locale $metadata_arr[] = '<meta property="og:locale" content="' . esc_attr(str_replace('-', '_', amt_get_language_site($options))) . '" />'; // Image // Use a user defined image via filter. Otherwise use default image. // First filter using a term/taxonomy agnostic filter name. $posttype_image_url = apply_filters('amt_posttype_force_image_url', '', $post_type_object); if (empty($posttype_image_url)) { // Second filter (post type dependent). // Construct the filter name. Template: ``amt_posttype_image_url_POSTTYPESLUG`` $posttype_image_url_filter_name = sprintf('amt_posttype_image_url_%s', $post_type_object->name); //var_dump($posttype_image_url_filter_name); // The default image, if set, is used by default. $posttype_image_url = apply_filters($posttype_image_url_filter_name, $options["default_image_url"]); } if (!empty($posttype_image_url)) { $image_data = amt_get_image_attributes_array($posttype_image_url); if (!empty($image_data)) { $image_size = apply_filters('amt_image_size_index', 'full'); $image_meta_tags = amt_get_opengraph_image_metatags($options, $image_data, $size = $image_size); if (!empty($image_meta_tags)) { $metadata_arr = array_merge($metadata_arr, $image_meta_tags); } } //$metadata_arr[] = '<meta property="og:image" content="' . esc_url_raw( $posttype_image_url ) . '" />'; //if ( is_ssl() || ( ! is_ssl() && $options["has_https_access"] == "1" ) ) { // $metadata_arr[] = '<meta property="og:image:secure_url" content="' . esc_url_raw( str_replace('http:', 'https:', $posttype_image_url ) ) . '" />'; //} } // Attachments } elseif (is_attachment()) { $mime_type = get_post_mime_type($post->ID); //$attachment_type = strstr( $mime_type, '/', true ); // See why we do not use strstr(): http://www.codetrax.org/issues/1091 $attachment_type = preg_replace('#\\/[^\\/]*$#', '', $mime_type); // First add metadata common to all attachment types. // Type // Note: there is no specific type for images/audio. We use article amd video // TODO: Check whether we could use another type specific to each attachment type. if ('video' == $attachment_type) { // video.other og:type for video attachment pages $og_type = 'video.other'; } else { $og_type = 'article'; } $og_type = apply_filters('amt_opengraph_og_type_attachment', $og_type); $metadata_arr[] = '<meta property="og:type" content="' . esc_attr($og_type) . '" />'; // Site Name $metadata_arr[] = '<meta property="og:site_name" content="' . esc_attr(get_bloginfo('name')) . '" />'; // Title $metadata_arr['og:title'] = '<meta property="og:title" content="' . esc_attr(amt_get_title_for_metadata($options, $post)) . '" />'; // URL $metadata_arr[] = '<meta property="og:url" content="' . esc_url_raw(get_permalink($post->ID)) . '" />'; // Description - We use the description defined by Add-Meta-Tags $content_desc = amt_get_content_description($post); if (!empty($content_desc)) { $metadata_arr[] = '<meta property="og:description" content="' . esc_attr($content_desc) . '" />'; } // Locale $metadata_arr[] = '<meta property="og:locale" content="' . esc_attr(str_replace('-', '_', amt_get_language_content($options, $post))) . '" />'; // og:updated_time $metadata_arr[] = '<meta property="og:updated_time" content="' . esc_attr(amt_iso8601_date($post->post_modified)) . '" />'; // Metadata specific to each attachment type if ('image' == $attachment_type) { // Allow filtering of the image size. $image_size = apply_filters('amt_image_size_attachment', 'full'); $metadata_arr = array_merge($metadata_arr, amt_get_opengraph_image_metatags($options, $post->ID, $size = $image_size)); } elseif ('video' == $attachment_type) { if ($options["og_omit_video_metadata"] != "1") { // Video tags $metadata_arr[] = '<meta property="og:video" content="' . esc_url_raw(wp_get_attachment_url($post->ID)) . '" />'; if (is_ssl() || !is_ssl() && $options["has_https_access"] == "1") { $metadata_arr[] = '<meta property="og:video:secure_url" content="' . esc_url_raw(str_replace('http:', 'https:', wp_get_attachment_url($post->ID))) . '" />'; } // //$metadata_arr[] = '<meta property="og:video:width" content="' . esc_attr( $main_size_meta[1] ) . '" />'; //$metadata_arr[] = '<meta property="og:video:height" content="' . esc_attr( $main_size_meta[2] ) . '" />'; $metadata_arr[] = '<meta property="og:video:type" content="' . esc_attr($mime_type) . '" />'; } } elseif ('audio' == $attachment_type) { // Audio tags $metadata_arr[] = '<meta property="og:audio" content="' . esc_url_raw(wp_get_attachment_url($post->ID)) . '" />'; if (is_ssl() || !is_ssl() && $options["has_https_access"] == "1") { $metadata_arr[] = '<meta property="og:audio:secure_url" content="' . esc_url_raw(str_replace('http:', 'https:', wp_get_attachment_url($post->ID))) . '" />'; } $metadata_arr[] = '<meta property="og:audio:type" content="' . esc_attr($mime_type) . '" />'; } // Article: meta tags // Dates $metadata_arr[] = '<meta property="article:published_time" content="' . esc_attr(amt_iso8601_date($post->post_date)) . '" />'; $metadata_arr[] = '<meta property="article:modified_time" content="' . esc_attr(amt_iso8601_date($post->post_modified)) . '" />'; // Author // If a Facebook author profile URL has been provided, it has priority, // Otherwise fall back to the WordPress author archive. $fb_author_url = get_the_author_meta('amt_facebook_author_profile_url', $post->post_author); if (!empty($fb_author_url)) { $metadata_arr[] = '<meta property="article:author" content="' . esc_url_raw($fb_author_url, array('http', 'https', 'mailto')) . '" />'; } else { //$metadata_arr[] = '<meta property="article:author" content="' . esc_url_raw( get_author_posts_url( get_the_author_meta( 'ID', $post->post_author ) ) ) . '" />'; $metadata_arr[] = '<meta property="article:author" content="' . esc_url_raw(amt_get_local_author_profile_url(get_the_author_meta('ID', $post->post_author), $options)) . '" />'; } // Publisher // If a Facebook publisher profile URL has been provided, it has priority. // Otherwise fall back to the WordPress blog home url. if (!empty($options['social_main_facebook_publisher_profile_url'])) { $metadata_arr[] = '<meta property="article:publisher" content="' . esc_url_raw($options['social_main_facebook_publisher_profile_url'], array('http', 'https', 'mailto')) . '" />'; } else { $metadata_arr[] = '<meta property="article:publisher" content="' . esc_url_raw(trailingslashit(get_bloginfo('url'))) . '" />'; } // Posts, pages, custom content types (attachments excluded, caught in previous clause) // Note: content might be multipage. Process with amt_process_paged() wherever needed. } elseif (is_singular()) { // Site Name $metadata_arr[] = '<meta property="og:site_name" content="' . esc_attr(get_bloginfo('name')) . '" />'; // Type // og:type set to 'video.other' for posts with post format set to video if (get_post_format($post->ID) == 'video') { $og_type = 'video.other'; // og:type set to 'product' if amt_is_product() validates // See: // * https://developers.facebook.com/docs/reference/opengraph/object-type/product/ // * https://developers.facebook.com/docs/payments/product } elseif (amt_is_product()) { $og_type = 'product'; // In any other case 'article' is used as the og:type } else { $og_type = 'article'; } // Allow filtering of og:type $og_type = apply_filters('amt_opengraph_og_type_content', $og_type); // Set og:type meta tag. $metadata_arr[] = '<meta property="og:type" content="' . esc_attr($og_type) . '" />'; // Title // Note: Contains multipage information $metadata_arr['og:title'] = '<meta property="og:title" content="' . esc_attr(amt_get_title_for_metadata($options, $post)) . '" />'; // URL - Uses amt_get_permalink_for_multipage() $metadata_arr[] = '<meta property="og:url" content="' . esc_url_raw(amt_get_permalink_for_multipage($post)) . '" />'; // Description - We use the description defined by Add-Meta-Tags // Note: Contains multipage information through amt_process_paged() $content_desc = amt_get_content_description($post); if (!empty($content_desc)) { $metadata_arr[] = '<meta property="og:description" content="' . esc_attr(amt_process_paged($content_desc)) . '" />'; } // Locale $metadata_arr[] = '<meta property="og:locale" content="' . esc_attr(str_replace('-', '_', amt_get_language_content($options, $post))) . '" />'; // og:updated_time $metadata_arr[] = '<meta property="og:updated_time" content="' . esc_attr(amt_iso8601_date($post->post_modified)) . '" />'; // Image // First check if a global image override URL has been entered. // If yes, use this image URL and override all other images. $image_data = amt_get_image_attributes_array(amt_get_post_meta_image_url($post->ID)); if (!empty($image_data)) { $image_size = apply_filters('amt_image_size_content', 'full'); $image_meta_tags = amt_get_opengraph_image_metatags($options, $image_data, $size = $image_size); if (!empty($image_meta_tags)) { $metadata_arr = array_merge($metadata_arr, $image_meta_tags); } //$global_image_override_url = amt_get_post_meta_image_url($post->ID); //if ( ! empty( $global_image_override_url ) ) { // $metadata_arr[] = '<meta property="og:image" content="' . esc_url_raw( $global_image_override_url ) . '" />'; // if ( is_ssl() || ( ! is_ssl() && $options["has_https_access"] == "1" ) ) { // $metadata_arr[] = '<meta property="og:image:secure_url" content="' . esc_url_raw( str_replace('http:', 'https:', $global_image_override_url ) ) . '" />'; // } // Further image processing } else { // Media Limits $image_limit = amt_metadata_get_image_limit($options); $video_limit = amt_metadata_get_video_limit($options); $audio_limit = amt_metadata_get_audio_limit($options); // Counters $ic = 0; // image counter $vc = 0; // video counter $ac = 0; // audio counter // We store the featured image ID in this variable so that it can easily be excluded // when all images are parsed from the $attachments array. $featured_image_id = 0; // Set to true if any image attachments are found. Use to finally add the default image // if no image attachments have been found. $has_images = false; if (function_exists('has_post_thumbnail') && has_post_thumbnail($post->ID)) { // Allow filtering of the image size. $image_size = apply_filters('amt_image_size_content', 'full'); $metadata_arr = array_merge($metadata_arr, amt_get_opengraph_image_metatags($options, get_post_thumbnail_id($post->ID), $size = $image_size)); // Finally, set the $featured_image_id $featured_image_id = get_post_thumbnail_id($post->ID); // Images have been found. $has_images = true; // Increase image counter $ic++; } // Process all attachments and add metatags (featured image will be excluded) foreach ($attachments as $attachment) { // Excluded the featured image since if ($attachment->ID != $featured_image_id) { $mime_type = get_post_mime_type($attachment->ID); //$attachment_type = strstr( $mime_type, '/', true ); // See why we do not use strstr(): http://www.codetrax.org/issues/1091 $attachment_type = preg_replace('#\\/[^\\/]*$#', '', $mime_type); if ('image' == $attachment_type && $ic < $image_limit) { // Image tags // Allow filtering of the image size. $image_size = apply_filters('amt_image_size_content', 'full'); $metadata_arr = array_merge($metadata_arr, amt_get_opengraph_image_metatags($options, $attachment->ID, $size = $image_size)); // Images have been found. $has_images = true; // Increase image counter $ic++; } elseif ('video' == $attachment_type && $vc < $video_limit) { if ($options["og_omit_video_metadata"] != "1") { // Video tags $metadata_arr[] = '<meta property="og:video" content="' . esc_url_raw(wp_get_attachment_url($attachment->ID)) . '" />'; if (is_ssl() || !is_ssl() && $options["has_https_access"] == "1") { $metadata_arr[] = '<meta property="og:video:secure_url" content="' . esc_url_raw(str_replace('http:', 'https:', wp_get_attachment_url($attachment->ID))) . '" />'; } //$metadata_arr[] = '<meta property="og:video:width" content="' . esc_attr( $main_size_meta[1] ) . '" />'; //$metadata_arr[] = '<meta property="og:video:height" content="' . esc_attr( $main_size_meta[2] ) . '" />'; $metadata_arr[] = '<meta property="og:video:type" content="' . esc_attr($mime_type) . '" />'; // Increase video counter $vc++; } } elseif ('audio' == $attachment_type && $ac < $audio_limit) { // Audio tags $metadata_arr[] = '<meta property="og:audio" content="' . esc_url_raw(wp_get_attachment_url($attachment->ID)) . '" />'; if (is_ssl() || !is_ssl() && $options["has_https_access"] == "1") { $metadata_arr[] = '<meta property="og:audio:secure_url" content="' . esc_url_raw(str_replace('http:', 'https:', wp_get_attachment_url($attachment->ID))) . '" />'; } $metadata_arr[] = '<meta property="og:audio:type" content="' . esc_attr($mime_type) . '" />'; // Increase audio counter $ac++; } } } // Embedded Media foreach ($embedded_media['images'] as $embedded_item) { if ($ic == $image_limit) { break; } $metadata_arr[] = '<meta property="og:image" content="' . esc_url_raw($embedded_item['image']) . '" />'; $metadata_arr[] = '<meta property="og:image:secure_url" content="' . esc_url_raw(str_replace('http:', 'https:', $embedded_item['image'])) . '" />'; if (apply_filters('amt_extended_image_tags', true)) { $metadata_arr[] = '<meta property="og:image:width" content="' . esc_attr($embedded_item['width']) . '" />'; $metadata_arr[] = '<meta property="og:image:height" content="' . esc_attr($embedded_item['height']) . '" />'; $metadata_arr[] = '<meta property="og:image:type" content="image/jpeg" />'; } // Images have been found. $has_images = true; // Increase image counter $ic++; } foreach ($embedded_media['videos'] as $embedded_item) { if ($options["og_omit_video_metadata"] != "1") { if ($vc == $video_limit) { break; } $metadata_arr[] = '<meta property="og:video" content="' . esc_url_raw($embedded_item['player']) . '" />'; $metadata_arr[] = '<meta property="og:video:secure_url" content="' . esc_url_raw(str_replace('http:', 'https:', $embedded_item['player'])) . '" />'; $metadata_arr[] = '<meta property="og:video:type" content="application/x-shockwave-flash" />'; $metadata_arr[] = '<meta property="og:video:width" content="' . esc_attr($embedded_item['width']) . '" />'; $metadata_arr[] = '<meta property="og:video:height" content="' . esc_attr($embedded_item['height']) . '" />'; // Increase video counter $vc++; } } foreach ($embedded_media['sounds'] as $embedded_item) { if ($ac == $audio_limit) { break; } $metadata_arr[] = '<meta property="og:audio" content="' . esc_url_raw($embedded_item['player']) . '" />'; $metadata_arr[] = '<meta property="og:audio:secure_url" content="' . esc_url_raw(str_replace('http:', 'https:', $embedded_item['player'])) . '" />'; $metadata_arr[] = '<meta property="og:audio:type" content="application/x-shockwave-flash" />'; // Increase audio counter $ac++; } // If no images have been found so far use the default image, if set. if ($has_images === false) { // Use the default image, if one has been set. $image_data = amt_get_default_image_data(); if (!empty($image_data)) { $image_size = apply_filters('amt_image_size_content', 'full'); $image_meta_tags = amt_get_opengraph_image_metatags($options, $image_data, $size = $image_size); if (!empty($image_meta_tags)) { $metadata_arr = array_merge($metadata_arr, $image_meta_tags); } } //$metadata_arr[] = '<meta property="og:image" content="' . esc_url_raw( $options["default_image_url"] ) . '" />'; //if ( is_ssl() || ( ! is_ssl() && $options["has_https_access"] == "1" ) ) { // $metadata_arr[] = '<meta property="og:image:secure_url" content="' . esc_url_raw( str_replace('http:', 'https:', $options["default_image_url"] ) ) . '" />'; //} } } // og:referenced $referenced_url_list = amt_get_referenced_items($post); foreach ($referenced_url_list as $referenced_url) { $referenced_url = trim($referenced_url); if (!empty($referenced_url)) { $metadata_arr[] = '<meta property="og:referenced" content="' . esc_url_raw($referenced_url) . '" />'; } } // Article: meta tags if ($og_type == 'article') { // Dates $metadata_arr[] = '<meta property="article:published_time" content="' . esc_attr(amt_iso8601_date($post->post_date)) . '" />'; $metadata_arr[] = '<meta property="article:modified_time" content="' . esc_attr(amt_iso8601_date($post->post_modified)) . '" />'; // Author // If a Facebook author profile URL has been provided, it has priority, // Otherwise fall back to the WordPress author archive. $fb_author_url = get_the_author_meta('amt_facebook_author_profile_url', $post->post_author); if (!empty($fb_author_url)) { $metadata_arr[] = '<meta property="article:author" content="' . esc_url_raw($fb_author_url, array('http', 'https', 'mailto')) . '" />'; } else { //$metadata_arr[] = '<meta property="article:author" content="' . esc_url_raw( get_author_posts_url( get_the_author_meta( 'ID', $post->post_author ) ) ) . '" />'; $metadata_arr[] = '<meta property="article:author" content="' . esc_url_raw(amt_get_local_author_profile_url(get_the_author_meta('ID', $post->post_author), $options)) . '" />'; } // Publisher // If a Facebook publisher profile URL has been provided, it has priority. // Otherwise fall back to the WordPress blog home url. if (!empty($options['social_main_facebook_publisher_profile_url'])) { $metadata_arr[] = '<meta property="article:publisher" content="' . esc_url_raw($options['social_main_facebook_publisher_profile_url'], array('http', 'https', 'mailto')) . '" />'; } else { $metadata_arr[] = '<meta property="article:publisher" content="' . esc_url_raw(trailingslashit(get_bloginfo('url'))) . '" />'; } /* // article:section: We use the first category as the section. $first_cat = amt_get_first_category($post); if ( ! empty( $first_cat ) ) { $metadata_arr[] = '<meta property="article:section" content="' . esc_attr( $first_cat ) . '" />'; } */ // article:section: We use print an ``article:section`` meta tag for each of the post's categories. $categories = get_the_category($post->ID); $categories = apply_filters('amt_post_categories_for_opengraph', $categories); foreach ($categories as $cat) { $section = trim($cat->cat_name); if (!empty($section) && $cat->slug != 'uncategorized') { $metadata_arr[] = '<meta property="article:section" content="' . esc_attr($section) . '" />'; } } // article:tag: Keywords are listed as post tags $keywords = explode(',', amt_get_content_keywords($post, $auto = true, $exclude_categories = true)); foreach ($keywords as $tag) { $tag = trim($tag); if (!empty($tag)) { $metadata_arr[] = '<meta property="article:tag" content="' . esc_attr($tag) . '" />'; } } } elseif ($og_type == 'video.other') { // Dates $metadata_arr[] = '<meta property="video:release_date" content="' . esc_attr(amt_iso8601_date($post->post_date)) . '" />'; // video:tag: Keywords are listed as post tags $keywords = explode(',', amt_get_content_keywords($post)); foreach ($keywords as $tag) { $tag = trim($tag); if (!empty($tag)) { $metadata_arr[] = '<meta property="video:tag" content="' . esc_attr($tag) . '" />'; } } } elseif ($og_type == 'product') { // Extend the current metadata with properties of the Product object. // See: // * https://developers.facebook.com/docs/reference/opengraph/object-type/product/ // * https://developers.facebook.com/docs/payments/product $metadata_arr = apply_filters('amt_product_data_opengraph', $metadata_arr, $post); } } // Filtering of the generated Opengraph metadata $metadata_arr = apply_filters('amt_opengraph_metadata_head', $metadata_arr); return $metadata_arr; }
/** * Generates basic metadata for the head area. * */ function amt_add_basic_metadata_head($post, $attachments, $embedded_media, $options) { if (apply_filters('amt_exclude_basic_metadata', false)) { return array(); } $do_description = $options["auto_description"] == "1" ? true : false; $do_keywords = $options["auto_keywords"] == "1" ? true : false; $do_noodp_description = $options["noodp_description"] == "1" ? true : false; // Array to store metadata $metadata_arr = array(); // Pre-processing // Store hreflang links in array $hreflang_links_arr = array(); // Store base robots options $robots_options = array(); if ($do_noodp_description && (is_front_page() || is_singular() || is_category() || is_tag() || is_tax() || is_author())) { // Add NOODP on posts and pages $robots_options[] = 'noodp'; $robots_options[] = 'noydir'; } // Store full meta tags (site wide and post specific) // Add site wide meta tags $full_metatags_as_string = ''; if (!empty($options['site_wide_meta'])) { $full_metatags_for_site = html_entity_decode(stripslashes($options['site_wide_meta'])); $full_metatags_as_string .= apply_filters('amt_full_metatags_site', $full_metatags_for_site); $full_metatags_as_string .= PHP_EOL; } // Full meta tags if (is_singular() || amt_is_static_front_page() || amt_is_static_home()) { // per post full meta tags $full_metatags_for_content = amt_get_post_meta_full_metatags($post->ID); $full_metatags_for_content = html_entity_decode(stripslashes($full_metatags_for_content)); $full_metatags_as_string .= apply_filters('amt_full_metatags_post', $full_metatags_for_content); } elseif (is_category() || is_tag() || is_tax()) { // Term specific full meta tags ($post is a term object) $full_metatags_for_term = amt_get_term_meta_full_metatags($post->term_id); $full_metatags_for_term = html_entity_decode(stripslashes($full_metatags_for_term)); $full_metatags_as_string .= apply_filters('amt_full_metatags_term', $full_metatags_for_term); } elseif (is_author()) { // User specific full meta tags ($post is a user object) $full_metatags_for_user = amt_get_user_meta_full_metatags($post->ID); $full_metatags_for_user = html_entity_decode(stripslashes($full_metatags_for_user)); $full_metatags_as_string .= apply_filters('amt_full_metatags_term', $full_metatags_for_user); } // Sanitize //$full_metatags_as_string = esc_textarea( wp_kses( $full_metatags_as_string, amt_get_allowed_html_kses() ) ); $full_metatags_as_string = wp_kses($full_metatags_as_string, amt_get_allowed_html_kses()); // Make array of full meta tags $full_meta_tags = preg_split('#\\R#', $full_metatags_as_string, NULL, PREG_SPLIT_NO_EMPTY); // Process if (apply_filters('amt_full_metatags_processor_enable', true)) { // Store processed meta tags here $processed_full_meta_tags = array(); // Field substitutions currently take place only on content pages. // TODO: See if this can be expanded to terms, authors. // Store the post's custom fields $custom_fields = null; // Store the post object's custom fields. // if (is_singular() || amt_is_static_front_page() || amt_is_static_home()) { // Get an array of all custom fields names of the post object. $custom_fields = get_post_custom_keys($post->ID); } // Iterate over full meta tags foreach ($full_meta_tags as $single_meta_tag) { // Note: Field value substitutions take place first, outside the elseif clauses. // Process substitutions of special notation with data from Custom Fields // Supported special notation: // [field=Field Name] // Notes: // - 'Field Name' is the name of custom field. // - If the custom field with name 'Field Name' does not exist, the meta tag // that contains it is omitted. // - If the value of the field is an empty string, then the substitution // takes place normally. // // The regex pattern fo our special notation. $special_notation_pattern = '#(?:\\[field\\=)([^\\]]+)(?:\\])#'; // The following covers content pages, as $custom_fields is only set on content pages. See above. if (!empty($custom_fields) && isset($post->ID)) { // This also assumes that we have a post object since custom fields // are set only on content pages, otherwise it is null. // Check for special notation if (preg_match($special_notation_pattern, $single_meta_tag, $matches)) { //var_dump($matches); // If the field name of the special notation does not match // any custom field name, omit the meta tag as per the rules above. if (!in_array($matches[1], $custom_fields)) { continue; } // Since there is special notation and the field name from the special // notation exists in the $custom_fields array, iterate over the available // custom fields and perform the substitutions. foreach ($custom_fields as $custom_field) { // Check if it matches the field name of the special notation if ($custom_field == $matches[1]) { // Fetch the custom field's value $field_value = get_post_meta($post->ID, $custom_field, true); // Sanitize value // TODO: this can be a problem depending on the value and the used sanitization function. $field_value = esc_attr(sanitize_text_field($field_value)); // Perform the substitution even if the the value is an empty string as per the rules above $single_meta_tag = str_replace(sprintf('[field=%s]', $custom_field), $field_value, $single_meta_tag); } } } } else { // In any other case, just remove the meta tags which contain the special notation. if (preg_match($special_notation_pattern, $single_meta_tag, $tmp)) { continue; } } // Process the PAGEINFO variable. // If the current page is the 1st page of any archive or of multipage content, // PAGEINFO is just stripped. For subsequent pages of archives or multipage // content, PAGEINFO is replaced with page based path (page/N/ for archives or N/ for multipage content) // // For paginated archives or paginated main page with latest posts. $has_paging_info = false; if (is_paged()) { $paged = get_query_var('paged'); // paged if ($paged && $paged >= 2) { $single_meta_tag = str_replace('PAGEINFO', 'page/' . $paged . '/', $single_meta_tag); $has_paging_info = true; } // For a Post or Page that has been divided into pages using the <!--nextpage--> QuickTag } else { $paged = get_query_var('page'); // page if ($paged && $paged >= 2) { $single_meta_tag = str_replace('PAGEINFO', $paged . '/', $single_meta_tag); $has_paging_info = true; } } // If this is not paged, strip PAGEINFO if ($has_paging_info === false) { $single_meta_tag = str_replace('PAGEINFO', '', $single_meta_tag); } // Process custom canonical link // If a rel="canonical" meta tags exists, we deactivate WordPress' 'rel_canonical' action, // Since it is assumed that a custom canonical link has been added. //if ( preg_match( '# rel="canonical" #', $post_full_meta_tags, $tmp ) ) { if (strpos($single_meta_tag, ' rel="canonical" ') !== false) { // Remove default WordPress action remove_action('wp_head', 'rel_canonical'); } elseif (strpos($single_meta_tag, ' name="robots" ') !== false) { if (preg_match('# content="([^"]+)" #', $single_meta_tag, $matches)) { $tmp_robots_opts = explode(',', $matches[1]); foreach ($tmp_robots_opts as $single_robots_option) { $single_robots_option_cleaned = strtolower(trim($single_robots_option)); if (!empty($single_robots_option_cleaned)) { $robots_options[] = $single_robots_option_cleaned; } } } // We simply collect options. Do not add any robots meta tags to the processed meta tags array. continue; } elseif (strpos($single_meta_tag, ' hreflang="') !== false) { // Simply add to the hreflang links array for later processing $hreflang_links_arr[] = $single_meta_tag; // We simply collect hreflang links for later processing. Do not add them to the processed meta tags array. continue; } // If we have reached here, add the meta tags to the array with processed meta tags. $processed_full_meta_tags[] = $single_meta_tag; } } else { // Full meta tags processor not enabled $processed_full_meta_tags = $full_meta_tags; } //var_dump($full_meta_tags); //var_dump($processed_full_meta_tags); // Add Meta Tags // Add a robots meta tag if robots options exist. // Backwards compatible filter. TODO: This is deprecated. Needs to be deleted after a while. $old_options_as_string = apply_filters('amt_robots_data', ''); if (!empty($old_options_as_string)) { foreach (explode(',', $old_options_as_string) as $single_robots_option) { $single_robots_option_cleaned = strtolower(trim($single_robots_option)); if (!empty($single_robots_option_cleaned)) { $robots_options[] = $single_robots_option_cleaned; } } } // Add robot_options filtering $robots_options = apply_filters('amt_robots_options', $robots_options); if (version_compare(PHP_VERSION, '5.3', '<')) { // The flag is not supported $robots_options = array_unique($robots_options); } else { $robots_options = array_unique($robots_options, SORT_STRING); } if (!empty($robots_options)) { $metadata_arr['basic:robots'] = '<meta name="robots" content="' . esc_attr(implode(',', $robots_options)) . '" />'; } // Add full meta tags // Merge meta tags $processed_full_meta_tags = apply_filters('amt_full_metatags_processed', $processed_full_meta_tags); if (!empty($processed_full_meta_tags)) { $metadata_arr = array_merge($metadata_arr, $processed_full_meta_tags); } // Add copyright link // On every page print the copyright head link $copyright_url = amt_get_site_copyright_url($options); //if ( empty($copyright_url)) { // $copyright_url = trailingslashit( get_bloginfo('url') ); //} if (!empty($copyright_url)) { $metadata_arr['basic:copyright'] = '<link rel="copyright" type="text/html" title="' . esc_attr(get_bloginfo('name')) . ' ' . __('copyright information', 'add-meta-tags') . '" href="' . esc_url($copyright_url) . '" />'; } // hreflang link element // This section also expects an array of extra hreflang links that may have // been collected from the full meta tags boxes. if ($options['generate_hreflang_links'] == '1') { if (is_singular()) { $locale = amt_get_language_content($options, $post); $hreflang = amt_get_the_hreflang($locale, $options); $hreflang_url = amt_get_permalink_for_multipage($post); } else { $locale = amt_get_language_site($options); $hreflang = amt_get_the_hreflang($locale, $options); $hreflang_url = ''; if (amt_is_default_front_page()) { $hreflang_url = trailingslashit(get_bloginfo('url')); } elseif (is_category() || is_tag() || is_tax()) { // $post is a term object $hreflang_url = get_term_link($post); } elseif (is_author()) { // $post is an author object $hreflang_url = get_author_posts_url($post->ID); } elseif (is_year()) { $archive_year = get_the_time('Y'); $hreflang_url = get_year_link($archive_year); } elseif (is_month()) { $archive_year = get_the_time('Y'); $archive_month = get_the_time('m'); $hreflang_url = get_month_link($archive_year, $archive_month); } elseif (is_day()) { $archive_year = get_the_time('Y'); $archive_month = get_the_time('m'); $archive_day = get_the_time('d'); $hreflang_url = get_day_link($archive_year, $archive_month, $archive_day); } // If paged information is available if (is_paged()) { //$hreflang_url = trailingslashit( $hreflang_url ) . get_query_var('paged') . '/'; $hreflang_url = get_pagenum_link(get_query_var('paged')); } } // hreflang links array $hreflang_arr = array(); // Add link element if (!empty($hreflang) && !empty($hreflang_url)) { $hreflang_arr[] = '<link rel="alternate" hreflang="' . esc_attr($hreflang) . '" href="' . esc_url_raw($hreflang_url) . '" />'; } // Add extra hreflang links that have been collected from the full meta tags boxes if (!empty($hreflang_links_arr)) { $hreflang_arr = array_merge($hreflang_arr, $hreflang_links_arr); } // Allow filtering of the hreflang array $hreflang_arr = apply_filters('amt_hreflang_links', $hreflang_arr); // Add to to metadata array foreach ($hreflang_arr as $hreflang_link) { if (preg_match('# hreflang="([^"]+)" #', $hreflang_link, $matches)) { $metadata_arr['basic:hreflang:' . $matches[1]] = $hreflang_link; } } } // Basic Meta Tags // Custom content override if (amt_is_custom($post, $options)) { // Return metadata with: // add_filter( 'amt_custom_metadata_basic', 'my_function', 10, 5 ); // Return an array of meta tags. Array item format: ['key_can_be_whatever'] = '<meta name="foo" content="bar" />' $metadata_arr = apply_filters('amt_custom_metadata_basic', $metadata_arr, $post, $options, $attachments, $embedded_media); // Default front page displaying latest posts } elseif (amt_is_default_front_page()) { // Description and Keywords from the Add-Meta-Tags settings override // default behaviour. // Description if ($do_description) { // Use the site description from the Add-Meta-Tags settings. // Fall back to the blog description. $site_description = amt_get_site_description($options); if (empty($site_description)) { // Alternatively, use the blog description // Here we sanitize the provided description for safety $site_description = sanitize_text_field(amt_sanitize_description(get_bloginfo('description'))); } // If we have a description, use it in the description meta-tag of the front page if (!empty($site_description)) { // Note: Contains multipage information through amt_process_paged() $metadata_arr['basic:description'] = '<meta name="description" content="' . esc_attr(amt_process_paged($site_description)) . '" />'; } } // Keywords if ($do_keywords) { // Use the site keywords from the Add-Meta-Tags settings. // Fall back to the blog categories. $site_keywords = amt_get_site_keywords($options); if (empty($site_keywords)) { // Alternatively, use the blog categories // Here we sanitize the provided keywords for safety $site_keywords = sanitize_text_field(amt_sanitize_keywords(amt_get_all_categories())); } // If we have keywords, use them in the keywords meta-tag of the front page if (!empty($site_keywords)) { $metadata_arr['basic:keywords'] = '<meta name="keywords" content="' . esc_attr($site_keywords) . '" />'; } } // Attachments } elseif (is_attachment()) { // has to be before is_singular() since is_singular() is true for attachments. // Description if ($do_description) { $description = amt_get_content_description($post, $auto = $do_description); if (!empty($description)) { // Note: Contains multipage information through amt_process_paged() $metadata_arr['basic:description'] = '<meta name="description" content="' . esc_attr(amt_process_paged($description)) . '" />'; } } // No keywords // Content pages and static pages used as "front page" and "posts page" // This also supports products via is_singular() } elseif (is_singular() || amt_is_static_front_page() || amt_is_static_home()) { // Description if ($do_description) { $description = amt_get_content_description($post, $auto = $do_description); if (!empty($description)) { // Note: Contains multipage information through amt_process_paged() $metadata_arr['basic:description'] = '<meta name="description" content="' . esc_attr(amt_process_paged($description)) . '" />'; } } // Keywords if ($do_keywords) { $keywords = amt_get_content_keywords($post, $auto = $do_keywords); if (!empty($keywords)) { $metadata_arr['basic:keywords'] = '<meta name="keywords" content="' . esc_attr($keywords) . '" />'; // Static Posts Index Page // If no keywords have been set in the metabox and this is the static page, // which displayes the latest posts, use the categories of the posts in the loop. } elseif (amt_is_static_home()) { // Here we sanitize the provided keywords for safety $cats_from_loop = sanitize_text_field(amt_sanitize_keywords(implode(', ', amt_get_categories_from_loop()))); if (!empty($cats_from_loop)) { $metadata_arr['basic:keywords'] = '<meta name="keywords" content="' . esc_attr($cats_from_loop) . '" />'; } } } // 'news_keywords' $newskeywords = amt_get_post_meta_newskeywords($post->ID); if (!empty($newskeywords)) { $metadata_arr['basic:news_keywords'] = '<meta name="news_keywords" content="' . esc_attr($newskeywords) . '" />'; } // Category based archives } elseif (is_category()) { if ($do_description) { // If set, the description of the category is used in the 'description' metatag. // Otherwise, a generic description is used. // Here we sanitize the provided description for safety $description_content = sanitize_text_field(amt_sanitize_description(category_description())); // Note: Contains multipage information through amt_process_paged() if (empty($description_content)) { // Add a filtered generic description. $generic_description = apply_filters('amt_generic_description_category_archive', __('Content filed under the %s category.', 'add-meta-tags')); $generic_description = sprintf($generic_description, single_cat_title($prefix = '', $display = false)); $metadata_arr['basic:description'] = '<meta name="description" content="' . esc_attr(amt_process_paged($generic_description)) . '" />'; } else { $metadata_arr['basic:description'] = '<meta name="description" content="' . esc_attr(amt_process_paged($description_content)) . '" />'; } } if ($do_keywords) { // The category name alone is included in the 'keywords' metatag // Here we sanitize the provided keywords for safety $cur_cat_name = sanitize_text_field(amt_sanitize_keywords(single_cat_title($prefix = '', $display = false))); if (!empty($cur_cat_name)) { $metadata_arr['basic:keywords'] = '<meta name="keywords" content="' . esc_attr($cur_cat_name) . '" />'; } } } elseif (is_tag()) { if ($do_description) { // If set, the description of the tag is used in the 'description' metatag. // Otherwise, a generic description is used. // Here we sanitize the provided description for safety $description_content = sanitize_text_field(amt_sanitize_description(tag_description())); // Note: Contains multipage information through amt_process_paged() if (empty($description_content)) { // Add a filtered generic description. $generic_description = apply_filters('amt_generic_description_tag_archive', __('Content tagged with %s.', 'add-meta-tags')); $generic_description = sprintf($generic_description, single_tag_title($prefix = '', $display = false)); $metadata_arr['basic:description'] = '<meta name="description" content="' . esc_attr(amt_process_paged($generic_description)) . '" />'; } else { $metadata_arr['basic:description'] = '<meta name="description" content="' . esc_attr(amt_process_paged($description_content)) . '" />'; } } if ($do_keywords) { // The tag name alone is included in the 'keywords' metatag // Here we sanitize the provided keywords for safety $cur_tag_name = sanitize_text_field(amt_sanitize_keywords(single_tag_title($prefix = '', $display = false))); if (!empty($cur_tag_name)) { $metadata_arr['basic:keywords'] = '<meta name="keywords" content="' . esc_attr($cur_tag_name) . '" />'; } } // Custom taxonomies - Should be after is_category() and is_tag(), as it would catch those taxonomies as well. // This also supports product groups via is_tax(). Only product groups that are WordPress custom taxonomies are supported. } elseif (is_tax()) { // Taxonomy term object. // When viewing taxonomy archives, the $post object is the taxonomy term object. Check with: var_dump($post); $tax_term_object = $post; //var_dump($tax_term_object); if ($do_description) { // If set, the description of the custom taxonomy term is used in the 'description' metatag. // Otherwise, a generic description is used. // Here we sanitize the provided description for safety $description_content = sanitize_text_field(amt_sanitize_description(term_description($tax_term_object->term_id, $tax_term_object->taxonomy))); // Note: Contains multipage information through amt_process_paged() if (empty($description_content)) { // Add a filtered generic description. // Construct the filter name. Template: ``amt_generic_description_TAXONOMYSLUG_archive`` $taxonomy_description_filter_name = sprintf('amt_generic_description_%s_archive', $tax_term_object->taxonomy); // var_dump($taxonomy_description_filter_name); $generic_description = apply_filters($taxonomy_description_filter_name, __('Content filed under the %s taxonomy.', 'add-meta-tags')); $generic_description = sprintf($generic_description, single_term_title($prefix = '', $display = false)); $metadata_arr['basic:description'] = '<meta name="description" content="' . esc_attr(amt_process_paged($generic_description)) . '" />'; } else { $metadata_arr['basic:description'] = '<meta name="description" content="' . esc_attr(amt_process_paged($description_content)) . '" />'; } } if ($do_keywords) { // The taxonomy term name alone is included in the 'keywords' metatag. // Here we sanitize the provided keywords for safety. $cur_tax_term_name = sanitize_text_field(amt_sanitize_keywords(single_term_title($prefix = '', $display = false))); if (!empty($cur_tax_term_name)) { $metadata_arr['basic:keywords'] = '<meta name="keywords" content="' . esc_attr($cur_tax_term_name) . '" />'; } } } elseif (is_author()) { // Author object // NOTE: Inside the author archives `$post->post_author` does not contain the author object. // In this case the $post (get_queried_object()) contains the author object itself. // We also can get the author object with the following code. Slug is what WP uses to construct urls. // $author = get_user_by( 'slug', get_query_var( 'author_name' ) ); // Also, ``get_the_author_meta('....', $author)`` returns nothing under author archives. // Access user meta with: $author->description, $author->user_email, etc // $author = get_queried_object(); $author = $post; // If a bio has been set in the user profile, use it in the description metatag of the // first page of the author archive *ONLY*. The other pages of the author archive use a generic description. // This happens because the 1st page of the author archive is considered the profile page // by the other metadata modules. // Otherwise use a generic meta tag. if ($do_description) { // Here we sanitize the provided description for safety $author_description = sanitize_text_field(amt_sanitize_description($author->description)); if (empty($author_description) || is_paged()) { // Note: Contains multipage information through amt_process_paged() // Add a filtered generic description. $generic_description = apply_filters('amt_generic_description_author_archive', __('Content published by %s.', 'add-meta-tags')); $generic_description = sprintf($generic_description, $author->display_name); $metadata_arr['basic:description'] = '<meta name="description" content="' . esc_attr(amt_process_paged($generic_description)) . '" />'; } else { $metadata_arr['basic:description'] = '<meta name="description" content="' . esc_attr($author_description) . '" />'; } } // For the keywords metatag use the categories of the posts the author has written and are displayed in the current page. if ($do_keywords) { // Here we sanitize the provided keywords for safety $cats_from_loop = sanitize_text_field(amt_sanitize_keywords(implode(', ', amt_get_categories_from_loop()))); if (!empty($cats_from_loop)) { $metadata_arr['basic:keywords'] = '<meta name="keywords" content="' . esc_attr($cats_from_loop) . '" />'; } } // Custom Post Type Archive } elseif (is_post_type_archive()) { // Custom post type object. // When viewing custom post type archives, the $post object is the custom post type object. Check with: var_dump($post); $post_type_object = $post; //var_dump($post_type_object); if ($do_description) { // Description // Note: Contains multipage information through amt_process_paged() // Add a filtered generic description. // Construct the filter name. Template: ``amt_generic_description_posttype_POSTTYPESLUG_archive`` $custom_post_type_description_filter_name = sprintf('amt_generic_description_posttype_%s_archive', $post_type_object->name); // var_dump($custom_post_type_description_filter_name); // Generic description $generic_description = apply_filters($custom_post_type_description_filter_name, __('%s archive.', 'add-meta-tags')); // Final generic description $generic_description = sprintf($generic_description, post_type_archive_title($prefix = '', $display = false)); $metadata_arr['basic:description'] = '<meta name="description" content="' . esc_attr(amt_process_paged($generic_description)) . '" />'; } // For the keywords metatag use the categories of the posts that are listed in the current page. if ($do_keywords) { // Here we sanitize the provided keywords for safety $cats_from_loop = sanitize_text_field(amt_sanitize_keywords(implode(', ', amt_get_categories_from_loop()))); if (!empty($cats_from_loop)) { $metadata_arr['basic:keywords'] = '<meta name="keywords" content="' . esc_attr($cats_from_loop) . '" />'; } } } // Filtering of the generated basic metadata $metadata_arr = apply_filters('amt_basic_metadata_head', $metadata_arr); return $metadata_arr; }
function amt_metadata_analysis($default_text, $metadata_block_head, $metadata_block_footer, $metadata_block_content_filter) { // Analysis is appended only o content pages if (!is_singular()) { return $default_text; } // Check the filter based switch if (!apply_filters('amt_metadata_analysis_enable', true)) { return $default_text; } // // Collect data // $options = amt_get_options(); $post = amt_get_queried_object(); if (!isset($post->ID) || $post->ID <= 0) { return $default_text; } // Content and stats // Post content $post_content = strtolower(amt_get_clean_post_content($options, $post)); $post_content_length = strlen($post_content); //var_dump($post_content); // Total words if (function_exists('wordstats_words')) { $post_word_count = wordstats_words($post_content); // provided by the word-statistics-plugin by FD } else { $post_word_count = str_word_count($post_content); } // Total sentences if (function_exists('wordstats_sentences')) { $post_sentence_count = wordstats_sentences($post_content); // provided by the word-statistics-plugin by FD } else { $post_sentence_count = preg_match_all('/[.!?\\r]/', $post_content, $dummy); } // Total syllables // TODO: Find better function $post_syllable_count = preg_match_all('/[aeiouy]/', $post_content, $dummy); // Titles // Original $post_title = strtolower(strip_tags(get_the_title($post->ID))); // Title HTML element if ($options['enable_advanced_title_management'] == '1') { // If Advanced Title management is enabled, use this directly: $post_title_html_element = strtolower(amt_get_title_for_title_element($options, $post)); } else { if (version_compare(get_bloginfo('version'), '4.4', '>=')) { // Since WP 4.4 // - https://make.wordpress.org/core/2015/10/20/document-title-in-4-4/ //$post_title_html_element = strtolower( apply_filters('document_title_parts', array('title' => $post_title) ) ); //$post_title_html_element = wp_get_document_title(); $post_title_html_element = strtolower(get_wp_title_rss()); } else { // Reverting back to the one argument version of the fitlering function. //$post_title_html_element = strtolower( apply_filters('wp_title', $post_title) ); // Until testing is performed on old WP versions we just use post title $post_title_html_element = $post_title; } } //var_dump($post_title_html_element); // Title in metadata $post_title_metadata = strtolower(amt_get_title_for_metadata($options, $post)); //var_dump($post_title_metadata); // URL $post_url = str_replace(get_bloginfo('url'), '', amt_get_permalink_for_multipage($post)); //var_dump($post_url); // Description $description = ''; if (array_key_exists('basic:description', $metadata_block_head)) { $description = strtolower(preg_replace('#^.*content="([^"]+)".*$#', '$1', $metadata_block_head['basic:description'])); } //var_dump($description); // Keywords $keywords = array(); if (array_key_exists('basic:keywords', $metadata_block_head)) { $keywords_content = strtolower(preg_replace('#^.*content="([^"]+)".*$#', '$1', $metadata_block_head['basic:keywords'])); $keywords = explode(',', str_replace(', ', ',', $keywords_content)); } //var_dump($keywords); // Keyword matching pattern //$keyword_matching_pattern = '#(?:%s)#'; //$keyword_matching_pattern = '#(?:%s)[[:^alpha:]]#'; //$keyword_matching_pattern = '#(?:%s)[[:^alpha:]]?#'; $keyword_matching_pattern = '#(?:%s)(?:[[:^alpha:]]|$)#'; $keyword_matching_pattern = apply_filters('amt_metadata_analysis_keyword_matching_pattern', $keyword_matching_pattern); // Whether to use topic keywords field or the keywords from the 'keywords' meta tag. $use_keywords = false; // First check for a field that contains topic keywords. $topic_keywords_field_name = apply_filters('amt_metadata_analysis_topic_keywords_field', 'topic_keywords'); $topic_keywords_field_value = get_post_meta($post->ID, $topic_keywords_field_name, true); if (!empty($topic_keywords_field_value)) { $topic_keywords = explode(',', str_replace(', ', ',', $topic_keywords_field_value)); } else { $topic_keywords = $keywords; $use_keywords = true; //var_dump($topic_keywords); } $BR = PHP_EOL; if ($options['review_mode_omit_notices'] == '0') { $output = $default_text . $BR . $BR; //$output .= $BR . '<span class="">Text analysis</span>' . $BR; } else { $output = ''; } if ($options['review_mode_omit_notices'] == '0') { $output .= 'Metadata Overview' . $BR; $output .= '=================' . $BR; //$output .= 'This overview has been generated by the Add-Meta-Tags plugin for statistical and' . $BR; //$output .= 'informational purposes only. Please do not modify or base your work upon this report.' . $BR . $BR; $output .= 'NOTICE: Add-Meta-Tags does not provide SEO advice and does not rate your content.' . $BR; $output .= 'This <a target="_blank" href="http://www.codetrax.org/projects/wp-add-meta-tags/wiki/Metadata_Overview">overview</a> has been generated for statistical and informational purposes only.' . $BR . $BR; //$output .= '<a target="_blank" href="http://www.codetrax.org/projects/wp-add-meta-tags/wiki/FAQ#Is-Add-Meta-Tags-an-SEO-plugin">Read more</a> about the mentality upon which the development of this plugin has been based.' . $BR; //$output .= 'Please use this statistical information to identify keyword overstuffing' . $BR; //$output .= 'and stay away from following any patterns or being bound by the numbers.' . $BR . $BR; } if ($use_keywords) { $output .= sprintf('This overview has been based on post keywords, because the Custom Field \'<em>%s</em>\' could not be found.', $topic_keywords_field_name) . $BR; } else { $output .= sprintf('This overview has been based on <em>topic keywords</em> retrieved from the Custom Field \'<em>%s</em>\'.', $topic_keywords_field_name) . $BR; } if ($options['review_mode_omit_notices'] == '0') { $output .= 'Keyword Analysis' . $BR; $output .= '----------------' . $BR; } else { $output .= $BR; } $output .= '<table class="amt-ht-table">'; $output .= '<tr> <th>Topic Keyword</th> <th>Content</th> <th>Description</th> <th>Keywords</th> <th>Post Title</th> <th>HTML title</th> <th>Metadata titles</th> <th>Post URL</th> </tr>'; foreach ($topic_keywords as $topic_keyword) { $output .= sprintf('<tr> <td>%s</td>', $topic_keyword); $is_into = array(); // Check content $is_into['content'] = ''; $occurrences = preg_match_all(sprintf($keyword_matching_pattern, $topic_keyword), $post_content, $matches); if ($occurrences) { // Only for content $topic_keyword_desnity = round($occurrences / $post_word_count * 100, 2); $output .= sprintf(' <td>%d (%.2f%%)</td>', $occurrences, $topic_keyword_desnity); } else { $output .= '<td> </td>'; } // Check description $occurrences = preg_match_all(sprintf($keyword_matching_pattern, $topic_keyword), $description, $matches); if ($occurrences) { $output .= sprintf(' <td>%d</td>', $occurrences); } else { $output .= '<td> </td>'; } // Check keywords if ($use_keywords) { $output .= '<td>N/A</td>'; $is_into['keywords'] = 'N/A'; } elseif (in_array($topic_keyword, $keywords)) { // Always 1 $output .= '<td>1</td>'; } else { $output .= '<td> </td>'; } // Check original title $occurrences = preg_match_all(sprintf($keyword_matching_pattern, $topic_keyword), $post_title, $matches); if ($occurrences) { $output .= sprintf(' <td>%d</td>', $occurrences); } else { $output .= '<td> </td>'; } // Check title element $occurrences = preg_match_all(sprintf($keyword_matching_pattern, $topic_keyword), $post_title_html_element, $matches); if ($occurrences) { $output .= sprintf(' <td>%d</td>', $occurrences); } else { $output .= '<td> </td>'; } // Check metadata titles $occurrences = preg_match_all(sprintf($keyword_matching_pattern, $topic_keyword), $post_title_metadata, $matches); if ($occurrences) { $output .= sprintf(' <td>%d</td>', $occurrences); } else { $output .= '<td> </td>'; } // Check post URL $occurrences = preg_match_all(sprintf($keyword_matching_pattern, $topic_keyword), $post_url, $matches); if ($occurrences) { $output .= sprintf(' <td>%d</td>', $occurrences); } else { $output .= '<td> </td>'; } // Close row $output .= ' </tr>' . $BR; } $output .= '</table>' . $BR; // Topic Keywords Distribution Graph if ($options['review_mode_omit_notices'] == '0') { $output .= 'Topic Keywords Distribution Graph' . $BR; $output .= '---------------------------------' . $BR; $output .= 'The following text based graph shows how the <em>topic keywords</em> are distributed within your content.' . $BR; $output .= 'You can use it to identify incidents of keyword overstuffing.' . $BR . $BR; } //$output .= $BR . $BR; $total_bars = 39; // zero based $step = $post_content_length / $total_bars; // Debug //$output .= $BR . $post_content_length . ' ' . $step . $BR; $max_weight = null; $weights = array(); // Reset weights for ($x = 0; $x <= $total_bars; $x++) { $weights[$x] = 1; } foreach ($topic_keywords as $topic_keyword) { // Use preg_match_all with PREG_OFFSET_CAPTURE -- http://php.net/manual/en/function.preg-match-all.php $topic_keyword_occurrences = preg_match_all(sprintf($keyword_matching_pattern, $topic_keyword), $post_content, $matches, PREG_OFFSET_CAPTURE); //var_dump($matches); if (!empty($topic_keyword_occurrences)) { foreach ($matches[0] as $match) { $pos = $match[1]; $step_index = absint($pos / $step); $weights[$step_index] = $weights[$step_index] + 1; if ($weights[$step_index] > $max_weight) { $max_weight = $weights[$step_index]; } // Debug //$output .= sprintf('kw: %s, pos: %s, step index: %s, step weight: %s', $topic_keyword, $pos, $step_index, $weights[$step_index]) . $BR; } } } //var_dump($weights); for ($x = $max_weight - 1; $x >= 1; $x--) { $line = ''; for ($y = 0; $y <= $total_bars; $y++) { if ($weights[$y] > $x) { $line .= '#'; } else { $line .= ' '; } } $output .= $line . $BR; } // Currently this text based ruler is used as base line. $output .= str_repeat('---------+', ($total_bars + 1) / 10) . $BR; if ($options['review_mode_omit_notices'] == '0') { $output .= $BR . '<code>#</code>: indicates a single occurrence of a <em>topic keyword</em>.' . $BR; } else { $output .= $BR; } // Stats and scores by algos provided by the word-statistics-plugin by FD if (function_exists('wordstats_words')) { // Readability Tests if ($options['review_mode_omit_notices'] == '0') { $output .= $BR . 'Readability Scores and Text Statistics' . $BR; $output .= '--------------------------------------' . $BR; $output .= 'These readability scores and text statistics are based on algorithms provided by the <em>FD Word Statistics Plugin</em>.' . $BR . $BR; } if (function_exists('wordstats_words')) { $output .= sprintf(' ● Total words: <strong>%d</strong>', wordstats_words($post_content)) . $BR; } if (function_exists('wordstats_sentences')) { $output .= sprintf(' ● Total sentences: <strong>%d</strong>', wordstats_sentences($post_content)) . $BR; } if (function_exists('wordstats_flesch_kincaid')) { $output .= sprintf(' ● Flesch-Kincaid US grade level: <strong>%.1f</strong> <em>(For instance, a score of 9.3 means suitable for a 9th grade student in the US, <a target="_blank" href="%s">read more</a>.)</em>', wordstats_flesch_kincaid($post_content), 'https://en.wikipedia.org/wiki/Flesch%E2%80%93Kincaid_readability_tests#Flesch.E2.80.93Kincaid_grade_level') . $BR; } if (function_exists('wordstats_flesch')) { $output .= sprintf(' ● Flesch reading ease: <strong>%.1f%%</strong> <em>(avg 11 y.o. student: 90-100%%, 13-15 y.o. students: 60-70%%, university graduates: 0-30%%, <a target="_blank" href="%s">read more</a>.)</em>', wordstats_flesch($post_content), 'https://en.wikipedia.org/wiki/Flesch%E2%80%93Kincaid_readability_tests#Flesch_reading_ease') . $BR; } if (function_exists('wordstats_fog')) { $output .= sprintf(' ● Gunning fog index: <strong>%.1f</strong> <em>(wide audience: < 12, near universal understanding: < 8, <a target="_blank" href="%s">read more</a>.)</em>', wordstats_fog($post_content), 'https://en.wikipedia.org/wiki/Gunning_fog_index') . $BR; } $output .= $BR; } else { if ($options['review_mode_omit_notices'] == '0') { $output .= $BR . $BR . 'Note: There is experimental support for <em>FD Word Statistics Plugin</em>.'; $output .= $BR . 'If installed, you can get some readability scores and text statistics here.' . $BR . $BR; } } return $output; }
function amt_add_dublin_core_metadata_head($post, $attachments, $embedded_media, $options) { if (apply_filters('amt_exclude_dublin_core_metadata', false)) { return array(); } $metadata_arr = array(); $do_auto_dublincore = $options["auto_dublincore"] == "1" ? true : false; if (!$do_auto_dublincore) { return $metadata_arr; } // Custom content override if (amt_is_custom($post, $options)) { // Return metadata with: // add_filter( 'amt_custom_metadata_dublin_core', 'my_function', 10, 5 ); // Return an array of meta tags. Array item format: ['key_can_be_whatever'] = '<meta name="foo" content="bar" />' $metadata_arr = apply_filters('amt_custom_metadata_dublin_core', $metadata_arr, $post, $options, $attachments, $embedded_media); return $metadata_arr; } if (!is_singular() || is_front_page()) { // is_front_page() is used for the case in which a static page is used as the front page. // Dublin Core metadata has a meaning for content only. return array(); } // The Dublin Core metadata generator does not support products or product groups. if (amt_is_product() || amt_is_product_group()) { return array(); } // Title // Note: Contains multipage information through amt_process_paged() $metadata_arr['dcterms.title'] = '<meta name="dcterms.title" content="' . esc_attr(amt_get_title_for_metadata($options, $post)) . '" />'; // Resource identifier - Uses amt_get_permalink_for_multipage() $metadata_arr[] = '<meta name="dcterms.identifier" content="' . esc_url_raw(amt_get_permalink_for_multipage($post)) . '" />'; $metadata_arr[] = '<meta name="dcterms.creator" content="' . esc_attr(amt_get_dublin_core_author_notation($post)) . '" />'; //$metadata_arr[] = '<meta name="dcterms.date" content="' . esc_attr( amt_iso8601_date($post->post_date) ) . '" />'; $metadata_arr[] = '<meta name="dcterms.created" content="' . esc_attr(amt_iso8601_date($post->post_date)) . '" />'; $metadata_arr[] = '<meta name="dcterms.available" content="' . esc_attr(amt_iso8601_date($post->post_date)) . '" />'; //$metadata_arr[] = '<meta name="dcterms.issued" content="' . esc_attr( amt_iso8601_date($post->post_date) ) . '" />'; $metadata_arr[] = '<meta name="dcterms.modified" content="' . esc_attr(amt_iso8601_date($post->post_modified)) . '" />'; // Description // We use the same description as the ``description`` meta tag. // Note: Contains multipage information through amt_process_paged() $content_desc = amt_get_content_description($post); if (!empty($content_desc)) { $metadata_arr[] = '<meta name="dcterms.description" content="' . esc_attr(amt_process_paged($content_desc)) . '" />'; } // Keywords if (!is_attachment()) { // Attachments do not support keywords // dcterms.subject - one for each keyword. $keywords = explode(',', amt_get_content_keywords($post)); foreach ($keywords as $subject) { $subject = trim($subject); if (!empty($subject)) { $metadata_arr[] = '<meta name="dcterms.subject" content="' . esc_attr($subject) . '" />'; } } } $metadata_arr[] = '<meta name="dcterms.language" content="' . esc_attr(amt_get_language_content($options, $post)) . '" />'; $metadata_arr[] = '<meta name="dcterms.publisher" content="' . esc_url_raw(trailingslashit(get_bloginfo('url'))) . '" />'; // Copyright page $copyright_url = amt_get_site_copyright_url($options); if (empty($copyright_url)) { $copyright_url = trailingslashit(get_bloginfo('url')); } if (!empty($copyright_url)) { $metadata_arr[] = '<meta name="dcterms.rights" content="' . esc_url_raw($copyright_url) . '" />'; } // License $license_url = ''; // The following requires creative commons configurator if (function_exists('bccl_get_license_url')) { $license_url = bccl_get_license_url(); } // Allow filtering of the license URL $license_url = apply_filters('amt_dublin_core_license', $license_url, $post->ID); // Add metatag if $license_url is not empty. if (!empty($license_url)) { $metadata_arr[] = '<meta name="dcterms.license" content="' . esc_url_raw($license_url) . '" />'; } // Coverage $metadata_arr[] = '<meta name="dcterms.coverage" content="World" />'; if (is_attachment()) { $mime_type = get_post_mime_type($post->ID); //$attachment_type = strstr( $mime_type, '/', true ); // See why we do not use strstr(): http://www.codetrax.org/issues/1091 $attachment_type = preg_replace('#\\/[^\\/]*$#', '', $mime_type); $metadata_arr[] = '<meta name="dcterms.isPartOf" content="' . esc_url_raw(get_permalink($post->post_parent)) . '" />'; if ('image' == $attachment_type) { $metadata_arr[] = '<meta name="dcterms.type" content="Image" />'; $metadata_arr[] = '<meta name="dcterms.format" content="' . $mime_type . '" />'; } elseif ('video' == $attachment_type) { $metadata_arr[] = '<meta name="dcterms.type" content="MovingImage" />'; $metadata_arr[] = '<meta name="dcterms.format" content="' . $mime_type . '" />'; } elseif ('audio' == $attachment_type) { $metadata_arr[] = '<meta name="dcterms.type" content="Sound" />'; $metadata_arr[] = '<meta name="dcterms.format" content="' . $mime_type . '" />'; } // Finally add the hasFormat $metadata_arr[] = '<meta name="dcterms.hasFormat" content="' . esc_url_raw(wp_get_attachment_url($post->ID)) . '" />'; } else { // Default: Text $metadata_arr[] = '<meta name="dcterms.type" content="Text" />'; $metadata_arr[] = '<meta name="dcterms.format" content="text/html" />'; // Add media files // Media Limits $image_limit = amt_metadata_get_image_limit($options); $video_limit = amt_metadata_get_video_limit($options); $audio_limit = amt_metadata_get_audio_limit($options); // Counters $ic = 0; // image counter $vc = 0; // video counter $ac = 0; // audio counter // List attachments foreach ($attachments as $attachment) { $mime_type = get_post_mime_type($attachment->ID); //$attachment_type = strstr( $mime_type, '/', true ); // See why we do not use strstr(): http://www.codetrax.org/issues/1091 $attachment_type = preg_replace('#\\/[^\\/]*$#', '', $mime_type); if ('image' == $attachment_type && $ic < $image_limit) { $metadata_arr[] = '<meta name="dcterms.hasPart" content="' . esc_url_raw(get_permalink($attachment->ID)) . '" />'; // Increase image counter $ic++; } elseif ('video' == $attachment_type && $vc < $video_limit) { $metadata_arr[] = '<meta name="dcterms.hasPart" content="' . esc_url_raw(get_permalink($attachment->ID)) . '" />'; // Increase video counter $vc++; } elseif ('audio' == $attachment_type && $ac < $audio_limit) { $metadata_arr[] = '<meta name="dcterms.hasPart" content="' . esc_url_raw(get_permalink($attachment->ID)) . '" />'; // Increase audio counter $ac++; } } // Embedded Media foreach ($embedded_media['images'] as $embedded_item) { if ($ic == $image_limit) { break; } $metadata_arr[] = '<meta name="dcterms.hasPart" content="' . esc_url_raw($embedded_item['page']) . '" />'; // Increase image counter $ic++; } foreach ($embedded_media['videos'] as $embedded_item) { if ($vc == $video_limit) { break; } $metadata_arr[] = '<meta name="dcterms.hasPart" content="' . esc_url_raw($embedded_item['page']) . '" />'; // Increase video counter $vc++; } foreach ($embedded_media['sounds'] as $embedded_item) { if ($ac == $audio_limit) { break; } $metadata_arr[] = '<meta name="dcterms.hasPart" content="' . esc_url_raw($embedded_item['page']) . '" />'; // Increase audio counter $ac++; } } /** * WordPress Post Formats: http://codex.wordpress.org/Post_Formats * Dublin Core Format: http://dublincore.org/documents/dcmi-terms/#terms-format * Dublin Core DCMIType: http://dublincore.org/documents/dcmi-type-vocabulary/ */ /** * TREAT ALL POST FORMATS AS TEXT (for now) */ /** $format = get_post_format( $post->id ); if ( empty($format) || $format=="aside" || $format=="link" || $format=="quote" || $format=="status" || $format=="chat") { // Default format $metadata_arr[] = '<meta name="dcterms.type" content="Text" />'; $metadata_arr[] = '<meta name="dcterms.format" content="text/html" />'; } elseif ($format=="gallery") { $metadata_arr[] = '<meta name="dcterms.type" content="Collection" />'; // $metadata_arr[] = '<meta name="dcterms.format" content="image" />'; } elseif ($format=="image") { $metadata_arr[] = '<meta name="dcterms.type" content="Image" />'; // $metadata_arr[] = '<meta name="dcterms.format" content="image/png" />'; } elseif ($format=="video") { $metadata_arr[] = '<meta name="dcterms.type" content="Moving Image" />'; $metadata_arr[] = '<meta name="dcterms.format" content="application/x-shockwave-flash" />'; } elseif ($format=="audio") { $metadata_arr[] = '<meta name="dcterms.type" content="Sound" />'; $metadata_arr[] = '<meta name="dcterms.format" content="audio/mpeg" />'; } */ // Filtering of the generated Dublin Core metadata $metadata_arr = apply_filters('amt_dublin_core_metadata_head', $metadata_arr); return $metadata_arr; }
/** * Filter function that generates and embeds Schema.org metadata in the content. */ function amt_add_schemaorg_metadata_content_filter($post_body) { if (is_feed()) { return $post_body; } if (!is_singular() || is_front_page()) { // is_front_page() is used for the case in which a static page is used as the front page. // In this filter function we only deal with content and attachments. return $post_body; } // Get the options the DB $options = get_option("add_meta_tags_opts"); $do_auto_schemaorg = $options["auto_schemaorg"] == "1" ? true : false; if (!$do_auto_schemaorg) { return $post_body; } // Get current post object $post = get_queried_object(); $metadata_arr = array(); // Since this is a function that is hooked to the 'the_content' filter // of WordPress, the post type check has not run, so this happens here. // Check if metadata is supported on this content type. $post_type = get_post_type($post); if (!in_array($post_type, amt_get_supported_post_types())) { return $post_body; } // Get an array containing the attachments $attachments = amt_get_ordered_attachments($post); //var_dump($attachments); // Get an array containing the URLs of the embedded media $embedded_media = amt_get_embedded_media($post); //var_dump($embedded_media); // Products if (amt_is_product()) { // Scope BEGIN: Product: http://schema.org/Product $metadata_arr[] = '<!-- Scope BEGIN: Product -->'; // Construct itemref attribute. Should contain a comma delimited list of IDs. $itemref = apply_filters('amt_schemaorg_itemref_product', ''); if (!empty($itemref)) { $itemref_attrib = ' itemref="' . $itemref . '"'; } else { $itemref_attrib = ''; } $metadata_arr[] = '<div itemscope itemtype="http://schema.org/Product"' . $itemref_attrib . '>'; // URL - Uses amt_get_permalink_for_multipage() $metadata_arr[] = '<meta itemprop="url" content="' . esc_url_raw(amt_get_permalink_for_multipage($post)) . '" />'; // name // Note: Contains multipage information through amt_process_paged() $metadata_arr[] = '<meta itemprop="name" content="' . esc_attr(amt_process_paged(get_the_title($post->ID))) . '" />'; // Description - We use the description defined by Add-Meta-Tags // Note: Contains multipage information through amt_process_paged() $content_desc = amt_get_content_description($post); if (empty($content_desc)) { // Use the post body as the description. Product objects do not support body text. $content_desc = sanitize_text_field(amt_sanitize_description($post_body)); } if (!empty($content_desc)) { $metadata_arr[] = '<meta itemprop="description" content="' . esc_attr(amt_process_paged($content_desc)) . '" />'; } // Dates $metadata_arr[] = '<meta itemprop="releaseDate" content="' . esc_attr(amt_iso8601_date($post->post_date)) . '" />'; // Images // First check if a global image override URL has been entered. // If yes, use this image URL and override all other images. $global_image_override_url = amt_get_post_meta_image_url($post->ID); if (!empty($global_image_override_url)) { $metadata_arr[] = '<!-- Scope BEGIN: ImageObject -->'; $metadata_arr[] = '<span itemprop="image" itemscope itemtype="http://schema.org/ImageObject">'; $metadata_arr[] = '<meta itemprop="contentUrl" content="' . esc_url_raw($global_image_override_url) . '" />'; $metadata_arr[] = '</span> <!-- Scope END: ImageObject -->'; // Further image processing } else { // Set to true if any image attachments are found. Use to finally add the default image // if no image attachments have been found. $has_images = false; // Scope BEGIN: ImageObject: http://schema.org/ImageObject // Image - Featured image is checked first, so that it can be the first associated image. if (function_exists('has_post_thumbnail') && has_post_thumbnail($post->ID)) { // Get the image attachment object $image = get_post(get_post_thumbnail_id($post->ID)); // metadata BEGIN $metadata_arr[] = '<!-- Scope BEGIN: ImageObject -->'; $metadata_arr[] = '<span itemprop="image" itemscope itemtype="http://schema.org/ImageObject">'; // Allow filtering of the image size. $image_size = apply_filters('amt_image_size_product', 'full'); // Get image metatags. $metadata_arr = array_merge($metadata_arr, amt_get_schemaorg_image_metatags($image, $size = $image_size)); // metadata END $metadata_arr[] = '</span> <!-- Scope END: ImageObject -->'; // Images have been found. $has_images = true; } // Scope END: ImageObject // If no images have been found so far use the default image, if set. // Scope BEGIN: ImageObject: http://schema.org/ImageObject if ($has_images === false && !empty($options["default_image_url"])) { $metadata_arr[] = '<!-- Scope BEGIN: ImageObject -->'; $metadata_arr[] = '<span itemprop="image" itemscope itemtype="http://schema.org/ImageObject">'; $metadata_arr[] = '<meta itemprop="contentUrl" content="' . esc_url_raw($options["default_image_url"]) . '" />'; $metadata_arr[] = '</span> <!-- Scope END: ImageObject -->'; } // Scope END: ImageObject } // Extend the current metadata with properties of the Product object. // See: http://schema.org/Product $metadata_arr = apply_filters('amt_product_data_schemaorg', $metadata_arr, $post); // Scope END: Product $metadata_arr[] = '</div> <!-- Scope END: Product -->'; // Filtering of the generated Schema.org metadata $metadata_arr = apply_filters('amt_schemaorg_metadata_product', $metadata_arr); // Add post body // Remove last closing '</div>' tag, add post body and re-add the closing div afterwards. $closing_product_tag = array_pop($metadata_arr); // Product objects do not support a 'text' itemprop. We just add a div for now // for consistency with Article objects. // TODO: it should allow filtering '<div>' $metadata_arr[] = '<div> <!-- Product text body: BEGIN -->'; $metadata_arr[] = $post_body; $metadata_arr[] = '</div> <!-- Product text body: END -->'; // Now add closing tag for Article $metadata_arr[] = $closing_product_tag; // Attachemnts } elseif (is_attachment()) { $mime_type = get_post_mime_type($post->ID); //$attachment_type = strstr( $mime_type, '/', true ); // See why we do not use strstr(): http://www.codetrax.org/issues/1091 $attachment_type = preg_replace('#\\/[^\\/]*$#', '', $mime_type); // Early metatags - Scope starts if ('image' == $attachment_type) { // Scope BEGIN: ImageObject: http://schema.org/ImageObject $metadata_arr[] = '<!-- Scope BEGIN: ImageObject -->'; // Construct itemref attribute. Should contain a comma delimited list of IDs. $itemref = apply_filters('amt_schemaorg_itemref_attachment_image', ''); if (!empty($itemref)) { $itemref_attrib = ' itemref="' . $itemref . '"'; } else { $itemref_attrib = ''; } $metadata_arr[] = '<div itemscope itemtype="http://schema.org/ImageObject"' . $itemref_attrib . '>'; } elseif ('video' == $attachment_type) { // Scope BEGIN: VideoObject: http://schema.org/VideoObject $metadata_arr[] = '<!-- Scope BEGIN: VideoObject -->'; // Construct itemref attribute. Should contain a comma delimited list of IDs. $itemref = apply_filters('amt_schemaorg_itemref_attachment_video', ''); if (!empty($itemref)) { $itemref_attrib = ' itemref="' . $itemref . '"'; } else { $itemref_attrib = ''; } $metadata_arr[] = '<div itemscope itemtype="http://schema.org/VideoObject"' . $itemref_attrib . '>'; } elseif ('audio' == $attachment_type) { // Scope BEGIN: AudioObject: http://schema.org/AudioObject $metadata_arr[] = '<!-- Scope BEGIN: AudioObject -->'; // Construct itemref attribute. Should contain a comma delimited list of IDs. $itemref = apply_filters('amt_schemaorg_itemref_attachment_audio', ''); if (!empty($itemref)) { $itemref_attrib = ' itemref="' . $itemref . '"'; } else { $itemref_attrib = ''; } $metadata_arr[] = '<div itemscope itemtype="http://schema.org/AudioObject"' . $itemref_attrib . '>'; } else { // we do not currently support other attachment types, so we stop processing here return $post_body; } // Metadata commong to all attachments // Publisher // Scope BEGIN: Organization: http://schema.org/Organization $metadata_arr[] = '<!-- Scope BEGIN: Organization -->'; $metadata_arr[] = '<span itemprop="publisher" itemscope itemtype="http://schema.org/Organization">'; // Get publisher metatags $metadata_arr = array_merge($metadata_arr, amt_get_schemaorg_publisher_metatags($options, $post->post_author)); // Scope END: Organization $metadata_arr[] = '</span> <!-- Scope END: Organization -->'; // Author // Scope BEGIN: Person: http://schema.org/Person $metadata_arr[] = '<!-- Scope BEGIN: Person -->'; $metadata_arr[] = '<span itemprop="author" itemscope itemtype="http://schema.org/Person">'; // Get author metatags $metadata_arr = array_merge($metadata_arr, amt_get_schemaorg_author_metatags($post->post_author)); // Scope END: Person $metadata_arr[] = '</span> <!-- Scope END: Person -->'; // Dates $metadata_arr[] = '<meta itemprop="datePublished" content="' . esc_attr(amt_iso8601_date($post->post_date)) . '" />'; $metadata_arr[] = '<meta itemprop="dateModified" content="' . esc_attr(amt_iso8601_date($post->post_modified)) . '" />'; $metadata_arr[] = '<meta itemprop="copyrightYear" content="' . esc_attr(mysql2date('Y', $post->post_date)) . '" />'; // Language $metadata_arr[] = '<meta itemprop="inLanguage" content="' . esc_attr(str_replace('-', '_', amt_get_language_content($options))) . '" />'; // Metadata specific to each attachment type if ('image' == $attachment_type) { // Allow filtering of the image size. $image_size = apply_filters('amt_image_size_attachment', 'full'); // Get image metatags. $post is an image object. $metadata_arr = array_merge($metadata_arr, amt_get_schemaorg_image_metatags($post, $size = $image_size, $is_representative = true)); // Add the post body here $metadata_arr[] = $post_body; // Scope END: ImageObject $metadata_arr[] = '</div> <!-- Scope END: ImageObject -->'; } elseif ('video' == $attachment_type) { // Video specific metatags // URL (for attachments: links to attachment page) $metadata_arr[] = '<meta itemprop="url" content="' . esc_url_raw(get_permalink($post->ID)) . '" />'; $metadata_arr[] = '<meta itemprop="contentUrl" content="' . esc_url_raw(wp_get_attachment_url($post->ID)) . '" />'; $metadata_arr[] = '<meta itemprop="encodingFormat" content="' . esc_attr($mime_type) . '" />'; // Add the post body here $metadata_arr[] = $post_body; // Scope END: VideoObject $metadata_arr[] = '</div> <!-- Scope END: VideoObject -->'; } elseif ('audio' == $attachment_type) { // Audio specific metatags // URL (for attachments: links to attachment page) $metadata_arr[] = '<meta itemprop="url" content="' . esc_url_raw(get_permalink($post->ID)) . '" />'; $metadata_arr[] = '<meta itemprop="contentUrl" content="' . esc_url_raw(wp_get_attachment_url($post->ID)) . '" />'; $metadata_arr[] = '<meta itemprop="encodingFormat" content="' . esc_attr($mime_type) . '" />'; // Add the post body here $metadata_arr[] = $post_body; // Scope END: AudioObject $metadata_arr[] = '</div> <!-- Scope END: AudioObject -->'; } // Content } else { // Set main metadata entity. By default this set to Article. $main_content_object = 'Article'; // Check for Page // Main entity is set to WebPage on pages // DEV NOTE: Since many themes already set the WebPage itemscope on the // body element of the web page, set it to WebPage automatically would // result in duplicate entities. So this has to be done manually via // a filtering function. // if ( is_page() ) { // $main_content_object = 'WebPage'; // } // Check for Review $express_review_field_data = amt_get_post_meta_express_review($post->ID); $review_data = array(); if (!empty($express_review_field_data)) { $review_data = amt_get_review_data($express_review_field_data); if (!empty($review_data)) { $main_content_object = 'Review'; } } // Allow filtering the main metadata object for content. $main_content_object = apply_filters('amt_schemaorg_object_main', $main_content_object); // Scope BEGIN: Article: http://schema.org/Article $metadata_arr[] = '<!-- Scope BEGIN: ' . esc_attr($main_content_object) . ' -->'; // Construct itemref attribute. Should contain a comma delimited list of IDs. $itemref = apply_filters('amt_schemaorg_itemref_content', ''); if (!empty($itemref)) { $itemref_attrib = ' itemref="' . $itemref . '"'; } else { $itemref_attrib = ''; } $metadata_arr[] = '<div itemscope itemtype="http://schema.org/' . esc_attr($main_content_object) . '"' . $itemref_attrib . '>'; // Publisher // Scope BEGIN: Organization: http://schema.org/Organization $metadata_arr[] = '<!-- Scope BEGIN: Organization -->'; $metadata_arr[] = '<span itemprop="publisher" itemscope itemtype="http://schema.org/Organization">'; // Get publisher metatags $metadata_arr = array_merge($metadata_arr, amt_get_schemaorg_publisher_metatags($options, $post->post_author)); // Scope END: Organization $metadata_arr[] = '</span> <!-- Scope END: Organization -->'; // Author // Scope BEGIN: Person: http://schema.org/Person $metadata_arr[] = '<!-- Scope BEGIN: Person -->'; $metadata_arr[] = '<span itemprop="author" itemscope itemtype="http://schema.org/Person">'; // Get publisher metatags $metadata_arr = array_merge($metadata_arr, amt_get_schemaorg_author_metatags($post->post_author)); // Scope END: Person $metadata_arr[] = '</span> <!-- Scope END: Person -->'; // URL - Uses amt_get_permalink_for_multipage() $metadata_arr[] = '<meta itemprop="url" content="' . esc_url_raw(amt_get_permalink_for_multipage($post)) . '" />'; // Dates $metadata_arr[] = '<meta itemprop="datePublished" content="' . esc_attr(amt_iso8601_date($post->post_date)) . '" />'; $metadata_arr[] = '<meta itemprop="dateModified" content="' . esc_attr(amt_iso8601_date($post->post_modified)) . '" />'; $metadata_arr[] = '<meta itemprop="copyrightYear" content="' . esc_attr(mysql2date('Y', $post->post_date)) . '" />'; // Language $metadata_arr[] = '<meta itemprop="inLanguage" content="' . esc_attr(str_replace('-', '_', amt_get_language_content($options))) . '" />'; // name // Note: Contains multipage information through amt_process_paged() $metadata_arr[] = '<meta itemprop="name" content="' . esc_attr(amt_process_paged(get_the_title($post->ID))) . '" />'; // headline $metadata_arr[] = '<meta itemprop="headline" content="' . esc_attr(get_the_title($post->ID)) . '" />'; // Description - We use the description defined by Add-Meta-Tags // Note: Contains multipage information through amt_process_paged() $content_desc = amt_get_content_description($post); if (!empty($content_desc)) { $metadata_arr[] = '<meta itemprop="description" content="' . esc_attr(amt_process_paged($content_desc)) . '" />'; } /* // Section: We use the first category as the section $first_cat = sanitize_text_field( amt_sanitize_keywords( amt_get_first_category($post) ) ); if (!empty($first_cat)) { $metadata_arr[] = '<meta itemprop="articleSection" content="' . esc_attr( $first_cat ) . '" />'; } */ // Add articleSection in Article object only. if ($main_content_object == 'Article') { $categories = get_the_category($post->ID); $categories = apply_filters('amt_post_categories_for_schemaorg', $categories); foreach ($categories as $cat) { $section = trim($cat->cat_name); if (!empty($section) && $cat->slug != 'uncategorized') { $metadata_arr[] = '<meta itemprop="articleSection" content="' . esc_attr($section) . '" />'; } } } // Add review properties if Review if ($main_content_object == 'Review') { $metadata_arr[] = '<!-- Review Information BEGIN -->'; $metadata_arr[] = amt_get_review_info_box($review_data); $metadata_arr[] = '<!-- Review Information END -->'; } // Keywords - We use the keywords defined by Add-Meta-Tags $keywords = amt_get_content_keywords($post); if (!empty($keywords)) { $metadata_arr[] = '<meta itemprop="keywords" content="' . esc_attr($keywords) . '" />'; } // Referenced Items $referenced_url_list = amt_get_referenced_items($post); foreach ($referenced_url_list as $referenced_url) { $referenced_url = trim($referenced_url); if (!empty($referenced_url)) { $metadata_arr[] = '<meta itemprop="referencedItem" content="' . esc_url_raw($referenced_url) . '" />'; } } // Images // First check if a global image override URL has been entered. // If yes, use this image URL and override all other images. $global_image_override_url = amt_get_post_meta_image_url($post->ID); if (!empty($global_image_override_url)) { $metadata_arr[] = '<!-- Scope BEGIN: ImageObject -->'; $metadata_arr[] = '<span itemprop="image" itemscope itemtype="http://schema.org/ImageObject">'; $metadata_arr[] = '<meta itemprop="contentUrl" content="' . esc_url_raw($global_image_override_url) . '" />'; $metadata_arr[] = '</span> <!-- Scope END: ImageObject -->'; // Further image processing } else { // We store the featured image ID in this variable so that it can easily be excluded // when all images are parsed from the $attachments array. $featured_image_id = 0; // Set to true if any image attachments are found. Use to finally add the default image // if no image attachments have been found. $has_images = false; // Scope BEGIN: ImageObject: http://schema.org/ImageObject // Image - Featured image is checked first, so that it can be the first associated image. if (function_exists('has_post_thumbnail') && has_post_thumbnail($post->ID)) { // Thumbnail URL // First add the thumbnail URL of the featured image $thumbnail_info = wp_get_attachment_image_src(get_post_thumbnail_id($post->ID), 'thumbnail'); $metadata_arr[] = '<meta itemprop="thumbnailUrl" content="' . esc_url_raw($thumbnail_info[0]) . '" />'; // Add full image object for featured image. // Get the image attachment object $image = get_post(get_post_thumbnail_id($post->ID)); // metadata BEGIN $metadata_arr[] = '<!-- Scope BEGIN: ImageObject -->'; $metadata_arr[] = '<span itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">'; // Allow filtering of the image size. $image_size = apply_filters('amt_image_size_content', 'full'); // Get image metatags. $metadata_arr = array_merge($metadata_arr, amt_get_schemaorg_image_metatags($image, $size = $image_size)); // metadata END $metadata_arr[] = '</span> <!-- Scope END: ImageObject -->'; // Finally, set the $featured_image_id $featured_image_id = get_post_thumbnail_id($post->ID); // Images have been found. $has_images = true; } // Scope END: ImageObject // Process all attachments and add metatags (featured image will be excluded) foreach ($attachments as $attachment) { // Excluded the featured image since if ($attachment->ID != $featured_image_id) { $mime_type = get_post_mime_type($attachment->ID); //$attachment_type = strstr( $mime_type, '/', true ); // See why we do not use strstr(): http://www.codetrax.org/issues/1091 $attachment_type = preg_replace('#\\/[^\\/]*$#', '', $mime_type); if ('image' == $attachment_type) { // metadata BEGIN $metadata_arr[] = '<!-- Scope BEGIN: ImageObject -->'; $metadata_arr[] = '<span itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">'; // Allow filtering of the image size. $image_size = apply_filters('amt_image_size_content', 'full'); // Get image metatags. $metadata_arr = array_merge($metadata_arr, amt_get_schemaorg_image_metatags($attachment, $size = $image_size)); // metadata END $metadata_arr[] = '</span> <!-- Scope END: ImageObject -->'; // Images have been found. $has_images = true; } elseif ('video' == $attachment_type) { // Scope BEGIN: VideoObject: http://schema.org/VideoObject $metadata_arr[] = '<!-- Scope BEGIN: VideoObject -->'; $metadata_arr[] = '<span itemprop="associatedMedia" itemscope itemtype="http://schema.org/VideoObject">'; // Video specific metatags // URL (for attachments: links to attachment page) $metadata_arr[] = '<meta itemprop="url" content="' . esc_url_raw(get_permalink($attachment->ID)) . '" />'; $metadata_arr[] = '<meta itemprop="contentUrl" content="' . esc_url_raw(wp_get_attachment_url($attachment->ID)) . '" />'; $metadata_arr[] = '<meta itemprop="encodingFormat" content="' . esc_attr($mime_type) . '" />'; // Scope END: VideoObject $metadata_arr[] = '</span> <!-- Scope END: VideoObject -->'; } elseif ('audio' == $attachment_type) { // Scope BEGIN: AudioObject: http://schema.org/AudioObject $metadata_arr[] = '<!-- Scope BEGIN: AudioObject -->'; $metadata_arr[] = '<span itemprop="associatedMedia" itemscope itemtype="http://schema.org/AudioObject">'; // Audio specific metatags // URL (for attachments: links to attachment page) $metadata_arr[] = '<meta itemprop="url" content="' . esc_url_raw(get_permalink($attachment->ID)) . '" />'; $metadata_arr[] = '<meta itemprop="contentUrl" content="' . esc_url_raw(wp_get_attachment_url($attachment->ID)) . '" />'; $metadata_arr[] = '<meta itemprop="encodingFormat" content="' . esc_attr($mime_type) . '" />'; // Scope END: AudioObject $metadata_arr[] = '</span> <!-- Scope END: AudioObject -->'; } } } // Embedded Media foreach ($embedded_media['images'] as $embedded_item) { // Scope BEGIN: ImageObject: http://schema.org/ImageObject $metadata_arr[] = '<!-- Scope BEGIN: ImageObject -->'; $metadata_arr[] = '<span itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">'; // name (title) $metadata_arr[] = '<meta itemprop="name" content="' . esc_attr($embedded_item['alt']) . '" />'; // caption $metadata_arr[] = '<meta itemprop="caption" content="' . esc_attr($embedded_item['alt']) . '" />'; // alt $metadata_arr[] = '<meta itemprop="text" content="' . esc_attr($embedded_item['alt']) . '" />'; // URL (links to web page containing the image) $metadata_arr[] = '<meta itemprop="url" content="' . esc_url_raw($embedded_item['page']) . '" />'; // thumbnail url $metadata_arr[] = '<meta itemprop="thumbnailUrl" content="' . esc_url_raw($embedded_item['thumbnail']) . '" />'; // main image $metadata_arr[] = '<meta itemprop="contentUrl" content="' . esc_url_raw($embedded_item['image']) . '" />'; if (apply_filters('amt_extended_image_tags', true)) { $metadata_arr[] = '<meta itemprop="width" content="' . esc_attr($embedded_item['width']) . '" />'; $metadata_arr[] = '<meta itemprop="height" content="' . esc_attr($embedded_item['height']) . '" />'; $metadata_arr[] = '<meta itemprop="encodingFormat" content="image/jpeg" />'; } // embedURL $metadata_arr[] = '<meta itemprop="embedURL" content="' . esc_url_raw($embedded_item['player']) . '" />'; // Scope END: ImageObject $metadata_arr[] = '</span> <!-- Scope END: ImageObject -->'; // Images have been found. $has_images = true; } foreach ($embedded_media['videos'] as $embedded_item) { // Scope BEGIN: VideoObject: http://schema.org/VideoObject // See: http://googlewebmastercentral.blogspot.gr/2012/02/using-schemaorg-markup-for-videos.html // See: https://support.google.com/webmasters/answer/2413309?hl=en $metadata_arr[] = '<!-- Scope BEGIN: VideoObject -->'; $metadata_arr[] = '<span itemprop="video" itemscope itemtype="http://schema.org/VideoObject">'; // Video Embed URL $metadata_arr[] = '<meta itemprop="embedURL" content="' . esc_url_raw($embedded_item['player']) . '" />'; // playerType $metadata_arr[] = '<meta itemprop="playerType" content="application/x-shockwave-flash" />'; // size $metadata_arr[] = '<meta itemprop="width" content="' . esc_attr($embedded_item['width']) . '" />'; $metadata_arr[] = '<meta itemprop="height" content="' . esc_attr($embedded_item['height']) . '" />'; // Scope END: VideoObject $metadata_arr[] = '</span> <!-- Scope END: VideoObject -->'; } foreach ($embedded_media['sounds'] as $embedded_item) { // Scope BEGIN: AudioObject: http://schema.org/AudioObject $metadata_arr[] = '<!-- Scope BEGIN: AudioObject -->'; $metadata_arr[] = '<span itemprop="audio" itemscope itemtype="http://schema.org/AudioObject">'; // Audio Embed URL $metadata_arr[] = '<meta itemprop="embedURL" content="' . esc_url_raw($embedded_item['player']) . '" />'; // playerType $metadata_arr[] = '<meta itemprop="playerType" content="application/x-shockwave-flash" />'; // Scope END: AudioObject $metadata_arr[] = '</span> <!-- Scope END: AudioObject -->'; } // If no images have been found so far use the default image, if set. // Scope BEGIN: ImageObject: http://schema.org/ImageObject if ($has_images === false && !empty($options["default_image_url"])) { $metadata_arr[] = '<!-- Scope BEGIN: ImageObject -->'; $metadata_arr[] = '<span itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">'; $metadata_arr[] = '<meta itemprop="contentUrl" content="' . esc_url_raw($options["default_image_url"]) . '" />'; $metadata_arr[] = '</span> <!-- Scope END: ImageObject -->'; } // Scope END: ImageObject } // Article Body // The article body is added after filtering the generated microdata below. // TODO: also check: comments, contributor, copyrightHolder, , creator, dateCreated, discussionUrl, editor, version (use post revision if possible) // Scope END: Article $metadata_arr[] = '</div> <!-- Scope END: ' . esc_attr($main_content_object) . ' -->'; // Filtering of the generated Schema.org metadata $metadata_arr = apply_filters('amt_schemaorg_metadata_content', $metadata_arr); // Add articleBody to Artice // Now add the article. Remove last closing '</span>' tag, add articleBody and re-add the closing span afterwards. $closing_article_tag = array_pop($metadata_arr); // Use the 'text' itemprop by default for the main text body of the CreativeWork, // so it can be used by more subtypes than Article. // But set it explicitly to 'articleBody if the main entiry is 'Article' // or 'reviewBody' if the main entity is a 'Review'. $main_text_property = 'text'; if ($main_content_object == 'Article') { $main_text_property = 'articleBody'; } elseif ($main_content_object == 'Review') { $main_text_property = 'reviewBody'; } // Allow filtering of the main text property. $main_text_property = apply_filters('amt_schemaorg_property_main_text', $main_text_property); $metadata_arr[] = '<div itemprop="' . esc_attr($main_text_property) . '">'; $metadata_arr[] = $post_body; $metadata_arr[] = '</div> <!-- Itemprop END: ' . esc_attr($main_text_property) . ' -->'; // Now add closing tag for Article $metadata_arr[] = $closing_article_tag; } // Add our comment if (count($metadata_arr) > 0) { array_unshift($metadata_arr, "<!-- BEGIN Schema.org microdata added by Add-Meta-Tags WordPress plugin -->"); array_unshift($metadata_arr, ""); // Intentionaly left empty array_push($metadata_arr, "<!-- END Schema.org microdata added by Add-Meta-Tags WordPress plugin -->"); array_push($metadata_arr, ""); // Intentionaly left empty } //return $post_body; return implode(PHP_EOL, $metadata_arr); }