PluginProbe
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO / 2.9.0
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO v2.9.0
2.10.0 2.9.0 2.8.0 2.7.0 2.6.0 2.5.0 2.4.0 2.3.0 2.2.0 2.1.1 2.1.0 2.0.2 2.0.1 2.0.0 1.32.0 1.31.0 1.30.0 1.29.0 1.28.0 1.27.0 1.26.0 1.25.0 trunk 1.0.0 1.0.1 All 51 releases
← All changes | includes/frontend/class-global-seo-schema-output.php +67 -9 2.3.0 → 2.9.0 View file →
@@ -104,8 +104,22 @@
104 104 }
105 105
106 106 $settings = $this->get_global_seo_settings($post_type);
107 107 if (($settings['schema_type'] ?? '') === 'Product') {
108 + // ...but only if this class is actually going to emit it. The
109 + // per-content-type Schema switch (#660) makes
110 + // output_global_seo_schema() return before it builds anything, so
111 + // claiming the entity here as well left the page with NO product
112 + // structured data at all — strictly worse than the duplicate this
113 + // method exists to prevent, and the opposite of what the docblock
114 + // above promises for "ThinkRank's product schema disabled".
115 + if (!\ThinkRank\SEO\Content_Type_Settings::is_enabled_for_current(
116 + \ThinkRank\SEO\Content_Type_Settings::FEATURE_SCHEMA,
117 + true
118 + )) {
119 + return $markup;
120 + }
121 +
108 122 return [];
109 123 }
110 124
111 125 // A per-post DEPLOYED Product schema duplicates WooCommerce's markup
@@ -153,8 +167,17 @@
153 167 * @since 1.0.0
154 168 * @return void
155 169 */
156 170 public function output_global_seo_schema(): void {
171 + // Per-content-type schema switch. 'inherit' (the default) keeps schema
172 + // on, exactly as before the matrix existed (#660).
173 + if (!\ThinkRank\SEO\Content_Type_Settings::is_enabled_for_current(
174 + \ThinkRank\SEO\Content_Type_Settings::FEATURE_SCHEMA,
175 + true
176 + )) {
177 + return;
178 + }
179 +
157 180 // Archives get a CollectionPage schema instead of the per-post-type one
158 181 if (!is_singular()) {
159 182 $this->output_archive_schema();
160 183 return;
@@ -327,8 +350,16 @@
327 350 * @param string $post_type Post type slug.
328 351 * @return bool True when structured data would be output for this post type.
329 352 */
330 353 public function would_output_schema(string $post_type): bool {
354 + if (!\ThinkRank\SEO\Content_Type_Settings::is_enabled(
355 + \ThinkRank\SEO\Content_Type_Settings::FEATURE_SCHEMA,
356 + $post_type,
357 + true
358 + )) {
359 + return false;
360 + }
361 +
331 362 $settings = $this->get_global_seo_settings($post_type);
332 363
333 364 return !empty($settings['schema_type']);
334 365 }
@@ -492,10 +523,11 @@
492 523 'datePublished' => get_the_date('c', $post),
493 524 'dateModified' => get_the_modified_date('c', $post),
494 525 ];
495 526
496 - // Add description
497 - $excerpt = get_the_excerpt($post);
527 + // Add description. A Bricks page's stored `post_content` is not on the
528 + // page, so core's derived excerpt must not describe it (#651).
529 + $excerpt = $this->post_excerpt_text($post);
498 530 if (!empty($excerpt)) {
499 531 $schema['description'] = wp_strip_all_tags($excerpt);
500 532 }
501 533
@@ -566,9 +598,9 @@
566 598 }
567 599 require_once $builder_file;
568 600 }
569 601
570 - $excerpt = get_the_excerpt($post);
602 + $excerpt = $this->post_excerpt_text($post);
571 603
572 604 $builder = new \ThinkRank\SEO\Schema_Builder();
573 605 $schema = $builder->build_schema(
574 606 'FAQPage',
@@ -573,9 +605,9 @@
573 605 $schema = $builder->build_schema(
574 606 'FAQPage',
575 607 [
576 608 'title' => get_the_title($post),
577 - 'content' => $post->post_content,
609 + 'content' => \ThinkRank\SEO\Builder_Content::visible_content($post),
578 610 'excerpt' => $excerpt ? wp_strip_all_tags($excerpt) : '',
579 611 'url' => get_permalink($post),
580 612 ],
581 613 get_post_type($post) === 'page' ? 'page' : 'post'
@@ -646,9 +678,9 @@
646 678 'dateModified' => get_the_modified_date('c', $post),
647 679 ];
648 680
649 681 // Add description
650 - $excerpt = get_the_excerpt($post);
682 + $excerpt = $this->post_excerpt_text($post);
651 683 if (!empty($excerpt)) {
652 684 $schema['description'] = wp_strip_all_tags($excerpt);
653 685 }
654 686
@@ -716,9 +748,9 @@
716 748 'url' => get_permalink($post),
717 749 ];
718 750
719 751 // Add description
720 - $description = get_the_excerpt($post);
752 + $description = $this->post_excerpt_text($post);
721 753 if (empty($description)) {
722 754 $caption = wp_get_attachment_caption($post->ID);
723 755 if (!empty($caption)) {
724 756 $description = $caption;
@@ -882,15 +914,20 @@
882 914 private function get_product_description(\WP_Post $post): string {
883 915 // Try custom meta field first
884 916 $description = get_post_meta($post->ID, '_thinkrank_product_description', true);
885 917
886 - // Fallback to excerpt or content
918 + // Fallback to excerpt or content. On a Bricks page the excerpt core
919 + // derives comes from discarded `post_content`, so the visible body is
920 + // used instead (#651).
887 921 if (empty($description)) {
888 - $description = get_the_excerpt($post);
922 + $description = $this->post_excerpt_text($post);
889 923 }
890 924
891 925 if (empty($description)) {
892 - $description = \ThinkRank\SEO\Pattern_Resolver::derive_excerpt((string) $post->post_content, 30);
926 + $description = \ThinkRank\SEO\Pattern_Resolver::derive_excerpt(
927 + \ThinkRank\SEO\Builder_Content::visible_content($post),
928 + 30
929 + );
893 930 }
894 931
895 932 return wp_strip_all_tags($description);
896 933 }
@@ -1154,8 +1191,29 @@
1154 1191 }
1155 1192 }
1156 1193
1157 1194 return $reviews;
1195 + }
1196 +
1197 + /**
1198 + * The post's excerpt, taken from content the page actually renders.
1199 + *
1200 + * `get_the_excerpt()` falls back to trimming `post_content`, which a Bricks
1201 + * page discards — so on one of those it describes text no visitor sees. A
1202 + * hand-written excerpt is the author's own summary and still wins, because
1203 + * `superseding_excerpt_source()` yields nothing for a post that has one
1204 + * (#651).
1205 + *
1206 + * @since 2.3.1
1207 + * @param \WP_Post $post Post being described.
1208 + * @return string
1209 + */
1210 + private function post_excerpt_text(\WP_Post $post): string {
1211 + $superseding = \ThinkRank\SEO\Builder_Content::superseding_excerpt_source($post);
1212 +
1213 + return '' !== $superseding
1214 + ? \ThinkRank\SEO\Pattern_Resolver::derive_excerpt($superseding, 30)
1215 + : (string) get_the_excerpt($post);
1158 1216 }
1159 1217
1160 1218 /**
1161 1219 * Register generated schema with the request's schema graph.