PluginProbe
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO / 2.11.0
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO v2.11.0
2.11.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 All 52 releases
← All changes | includes/abilities/analysis/class-get-post-seo-checks.php +51 -3 1.25.0 → 2.11.0 View file →
@@ -12,8 +12,9 @@
12 12 use ThinkRank\Abilities\Ability_Base;
13 13 use ThinkRank\Admin\Metabox_Manager;
14 14 use ThinkRank\AI\SEOScoreCalculator;
15 15 use ThinkRank\Core\Database;
16 +use ThinkRank\SEO\Pattern_Resolver;
16 17
17 18 if ( ! defined( 'ABSPATH' ) ) {
18 19 exit; // Exit if accessed directly.
19 20 }
@@ -27,9 +28,9 @@
27 28 */
28 29 public function __construct() {
29 30 $this->id = 'thinkrank/get-post-seo-checks';
30 31 $this->label = __( 'Get ThinkRank Post SEO Checks', 'thinkrank' );
31 - $this->description = __( 'Run ThinkRank SEO score analysis for one or more posts, pages, or custom post type items.', 'thinkrank' );
32 + $this->description = __( 'Run ThinkRank SEO score analysis for one or more posts, pages, or custom post type items. Each score includes keywords: for every focus keyword, whether it appears in the SEO title, meta description, URL slug, first paragraph, a subheading (H2-H6), the body, and an image alt text, with the heading or alt text that matched - use it to see which keyword is missing where. Scores are not persisted; use bulk-analyze-and-save to score and store them.', 'thinkrank' );
32 33 }
33 34
34 35 /**
35 36 * {@inheritDoc}
@@ -78,9 +79,47 @@
78 79 'type' => 'object',
79 80 'properties' => [
80 81 'status' => [ 'type' => 'string' ],
81 82 'message' => [ 'type' => 'string' ],
82 - 'data' => [ 'type' => 'array' ],
83 + 'data' => [
84 + 'type' => 'array',
85 + 'items' => [
86 + 'type' => 'object',
87 + 'properties' => [
88 + 'post_id' => [ 'type' => 'integer' ],
89 + 'error' => [ 'type' => 'string' ],
90 + 'score' => [
91 + 'type' => 'object',
92 + 'properties' => [
93 + 'overall_score' => [ 'type' => 'integer' ],
94 + 'grade' => [ 'type' => 'string' ],
95 + 'keywords' => [
96 + 'type' => 'array',
97 + 'items' => [
98 + 'type' => 'object',
99 + 'properties' => [
100 + 'keyword' => [ 'type' => 'string' ],
101 + 'passed' => [
102 + 'type' => 'integer',
103 + 'description' => __( 'Placements the keyword appears in.', 'thinkrank' ),
104 + ],
105 + 'total' => [ 'type' => 'integer' ],
106 + 'placements' => [
107 + 'type' => 'object',
108 + 'description' => sprintf(
109 + /* translators: %s: comma-separated placement names. */
110 + __( 'One entry per placement (%s), each {passed, where}; where is the matching heading or alt text.', 'thinkrank' ),
111 + implode( ', ', SEOScoreCalculator::PLACEMENTS )
112 + ),
113 + ],
114 + ],
115 + ],
116 + ],
117 + ],
118 + ],
119 + ],
120 + ],
121 + ],
83 122 ],
84 123 ];
85 124 }
86 125
@@ -115,9 +154,18 @@
115 154
116 155 foreach ( $post_ids as $post_id ) {
117 156 try {
118 157 $content = $calculator->analyze_post_content( $post_id );
119 - $score = $calculator->calculate_score( $content, $metabox->get_post_metadata( $post_id ) );
158 +
159 + // Override the raw per-post title/description with their effective
160 + // values (custom value, else the resolved Global pattern) so an
161 + // inherited title or description is scored as present — matching
162 + // the editor and frontend — instead of counting as missing.
163 + $metadata = $metabox->get_post_metadata( $post_id );
164 + $metadata['title'] = Pattern_Resolver::effective_title( $post_id );
165 + $metadata['description'] = Pattern_Resolver::effective_description( $post_id );
166 +
167 + $score = $calculator->calculate_score( $content, $metadata );
120 168
121 169 $data[] = [
122 170 'post_id' => $post_id,
123 171 'score' => $score,