PluginProbe
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO / 2.14.0
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO v2.14.0
2.14.1 2.14.0 2.13.0 2.12.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 All 56 releases
← All changes | includes/seo/class-seo-analyzer.php +10 -85 2.14.1 → 2.14.0 View file →
@@ -1245,13 +1245,8 @@
1245 1245 * REST request would fire every shortcode and block renderer on the site.
1246 1246 * The structural signals these checks look for (headings, lists, tables,
1247 1247 * the opening passage) survive in the stored markup.
1248 1248 *
1249 - * Except on a builder page, where they do not: the words and headings are
1250 - * in builder meta and `post_content` is empty, or, on a Bricks page, holds
1251 - * blocks Bricks never renders. Those rows read from builder_content(), so
1252 - * a builder-built site is graded on its pages rather than skipped (#892).
1253 - *
1254 1249 * @since 2.5.0
1255 1250 * @return array<int,array{id: int, content: string, text: string, modified: int}>
1256 1251 */
1257 1252 private function get_content_sample(): array {
@@ -1260,12 +1255,10 @@
1260 1255 }
1261 1256
1262 1257 $post_ids = $this->sample_post_ids();
1263 1258
1264 - // Meta too: builder_content() asks every sampled post whether Bricks
1265 - // owns it, and one query beats a hundred.
1266 1259 if (function_exists('_prime_post_caches')) {
1267 - _prime_post_caches($post_ids, false, true);
1260 + _prime_post_caches($post_ids, false, false);
1268 1261 }
1269 1262
1270 1263 $sample = [];
1271 1264
@@ -1276,9 +1269,9 @@
1276 1269 }
1277 1270
1278 1271 $modified = isset($post->post_modified_gmt) ? strtotime((string) $post->post_modified_gmt . ' UTC') : false;
1279 1272
1280 - $content = $this->builder_content($post) ?? (string) $post->post_content;
1273 + $content = (string) $post->post_content;
1281 1274
1282 1275 $sample[] = [
1283 1276 'id' => (int) $post->ID,
1284 1277 'content' => $content,
@@ -1292,45 +1285,8 @@
1292 1285 return $sample;
1293 1286 }
1294 1287
1295 1288 /**
1296 - * A sampled post's content from its page builder, when that is where it is.
1297 - *
1298 - * Null for every post whose `post_content` is what the visitor reads, so
1299 - * those keep the raw-markup path and never pay for rendering. A post with
1300 - * an empty `post_content`, or a Bricks page that discards it, resolves
1301 - * through Builder_Content, the extractor every other server-side scoring
1302 - * path reads through (#617). With nothing in `post_content` to render, the
1303 - * resolution only reads stored builder meta: no shortcode or block
1304 - * renderer runs.
1305 - *
1306 - * Guarded like builder_meta_keys(), so a partial checkout degrades to the
1307 - * raw markup instead of fataling mid-audit.
1308 - *
1309 - * @since 2.15.0
1310 - *
1311 - * @param \WP_Post $post Sampled post.
1312 - * @return string|null Resolved content, or null to use `post_content`.
1313 - */
1314 - private function builder_content(\WP_Post $post): ?string {
1315 - if ([] === self::builder_meta_keys()) {
1316 - return null;
1317 - }
1318 -
1319 - if ('' !== trim((string) $post->post_content)
1320 - && !Builder_Content::bricks_supersedes_post_content((int) $post->ID)
1321 - ) {
1322 - return null;
1323 - }
1324 -
1325 - try {
1326 - return Builder_Content::resolve($post);
1327 - } catch (\Throwable $e) {
1328 - return null;
1329 - }
1330 - }
1331 -
1332 - /**
1333 1289 * Shared shape for the content-sampled GEO checks: count how many posts in
1334 1290 * the sample satisfy a predicate and grade it on the coverage thresholds
1335 1291 * the Content category already uses.
1336 1292 *
@@ -1351,58 +1307,27 @@
1351 1307 string $fail_text,
1352 1308 string $how_to_fix,
1353 1309 string $empty_text
1354 1310 ): array {
1355 - // A page whose body is only a shortcode or a commerce block (Checkout,
1356 - // My account, Shop) leaves no extractable text, so every prose-shaped
1357 - // question here answers "no" for it and would drag the category down
1358 - // over content nobody wants quoted in an AI answer. Skipping them is
1359 - // deliberate: this grades the pages that could be cited. Builder pages
1360 - // are not in this group: get_content_sample() reads their builder
1361 - // storage, so they have text and are graded (#892).
1362 - $sampled = $this->get_content_sample();
1363 - $sample = [];
1364 - $textless = [];
1365 - foreach ($sampled as $row) {
1311 + // A page whose body is a shortcode or a builder layout leaves no
1312 + // extractable text, so every prose-shaped question here answers "no"
1313 + // for it — Cart, Checkout, My account and Shop would drag the category
1314 + // down over content nobody wants quoted in an AI answer. Skipping them
1315 + // is deliberate: this grades the pages that could be cited.
1316 + $sample = [];
1317 + foreach ($this->get_content_sample() as $row) {
1366 1318 if ('' !== $row['text']) {
1367 1319 $sample[] = $row;
1368 - } else {
1369 - $textless[] = $row['id'];
1370 1320 }
1371 1321 }
1372 1322
1373 1323 $total = count($sample);
1374 1324
1375 - // Nothing published: nothing to report.
1376 - if ([] === $sampled) {
1325 + if (0 === $total) {
1377 1326 return [
1378 1327 'label' => $label,
1379 1328 'status' => self::PASSED,
1380 1329 'message' => $empty_text,
1381 - ];
1382 - }
1383 -
1384 - // Pages exist, but none yielded text. That is a sample this check
1385 - // could not read, not an empty site, and it used to pass with "No
1386 - // published content to check yet", awarding the weight for content
1387 - // nobody examined (#892). Say so instead.
1388 - if (0 === $total) {
1389 - return [
1390 - 'label' => $label,
1391 - 'status' => self::WARNING,
1392 - 'message' => sprintf(
1393 - /* translators: %d: number of sampled pages. */
1394 - _n(
1395 - 'ThinkRank found no readable text on the %d page it sampled, so this could not be checked.',
1396 - 'ThinkRank found no readable text on any of the %d pages it sampled, so this could not be checked.',
1397 - count($textless),
1398 - 'thinkrank'
1399 - ),
1400 - count($textless)
1401 - ),
1402 - 'how_to_fix' => __('Pages built only from shortcodes, or with a page builder ThinkRank does not support, have no text it can read. Publish pages with written content, or check that your page builder is supported.', 'thinkrank'),
1403 - 'value' => sprintf('0/%d', count($textless)),
1404 - 'affected_posts' => $this->affected_posts($textless),
1405 1330 ];
1406 1331 }
1407 1332
1408 1333 $matching = 0;