CloudScale SEO AI Optimizer

Changelog

4.20.74

  • feat: Add “Generate Missing Titles” button — batch-generates SEO title tags for posts with no _cs_seo_title set
  • feat: Add “Have Title Tag” counter card in the summary row alongside “Have Description”

4.20.67

  • Add: Broken Link Checker — Date Created column in results table; Post, Date Created, and Status headers are now sortable
  • Fix: Broken Link Checker — sites returning 503 to server-side requests (Cloudflare JS-challenge) now treated as alive, eliminating false positives
  • Add: Redirects — Created column moved next to Last hit and made sortable; Hits, Last hit, and Created all support click-to-sort
  • Fix: Broken Link Checker — sites returning 401 to server-side requests (Reuters, WatchMojo) now treated as alive, eliminating false positives

4.20.27

  • Security: Broken Link Checker SSRF guard — blc_is_ssrf_blocked() now rejects URLs that resolve to loopback, link-local, or private IP ranges before making the wp_remote_head() call
  • Fix: Title Optimiser stale detection — added 60-second grace period so applying a title never immediately flags the post as “Edited since analysis” due to wp_update_post() timing
  • Fix: Title Optimiser applied-post hint text corrected from “re-analyse to compare originals” to “Title was changed to suggested title”
  • Docs: Added Readability, Broken Link Checker, and Image SEO Audit feature sections to readme description
  • Docs: Corrected “What This Plugin Does Not Do” — removed incorrect “no readability scoring” claim; added BLC to External Services section

4.20.2

  • Add: Title Optimiser — new 🎯 Title Optimiser tab; AI suggests keyword-rich replacement titles for all published posts; shows before/after SEO score and identified keywords; apply individually or in bulk; applying a title auto-creates a 301 redirect from the old URL
  • Change: AI Summary Box now uses SEO-first prompts — primary keyword front-loaded in every field, secondary keywords woven in naturally, written for search intent; existing summaries unchanged until regenerated

4.19.142

  • Add: Readability scoring — pure-PHP analysis of sentence length, heading density, and passive-voice rate; no AI call required; scores 0–100 with Easy / Moderate / Hard labels
  • Add: Readability badge in post metabox — colour-coded score with sub-metrics (avg words/sentence, words per heading, passive voice %); Score button for on-demand rescoring; auto-refreshes after meta description generation
  • Add: Sortable Readability column in Meta Writer post list — badge updates live during pipeline run
  • Add: Auto-pipeline and save_post hook both trigger readability scoring to keep scores fresh
  • Add: Migrate Categories panel in the Categories tab — lists all categories sorted by post count (fewest first) and lets you migrate posts category-by-category
  • Add: Single-category posts require a swap target; multi-category posts can be removed or swapped per row
  • Add: Apply per-row or Apply All to batch-migrate every pending post in one click
  • Add: Delete Category button appears automatically once a category is empty — available in both the category list (for already-empty categories) and in the migration view once all posts are migrated; server-side guard prevents deletion if posts still exist
  • Fix: Settings save safety net — new option keys no longer silently drop on save

4.19.126

  • Add: Target audience and Writing tone fields in Site Identity — injected into every AI request; largest quality improvement available without editing the system prompt
  • Add: Prominent callout banner above new fields nudging users to fill them in before generating
  • Improve: Default AI system prompt rewritten to actively use site context for niche and voice matching
  • Improve: Site context header in all AI call sites updated from passive label to active instruction
  • Improve: Help documentation — Auto Pipeline and Redirects now have screenshots; new fields documented; Explain buttons tip added
  • Fix: Right-side padding too tight — added padding-right to .ab-pane so card shadow is not clipped

4.19.99

  • Add: Initial implementation of Target audience and Writing tone site context fields

4.19.98

  • Fix: PCP critical — raw script tag in redirects admin moved to wp_add_inline_script to comply with WordPress.org standards
  • Fix: delete-redirect and clear-all-redirects fetch calls now have catch handlers for network errors
  • Fix: PCP NonceVerification.Missing — all AJAX handlers now call check_ajax_referer() directly in scope (was delegated via helper wrapper)
  • Fix: esc_attr() added to colour ternary expression in batch history table
  • Fix: removed stale “No redirect management” line from readme

4.19.90

  • Fix: Settings save broken for all checkbox fields — added hidden fallback inputs so unchecked checkboxes correctly save 0
  • Fix: Redirects zone-header white-on-white — added teal background colour to redirects card header
  • Fix: Manual redirect form and stored redirects table were rendering outside the card container
  • Fix: Save button left padding corrected across all admin cards
  • Add: Playwright settings-save tests covering all panels

4.19.89

  • Fix: Redirects zone-header white-on-white — added background colour to redirects card header
  • Fix: Add Manual Redirect and Stored Redirects sections moved inside the card container
  • Fix: Save button left padding corrected across all admin cards

4.19.88

  • Change: Sitemap & Robots tab renamed to Sitemap, Robots & Redirects
  • Change: Redirects section moved to Sitemap, Robots & Redirects tab

4.19.87

  • Change: Redirects section moved to bottom of Optimise SEO tab with zone-card styling and Explain button

4.19.86

  • Fix: Manual redirect row was inserting into wrong table element — fixed tbody selector

4.19.85

  • Add: Automatic Redirects — 301 redirect automatically captured and served when a published post or page slug is renamed
  • Add: Manual redirect form — add custom path→URL redirects for any resource including image paths and arbitrary old paths
  • Add: Hit counter and last-hit timestamp on every redirect entry, displayed inline next to the old path
  • Add: Clickable old-path links in the redirect table for one-click testing
  • Fix: Save Changes on the Redirects tab was silently ignored — enable_redirects added to sanitize_opts known-fields guard
  • Fix: 301 redirects not firing — moved hook to template_redirect priority 0 to run before cs_pcr_maybe_custom_404 which exits at priority 1
  • Fix: enable_redirects default changed to enabled (1) for fresh installs

4.19.72

  • Update: version bump

4.19.50

  • Add: “Automatic” model option — new default that always resolves to the current recommended model per provider (claude-sonnet-4-6 / gemini-2.0-flash); existing users with a pinned model are unaffected

4.19.11

  • Add: sitemap.txt endpoint — plain-text sitemap (one URL per line) served at /sitemap.txt alongside the existing XML sitemap

4.19.4

  • Fix: debug_log() method added to main class — font optimizer and OG letterbox AJAX handlers threw fatal errors in production; now delegates to Utils::log() for a single logging code path
  • Fix: orphaned duplicate DocBlocks removed from trait-ai-meta-writer.php
  • Fix: missing DocBlocks added across main class, trait-ai-meta-writer.php, and trait-settings-assets.php
  • Fix: @package tag added to trait-settings-assets.php file DocBlock

4.19.3

  • PCP: moved phpcs:ignore for post__not_in to same line as violation in trait-auto-pipeline.php, trait-ai-meta-writer.php, and trait-sitemap.php — inline suppression is required for PHPCS to recognise it

4.19.2

  • PCP fix: echoed tag in auto-run metabox replaced with wp_add_inline_script()
  • Fix: button label ‘u21ba’ in single-quoted PHP string replaced with literal UTF-8 ↺
  • Fix: inline conditional colour echo in metabox log wrapped with esc_attr()
  • Fix: orphaned DocBlock on on_post_delete restored; duplicate consecutive DocBlock removed
  • Fix: render_rc_block() DocBlock missing @since and @return — added
  • CHANGELOG.md synced — all versions from 4.14.6 through 4.19.1 back-filled

4.19.1

  • Added Explain buttons to Auto Pipeline, Mixed Content Fix, and Render & Minification cards
  • Updated Auto Pipeline description to reflect non-blocking HTTP approach (not cron)

4.19.0

  • Auto pipeline: all AI steps (meta description, focus keyword, internal links, AI summary) now require a minimum of 50 words of post content before running — prevents meaningless output on stub/test posts

4.18.9

  • AI auto pipeline now uses non-blocking wp_remote_post() instead of WP-Cron — fires immediately on publish with no cron dependency
  • HMAC token (120s TTL transient) authenticates the async pipeline request
  • Removed cs_seo_auto_run_pipeline cron hook; cleanup pipeline retains cron

4.18.8

  • Related Articles now run synchronously on publish via transition_post_status — no cron dependency
  • AI pipeline now calls spawn_cron() on shutdown after scheduling to force immediate cron execution

4.18.7

  • Reload button moved left of Show/Hide Details button and uses visibility:hidden so the layout never shifts when it appears

4.18.6

  • Auto Pipeline card moved to AI Tools tab (top of panel) with its own Save button
  • Added “Re-run on update” toggle — re-runs full pipeline 5 seconds after any published post is saved
  • Auto Pipeline settings removed from Scheduled Batch card

4.18.5

  • Removed duplicate Reload buttons from inside AI Meta Writer, ALT Text, and Summary Box toolbars — Reload only appears in the card header

4.18.4

  • Fix: altLoad() and sumLoad() were crashing on removed button elements, preventing auto-load on card expand

4.18.3

  • Removed all “Hide Posts” buttons from AI Meta Writer, ALT Text, Summary Box, Category Fixer, and Category Health cards

4.18.2

  • Removed “Load Posts” and “Scan Posts” CTA buttons from AI Meta Writer, ALT Text, and Summary Box cards
  • Cards now auto-load their posts on first “Show Details” expand via abToggleCard

4.18.1

  • Auto Pipeline: added “Auto Run on publish” toggle in Batch/Schedule settings — pipeline is disabled by default until explicitly enabled
  • Auto Pipeline: on_post_publish and on_post_delete now check the toggle before scheduling cron events

4.18.0

  • Auto Pipeline: new trait-auto-pipeline.php — all AI operations run automatically via WP-Cron when a post is published
  • Auto Pipeline: steps — meta description + SEO score, focus keyword, ALT text for attached images, internal links (AI-suggested, block-safe injection), AI summary box, Related Articles generation
  • Auto Pipeline: Gutenberg-safe internal link injection using parse_blocks / serialize_blocks on core/paragraph and core/heading blocks; classic editor fallback via str_replace
  • Auto Pipeline: delete cleanup pipeline removes all cs post meta and run log transients for permanently deleted posts
  • Auto Pipeline: “Re-run AI Automation” button in post edit screen metabox with live log display
  • Auto Pipeline: CSEO_ASYNC_ENABLED constant for synchronous debugging mode
  • Dashboard widget: “posts need AI auto run” and “pipeline jobs queued” metrics added
  • New meta keys: _cs_seo_auto_run_complete, _cs_seo_focus_keyword

4.17.6

  • Related Articles Post Status: “All Posts” now uses a direct DB query instead of WP_Query, fixing the environment where WP_Query with no meta restriction returned 0 results (new posts were invisible)
  • Related Articles Post Status: “All Posts” is now the default filter so newly published articles appear immediately on table load

4.17.5

  • File-level DocBlocks (@package, @since) added to all 20 remaining trait files
  • Settings page: all form field labels and RC table labels wrapped in esc_html_e()
  • ajax_rc_sync_counts @since history corrected to reflect 4.16.5, 4.17.1, 4.17.2 changes

4.17.4

  • PCP: removed load_plugin_textdomain() call — discouraged since WP 4.6, auto-loaded by WordPress.org
  • PCP: added missing translators comment to printf in metabox
  • PCP: removed set_time_limit() call in ajax_rc_sync_counts
  • PCP: prefixed global variables in uninstall.php ($cs_seo_options, $cs_seo_meta_keys, etc.)
  • PCP: added phpcs:ignore to Utils class declaration with explanation

4.17.3

  • Settings page now returns to the active tab after saving — active tab is saved to localStorage and restored on page reload

4.17.2

  • Fix: Generate & Sync now correctly decreases link counts for posts where _cs_rc_scores was deleted by earlier reset attempts — added a third code path that directly trims top/bottom arrays without requiring scores or re-running the pipeline
  • Fix: button label showed “&” literal after completion — changed to textContent with plain “&”

4.17.1

  • Merged “Generate Missing” and “Sync Counts” into one “Generate & Sync” button — single server-side pass that runs the full pipeline for posts with no scores and re-applies count settings for posts that already have scores

4.17.0

  • Related Articles Post Status table: post title links now open the live post URL (so related links are visible) instead of the editor

4.16.9

  • Fix: post title links in Related Articles Post Status table now open the post editor instead of the category editor (was using a relative URL that inherited the settings page context)

4.16.8

  • Fix: clicking Generate Missing when all posts are complete no longer leaves the table showing “No posts found.” — the table restores to its previous filter/page after the alert

4.16.7

  • Sync Counts now fills upward as well as trimming — re-applies the stored candidate scores to fill additional slots when the count setting is increased, so no full regeneration is needed

4.16.6

  • Fix: Related Articles settings (rc_top_count, rc_bottom_count, rc_enable) were silently discarded on save — the options sanitizer’s known-fields guard did not include any RC keys so every RC form submission was rejected as spurious

4.16.5

  • New: “Sync Counts” button in Related Articles Post Status — single server-side pass that trims all complete posts’ stored links to match current Top/Bottom count settings using a direct DB query, bypassing all WP_Query environment issues

4.16.4

  • Fix: Generate Missing now force-reloads with filter=pending before collecting IDs — previously it used the complete-post DOM rows and then filtered them all out, yielding 0 posts

4.16.3

  • Fix: rcRunOne final state fetch now uses rcCurrentFilter instead of hardcoded filter=all (which returns 0 in some environments), so row counts update live during a batch run
  • Fix: Reset All reloads with current filter rather than filter=all
  • Batch bar now shows post count at start so you can confirm the batch is running

4.16.2

  • Fix: Related Articles table autoload now uses filter=complete instead of filter=all (all-posts query returns 0 in some environments)
  • Fix: rcBatch auto-reloads the table with the target filter before collecting IDs if the DOM is empty, guaranteeing posts are found

4.16.1

  • Fix: rcBatch now reads post IDs from the visible DOM table rows instead of a pre-fetch API call; eliminates “No posts to process” caused by cs_rc_get_posts returning 0 for certain filter/query combinations

4.16.0

  • Fix: Refresh Stale now queries filter=’complete’ instead of filter=’all’ — semantically correct (re-runs previously completed posts) and resolves “No posts to process” caused by the all-posts query returning nothing in some environments

4.15.9

  • Refactor: rcBatch rewritten to use a page-1 probe for total count then process page-by-page, eliminating the pre-fetch bulk-collect approach that returned 0 posts in some environments

4.15.8

  • Fix: Refresh Stale and Retry Failed now actually regenerate posts — previously the step handler returned immediately for complete posts without running any steps; each post is now reset to pending before re-running

4.15.7

  • Fix: Related Articles batch (Refresh Stale, Generate Missing, Retry Failed) now fetches all pages before building the queue — previously only the first 50 posts were ever processed

4.15.6

  • AI Tools post table: ✏ Edit button on each row opens an inline textarea to manually enter or edit the meta description, with Save and Cancel

4.15.5

  • PCP medium fixes: load_textdomain moved from plugins_loaded to init
  • PHP version notice now uses i18n functions with translators comment
  • DocBlocks added to all methods in trait-options.php
  • File-level DocBlocks added to trait-schema.php and trait-ai-engine.php
  • dispatch_ai() and ajax_check() DocBlocks completed with @since, @param, @return
  • Created includes/class-cloudscale-seo-ai-optimizer-utils.php Utils class
  • Settings page: tab labels, zone headers, and all submit_button labels wrapped in i18n functions

4.15.4

  • PCP compliance: JSON-LD structured data now output via wp_print_inline_script_tag() instead of echoed strings — eliminates the only remaining critical PCP violation

4.15.3

  • Fix: PHP Warning “Undefined array key message” in batch scheduler log display — timeout and sum_ok entries have no message key

4.15.2

  • Scoring status bar now shows “(Post N of Total)” counter for both Calculate SEO Scores and Generate Missing phase 2

4.15.1

  • Fix: Generate Missing phase 2 scoring now does its own fresh post fetch instead of relying on phase 1 data; always logs phase 2 status

4.15.0

  • Generate Missing now runs a second phase that scores any posts still missing an SEO score after descriptions are done
  • Renamed “Score All” button to “Calculate SEO Scores”

4.14.9

  • AI Tools post table: Description, Title, and ALT columns are now sortable; all six data columns now have clickable sort headers

4.14.8

  • Fix: homepage SEO score no longer disappears on reload — static front page row now reads seo_score/seo_notes from post meta

4.14.7

  • AI Tools post table: added Date column and sortable headers for Post (title), Date, and SEO Score

4.14.6

  • Swapped Categories and Scheduled Batch tab order in settings page

4.13.2

  • Category Drift: cdLoad() now shows elapsed time counter and Stop button during analysis
  • Category Drift: cdAnalyseRemaining() now shows post count in loading label and Stop button
  • Both use AbortController so Stop cancels the in-flight fetch immediately

4.13.1

  • Fixed PHP operator-precedence bug in defer_font_css() noscript href — preg_match result was being concatenated before the ternary, making href always empty
  • Added i18n (esc_html__/esc_html_e) to user-visible strings in admin notice, metabox labels/buttons, and frontend summary box
  • Extracted admin_page_css(), llms_preview_js(), sitemap_preview_js() to trait-settings-assets.php (reduces trait-settings-page.php by ~300 lines)

4.13.0

  • Created CHANGELOG.md in Keep-a-Changelog format
  • Dashboard widget title now uses wp_kses_post() with esc_html() for the version span
  • Added @since, @param, @return DocBlocks to all public methods across all 23 trait files

4.0.0 – 4.12.9

  • For the complete version history of all earlier releases see CHANGELOG.md in the plugin directory.

Plugin Website
Visit website

Author
andrewjbaker
Version:
4.20.74
Last Updated
April 20, 2026
Requires
WordPress 6.0
Tested Up To
WordPress 6.9.4
Requires PHP
8.0

Share Post

Join our newsletter.

Get insights into what’s happening at ChangelogWP right in your inbox. We don’t believe in spam.