PluginProbe
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO / 2.10.0
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO v2.10.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/seo/class-schema-validator.php +43 -4 1.0.1 → 2.10.0 View file →
@@ -80,10 +80,19 @@
80 80 return $validation;
81 81 }
82 82
83 83 $schema_type = $schema['@type'];
84 - $spec = $this->schema_factory->get_schema_specification($schema_type);
85 84
85 + // A LocalBusiness node carries the subtype the site chose ("Dentist"),
86 + // and none of the ~150 subtypes has a spec of its own. They all share
87 + // LocalBusiness's requirements, so validate against that rather than
88 + // reporting the site's own business type as unsupported.
89 + if (\ThinkRank\Config\Local_Business_Types_Config::is_local_business($schema_type)) {
90 + $schema_type = 'LocalBusiness';
91 + }
92 +
93 + $spec =$this->schema_factory->get_schema_specification($schema_type);
94 +
86 95 if (empty($spec)) {
87 96 $validation['errors'][] = "Unsupported schema type: {$schema_type}";
88 97 $validation['valid'] = false;
89 98 return $validation;
@@ -155,8 +164,11 @@
155 164 break;
156 165 case 'FAQPage':
157 166 $validation = $this->validate_faq_schema($schema, $validation);
158 167 break;
168 + case 'VideoObject':
169 + $validation = $this->validate_video_object_schema($schema, $validation);
170 + break;
159 171 }
160 172
161 173 return $validation;
162 174 }
@@ -161,8 +173,35 @@
161 173 return $validation;
162 174 }
163 175
164 176 /**
177 + * Validate VideoObject schema specific requirements.
178 + *
179 + * Google requires name, description, thumbnailUrl and uploadDate. A video is
180 + * only playable with a contentUrl or embedUrl, so warn when both are missing.
181 + *
182 + * @since 1.0.0
183 + *
184 + * @param array $schema Schema markup
185 + * @param array $validation Current validation results
186 + * @return array Updated validation results
187 + */
188 + private function validate_video_object_schema(array $schema, array $validation): array {
189 + foreach (['name', 'description', 'thumbnailUrl', 'uploadDate'] as $field) {
190 + if (empty($schema[$field])) {
191 + $validation['errors'][] = sprintf('VideoObject schema requires a %s', $field);
192 + $validation['valid'] = false;
193 + }
194 + }
195 +
196 + if (empty($schema['contentUrl']) && empty($schema['embedUrl'])) {
197 + $validation['warnings'][] = 'VideoObject should include a contentUrl or embedUrl so the video is playable';
198 + }
199 +
200 + return $validation;
201 + }
202 +
203 + /**
165 204 * Validate Article schema specific requirements
166 205 * PRESERVED: Exact same method logic from original Schema_Generator
167 206 *
168 207 * @since 1.0.0
@@ -172,9 +211,9 @@
172 211 * @return array Updated validation results
173 212 */
174 213 private function validate_article_schema(array $schema, array $validation): array {
175 214 // Check headline length (Google recommends under 110 characters)
176 - if (isset($schema['headline']) && strlen($schema['headline']) > 110) {
215 + if (isset($schema['headline']) && is_string($schema['headline']) && strlen($schema['headline']) > 110) {
177 216 $validation['warnings'][] = 'Headline is longer than 110 characters, may be truncated in search results';
178 217 }
179 218
180 219 // Check for image
@@ -341,9 +380,9 @@
341 380 if (isset($schema['logo']) && !empty($schema['logo']) &&
342 381 (is_string($schema['logo']) || (is_array($schema['logo']) && !empty($schema['logo']['url'])))) {
343 382 $has_logo = true;
344 383 } elseif (isset($schema['publisher']['logo']) && !empty($schema['publisher']['logo']) &&
345 - (is_string($schema['publisher']['logo']) || (is_array($schema['publisher']['logo']) && !empty($schema['publisher']['logo']['url'])))) {
384 + (is_string($schema['publisher']['logo']) || (is_array($schema['publisher']['logo']) && !empty($schema['publisher']['logo']['url'])))) {
346 385 $has_logo = true;
347 386 }
348 387
349 388 if (!$has_logo) {
@@ -376,9 +415,9 @@
376 415 * @return array Updated validation results
377 416 */
378 417 private function validate_faq_schema(array $schema, array $validation): array {
379 418 // Check minimum number of questions
380 - if (isset($schema['mainEntity']) && count($schema['mainEntity']) < 2) {
419 + if (isset($schema['mainEntity']) && is_array($schema['mainEntity']) && count($schema['mainEntity']) < 2) {
381 420 $validation['warnings'][] = 'FAQ pages should have at least 2 questions for optimal SEO';
382 421 }
383 422
384 423 // Validate question structure