{"id":258332,"date":"2025-12-19T08:38:59","date_gmt":"2025-12-19T08:38:59","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/draftseo-ai\/"},"modified":"2026-06-17T16:31:36","modified_gmt":"2026-06-17T16:31:36","slug":"draftseo-ai","status":"publish","type":"plugin","link":"https:\/\/ne.wordpress.org\/plugins\/draftseo-ai\/","author":23098221,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"1.3.1","stable_tag":"1.3.1","tested":"7.0","requires":"6.2","requires_php":"7.4","requires_plugins":null,"header_name":"DraftSEO.ai","header_author":"DraftSEO.ai","header_description":"Publish AI-generated blogs from DraftSEO.AI platform directly to WordPress. Transfers images from Nebius CDN to WordPress media library while maintaining SEO optimization.","assets_banners_color":"fcfeff","last_updated":"2026-06-17 16:31:36","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"https:\/\/draftseo.ai\/wp-plugin","header_author_uri":"https:\/\/draftseo.ai","rating":0,"author_block_rating":0,"active_installs":60,"downloads":2041,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"0.1.0":{"tag":"0.1.0","author":"klimentp","date":"2025-12-19 08:35:58"},"0.2.0":{"tag":"0.2.0","author":"klimentp","date":"2025-12-19 09:19:45"},"1.0.0":{"tag":"1.0.0","author":"klimentp","date":"2026-02-14 13:46:55"},"1.0.1":{"tag":"1.0.1","author":"klimentp","date":"2026-02-14 18:08:29"},"1.0.2":{"tag":"1.0.2","author":"klimentp","date":"2026-02-14 21:59:09"},"1.0.3":{"tag":"1.0.3","author":"klimentp","date":"2026-02-14 22:34:15"},"1.0.4":{"tag":"1.0.4","author":"klimentp","date":"2026-02-14 23:26:33"},"1.0.5":{"tag":"1.0.5","author":"klimentp","date":"2026-02-14 23:47:51"},"1.1.0":{"tag":"1.1.0","author":"klimentp","date":"2026-03-10 11:51:33"},"1.1.1":{"tag":"1.1.1","author":"klimentp","date":"2026-03-10 11:51:33"},"1.1.2":{"tag":"1.1.2","author":"klimentp","date":"2026-03-25 19:54:36"},"1.1.3":{"tag":"1.1.3","author":"klimentp","date":"2026-03-29 12:38:18"},"1.1.4":{"tag":"1.1.4","author":"klimentp","date":"2026-04-02 18:24:30"},"1.1.5":{"tag":"1.1.5","author":"klimentp","date":"2026-04-03 09:41:15"},"1.1.6":{"tag":"1.1.6","author":"klimentp","date":"2026-04-03 10:06:26"},"1.2.0":{"tag":"1.2.0","author":"klimentp","date":"2026-04-04 20:29:07"},"1.2.1":{"tag":"1.2.1","author":"klimentp","date":"2026-04-05 06:27:25"},"1.2.2":{"tag":"1.2.2","author":"klimentp","date":"2026-04-05 07:42:01"},"1.2.3":{"tag":"1.2.3","author":"klimentp","date":"2026-04-05 10:21:19"},"1.2.4":{"tag":"1.2.4","author":"klimentp","date":"2026-04-05 11:21:36"},"1.2.5":{"tag":"1.2.5","author":"klimentp","date":"2026-05-27 14:31:59"},"1.2.6":{"tag":"1.2.6","author":"klimentp","date":"2026-06-12 14:01:41"},"1.2.7":{"tag":"1.2.7","author":"klimentp","date":"2026-06-15 10:15:23"},"1.3.0":{"tag":"1.3.0","author":"klimentp","date":"2026-06-15 19:45:49"},"1.3.1":{"tag":"1.3.1","author":"klimentp","date":"2026-06-17 16:31:36"}},"upgrade_notice":{"1.3.1":"<p>Refreshed light-themed admin design and brand-matched menu icon, faster re-publishing, more efficient syncing, and gentler default image importing.<\/p>","1.3.0":"<p>Security and reliability update: disconnecting now fully revokes access, the connection flow is locked to the official DraftSEO address, publish success is reported accurately, and background image jobs are crash-hardened. Recommended for all users.<\/p>","1.2.7":"<p>Confirmed compatible with WordPress 7.0, removes an early-translation debug notice, and adds automatic image alt text from embedded photo metadata. Recommended for all users.<\/p>","1.2.6":"<p>Fixes intermittent HTTP 500 errors on publish caused by third-party plugins on your WordPress site, a featured image crash on legacy imports, and a 30-second hang when publishing blogs with no images. Recommended for all users.<\/p>","1.2.5":"<p>Hotfix for WordPress auto-publish failing with HTTP 500 on sites where any browser cookie has a numeric name. Recommended for all users.<\/p>","1.2.4":"<p>Fixes stuck &quot;images importing\u2026&quot; jobs, adds a Logs tab in the plugin settings page with CSV export, and routes all image import errors to a searchable DB log. Recommended for all users.<\/p>","1.2.2":"<p>Fixes 5 bugs (duplicate posts, SEO title not written, image captions dropped, repair scan skipped after manual update, double-scheduling guard) and adds SEOPress support, VideoObject schema for YouTube embeds, and automatic sync reconciliation. Recommended for all users.<\/p>","1.2.1":"<p>Internal code reorganisation only \u2014 no new features or behaviour changes.<\/p>","1.2.0":"<p>Significantly improves image import reliability, automatically repairs all previously affected posts in the background after updating, and adds continuous health monitoring that catches any future stuck imports within 24 hours and fixes them automatically. Recommended for all users.<\/p>","1.1.6":"<p>Republishing a post is now faster \u2014 images already in your Media Library are not re-downloaded. Recommended for all users who republish posts regularly.<\/p>","1.1.5":"<p>Fixes the &quot;Republish&quot; button being blocked when images are still uploading in the background. All publish paths now report completion reliably. Recommended for all users.<\/p>","1.1.4":"<p>Cosmetic improvements and better connectivity feedback. The settings page now clearly shows when your connection to DraftSEO.ai is out of sync, with guided steps to fix it.<\/p>","1.1.3":"<p>Reliability improvements. Fixes images not appearing on low-traffic sites, background tasks not stopping cleanly on deactivation, and translations on non-English installs. Recommended for all users.<\/p>","1.1.2":"<p>Security update. Fixes API authentication failures on certain WordPress configurations that prevented DraftSEO.ai from syncing disconnect and deactivation events with your site.<\/p>","1.1.0":"<p>When you republish a post with a new AI-generated image, the previous image is automatically removed from your WordPress Media Library. Saves storage space and keeps your media folder clean.<\/p>","1.0.5":"<p>YouTube videos now display as embedded players on published WordPress posts.<\/p>","1.0.4":"<p>Fixes headings appearing as plain text after images in published posts. Also removes unwanted image captions that were displaying as visible text below every image.<\/p>","1.0.3":"<p>Fixes YouTube videos being stripped when publishing to WordPress. Also fixes headings rendering as plain text and malformed citation links.<\/p>","1.0.2":"<p>Hotfix: Fixes in-text citations, references list, external links, and adds FAQ structured data (JSON-LD) for SEO rich results.<\/p>","1.0.1":"<p>Hotfix: Fixes YouTube video embeds and data tables not rendering correctly in published posts.<\/p>","1.0.0":"<p>Major release with 30+ improvements to security, performance, and API architecture. See changelog for full details.<\/p>","0.2.0":"<p>Initial beta release of DraftSEO.ai plugin.<\/p>"},"ratings":[],"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3478994,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3478994,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3478994,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-772x250.png":{"filename":"banner-772x250.png","revision":3478994,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{},"all_blocks":[],"tagged_versions":["0.1.0","0.2.0","1.0.0","1.0.1","1.0.2","1.0.3","1.0.4","1.0.5","1.1.0","1.1.1","1.1.2","1.1.3","1.1.4","1.1.5","1.1.6","1.2.0","1.2.1","1.2.2","1.2.3","1.2.4","1.2.5","1.2.6","1.2.7","1.3.0","1.3.1"],"block_files":[],"assets_screenshots":{"screenshot-1.jpg":{"filename":"screenshot-1.jpg","revision":3478994,"resolution":"1","location":"assets","locale":"","width":1264,"height":842}},"screenshots":{"1":"The DraftSEO.ai connection screen in the WordPress admin."}},"plugin_section":[],"plugin_tags":[2353,323,529,7143,186],"plugin_category":[55],"plugin_contributors":[252493],"plugin_business_model":[],"class_list":["post-258332","plugin","type-plugin","status-publish","hentry","plugin_tags-ai","plugin_tags-blog","plugin_tags-content","plugin_tags-publishing","plugin_tags-seo","plugin_category-seo-and-marketing","plugin_contributors-klimentp","plugin_committers-klimentp"],"banners":{"banner":"https:\/\/ps.w.org\/draftseo-ai\/assets\/banner-772x250.png?rev=3478994","banner_2x":"https:\/\/ps.w.org\/draftseo-ai\/assets\/banner-1544x500.png?rev=3478994","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/draftseo-ai\/assets\/icon-128x128.png?rev=3478994","icon_2x":"https:\/\/ps.w.org\/draftseo-ai\/assets\/icon-256x256.png?rev=3478994","generated":false},"screenshots":[{"src":"https:\/\/ps.w.org\/draftseo-ai\/assets\/screenshot-1.jpg?rev=3478994","caption":"The DraftSEO.ai connection screen in the WordPress admin."}],"raw_content":"<!--section=description-->\n<p>Publish complete, AI-generated blog posts from DraftSEO.ai to WordPress in one click \u2014 or fully automatically. Images land in your own Media Library, SEO metadata is written to your SEO plugin, and categories and tags are applied. No copy-pasting, no manual uploads.<\/p>\n\n<h4>Key Features<\/h4>\n\n<ul>\n<li><strong>One-click or automatic publishing<\/strong> \u2014 Send finished blogs to WordPress as a draft, a scheduled post, or a live post. Turn on Auto-publish to have new blogs published for you.<\/li>\n<li><strong>Images in your own Media Library<\/strong> \u2014 Every image (with its alt text and caption) is downloaded to your Media Library in the background, so posts go live instantly and you keep full ownership \u2014 no external hotlinking.<\/li>\n<li><strong>Works with your SEO plugin<\/strong> \u2014 The SEO title, meta description, focus keyword, and canonical URL are written automatically to Yoast SEO, Rank Math, All in One SEO, or SEOPress (focus keyword where the plugin supports one).<\/li>\n<li><strong>Rich-result structured data<\/strong> \u2014 Adds VideoObject schema for embedded YouTube videos and FAQ schema, so your posts are eligible for video and FAQ rich results in Google.<\/li>\n<li><strong>Categories &amp; tags<\/strong> \u2014 Syncs your WordPress categories and auto-creates tags from each blog's keywords.<\/li>\n<li><strong>Clean, portable HTML<\/strong> \u2014 Proper heading structure, responsive tables, clickable in-text citations with a linked references list, and <code>rel=\"noopener noreferrer\"<\/code> on external links.<\/li>\n<li><strong>Built-in activity log<\/strong> \u2014 A Logs tab records every publish and image import. Filter by type, search, export to CSV, or clear it out.<\/li>\n<li><strong>Self-healing images<\/strong> \u2014 Images import in parallel in the background, and a daily check automatically re-imports anything an interrupted job missed.<\/li>\n<li><strong>Secure by design<\/strong> \u2014 Your connection credentials are encrypted, and disconnecting or removing the plugin fully revokes access, so no stale connections are left behind.<\/li>\n<\/ul>\n\n<h4>How It Works<\/h4>\n\n<ol>\n<li>Install and activate the plugin.<\/li>\n<li>In another browser tab, log in to your DraftSEO.ai account.<\/li>\n<li>Go to <strong>DraftSEO \u2192 Settings<\/strong> and click <strong>Connect with DraftSEO.ai<\/strong> \u2014 the connection completes automatically over OAuth (no API key to copy).<\/li>\n<li>Generate a blog in DraftSEO.ai and click <strong>Publish to WordPress<\/strong>, or switch on Auto-publish.<\/li>\n<\/ol>\n\n<p><strong>Requires an active DraftSEO.ai account.<\/strong> Visit <a href=\"https:\/\/draftseo.ai\">draftseo.ai<\/a> to sign up.<\/p>\n\n<h3>External Services<\/h3>\n\n<p>This plugin connects to DraftSEO.ai to generate and publish AI-written blog content. An active DraftSEO.ai account is required.<\/p>\n\n<p>Data sent to DraftSEO.ai:\n- Your website URL and a connection token (set up automatically when you connect)\n- Publishing requests for the blogs you choose to publish\n- A notice when you disconnect or remove the plugin, so your account stays in sync<\/p>\n\n<p>Data received from DraftSEO.ai:\n- Generated blog content\n- Images and their metadata<\/p>\n\n<p>Service provider: DraftSEO.ai \u2014 <a href=\"https:\/\/draftseo.ai\">draftseo.ai<\/a>\n<a href=\"https:\/\/draftseo.ai\/terms\">Terms of Service<\/a> \u00b7 <a href=\"https:\/\/draftseo.ai\/privacy\">Privacy Policy<\/a><\/p>\n\n<!--section=installation-->\n<h4>From your WordPress dashboard<\/h4>\n\n<ol>\n<li>Go to <strong>Plugins \u2192 Add New<\/strong> and search for \"DraftSEO.ai\".<\/li>\n<li>Click <strong>Install Now<\/strong>, then <strong>Activate<\/strong>.<\/li>\n<\/ol>\n\n<h4>Manual upload<\/h4>\n\n<ol>\n<li>Download the plugin ZIP.<\/li>\n<li>Go to <strong>Plugins \u2192 Add New \u2192 Upload Plugin<\/strong>, choose the ZIP, and click <strong>Install Now<\/strong>.<\/li>\n<li>Click <strong>Activate<\/strong>.<\/li>\n<\/ol>\n\n<h4>Connect<\/h4>\n\n<p>In another browser tab, log in to your DraftSEO.ai account. Then go to <strong>DraftSEO \u2192 Settings<\/strong> and click <strong>Connect with DraftSEO.ai<\/strong>. The connection completes automatically \u2014 there's no API key to copy.<\/p>\n\n<!--section=faq-->\n<dl>\n<dt id=\"do%20i%20need%20a%20draftseo.ai%20account%3F\"><h3>Do I need a DraftSEO.ai account?<\/h3><\/dt>\n<dd><p>Yes \u2014 the plugin publishes content from your DraftSEO.ai account, so you'll need an active one. Sign up at <a href=\"https:\/\/draftseo.ai\">draftseo.ai<\/a>.<\/p><\/dd>\n<dt id=\"how%20do%20i%20connect%20my%20site%3F\"><h3>How do I connect my site?<\/h3><\/dt>\n<dd><p>Log in to your DraftSEO.ai account in one tab, then click \"Connect with DraftSEO.ai\" on the plugin's settings page. The connection is made automatically over OAuth \u2014 there's no API key to copy or paste.<\/p><\/dd>\n<dt id=\"where%20do%20my%20images%20go%3F\"><h3>Where do my images go?<\/h3><\/dt>\n<dd><p>Every image is downloaded to your own WordPress Media Library and served from your site, so you keep full ownership with no ongoing dependency on DraftSEO.ai. There's no limit on the number of images per post.<\/p><\/dd>\n<dt id=\"what%20if%20an%20image%20fails%20to%20import%3F\"><h3>What if an image fails to import?<\/h3><\/dt>\n<dd><p>Publishing never waits on images \u2014 the post goes live immediately and images import in the background. If a download is interrupted, a daily background check re-imports the missing images automatically, so there's nothing for you to do.<\/p><\/dd>\n<dt id=\"which%20seo%20plugins%20are%20supported%3F\"><h3>Which SEO plugins are supported?<\/h3><\/dt>\n<dd><p>Yoast SEO, Rank Math, All in One SEO, and SEOPress. The SEO title, meta description, and canonical URL are written to whichever you have active (plus the focus keyword on plugins that support one).<\/p><\/dd>\n<dt id=\"can%20i%20publish%20to%20more%20than%20one%20site%3F\"><h3>Can I publish to more than one site?<\/h3><\/dt>\n<dd><p>Yes. Connect as many WordPress sites as you like to your DraftSEO.ai account \u2014 each just needs the plugin installed and connected.<\/p><\/dd>\n<dt id=\"does%20it%20work%20with%20custom%20post%20types%3F\"><h3>Does it work with custom post types?<\/h3><\/dt>\n<dd><p>Not yet \u2014 the plugin publishes to standard WordPress posts and pages.<\/p><\/dd>\n<dt id=\"where%20can%20i%20get%20help%3F\"><h3>Where can I get help?<\/h3><\/dt>\n<dd><p>Visit <a href=\"https:\/\/draftseo.ai\/contact\">draftseo.ai\/contact<\/a>.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>1.3.1<\/h4>\n\n<p>Refreshed light-themed admin design, faster re-publishing, more efficient syncing, and gentler default image importing.<\/p>\n\n<ul>\n<li>Improved: Re-publishing a post when only its SEO details changed is now faster \u2014 unchanged content and images are no longer reprocessed.<\/li>\n<li>Improved: Syncing large sites with DraftSEO.ai transfers less data.<\/li>\n<li>Improved: More reliable image handling in post content, and oversized requests now return a clear message instead of failing silently.<\/li>\n<li>Improved: Image importing uses gentler, safer defaults so it runs smoothly even on limited shared hosting, and activity logs are now kept for 60 days.<\/li>\n<li>Improved: The settings screen now uses a clean, light theme on every site for a consistent look, instead of following the operating system's dark appearance.<\/li>\n<li>Improved: Modernised the settings screen \u2014 matched, rounded Connect\/Disconnect buttons with smooth hover and keyboard-focus states, an underline tab indicator, a subtle DraftSEO.ai brand accent on the card, and a tidier single-column layout (with reduced-motion support).<\/li>\n<li>Improved: The sidebar menu icon now matches the DraftSEO.ai brand mark.<\/li>\n<li>Improved: Clearer, less repetitive wording on the connection screen, and consistent \"DraftSEO.ai\" branding throughout.<\/li>\n<\/ul>\n\n<h4>1.3.0<\/h4>\n\n<p>Security and reliability release: disconnecting now fully revokes access, salt rotations show a clear \"reconnect\" message, the connection flow is locked to the official DraftSEO address, publishing reports real success or failure, and the admin screens have a refreshed design.<\/p>\n\n<ul>\n<li>Security: Disconnecting your site (from either DraftSEO or the plugin's Disconnect button) now fully revokes the stored connection key. Previously the key the plugin actually used for authentication was left in place, so the site could still be published to after it showed as disconnected.<\/li>\n<li>Security: The \"Connect with DraftSEO.ai\" flow now only accepts the official DraftSEO address, so a tampered connection link can no longer point your site's connection at another server.<\/li>\n<li>Security: Image and callback URLs are now validated to prevent server-side request forgery, and the completion callback can only be sent to the DraftSEO platform.<\/li>\n<li>Improved: If your site's WordPress security keys (salts) are rotated \u2014 by a security plugin, a host migration, or cloning to staging \u2014 the plugin now detects that its saved key can no longer be read and shows a clear \"please reconnect\" message instead of a generic \"invalid key\" error. Your settings are kept so you know exactly what happened.<\/li>\n<li>Fixed: Publishing now reports a real failure if WordPress refuses to create the post, instead of occasionally reporting success for a post that was never created.<\/li>\n<li>Fixed: Sync now also recognises articles published as Pages or products, so it no longer republishes them as duplicates.<\/li>\n<li>Fixed: Background image, repair, and health jobs are now crash-hardened \u2014 a single bad image URL can no longer silently kill the job and leave \"images importing\u2026\" stuck forever.<\/li>\n<li>Improved: Faster sync on large sites (fewer database round-trips), tidier post URLs (native WordPress slugs), and accurate author names in the activity log.<\/li>\n<li>New: The plugin now shows an \"update available\" note in its settings when a newer version is recommended.<\/li>\n<li>New: Refreshed admin design that follows your WordPress admin colour scheme, with a clearer connection status card and a modernised Logs table.<\/li>\n<\/ul>\n\n<h4>1.2.7<\/h4>\n\n<p>WordPress 7.0 compatibility, plus automatic alt text from your images.<\/p>\n\n<ul>\n<li>Improved: Tested and confirmed compatible with WordPress 7.0 (still works on WordPress 6.2 and newer).<\/li>\n<li>Improved: Translations now load on WordPress's <code>init<\/code> hook, removing the \"translation loaded too early\" debug notice that could appear on WordPress 6.7 and newer.<\/li>\n<li>New: When a DraftSEO image has no alt text of its own, the plugin now reads alt text embedded in the image file (IPTC\/XMP metadata) on WordPress 7.0 and uses it automatically \u2014 better accessibility and SEO with no extra work.<\/li>\n<li>New: On WordPress 7.0, the plugin can record relevant WordPress core warnings that happen during its own operations in the Logs tab, even when debug mode is turned off \u2014 making support issues easier to diagnose.<\/li>\n<\/ul>\n\n<h4>1.2.6<\/h4>\n\n<p>Reliability fix: publishing no longer fails with HTTP 500 when another plugin on your WordPress site has a bug in its HTTP calls.<\/p>\n\n<ul>\n<li>Fixed: Publishing from DraftSEO could intermittently fail with HTTP 500 on sites where a third-party plugin (caching, SEO, analytics, etc.) made a malformed HTTP request during the WordPress <code>save_post<\/code> hook. The DraftSEO plugin now catches these exceptions and returns a clear error message instead of crashing the entire REST request. This was the leading cause of intermittent publish failures on affected sites.<\/li>\n<li>Fixed: On sites using the legacy image import path (no callback URL), the featured image import could crash with a PHP fatal error if the image URL resolved to an empty string. The plugin now skips the import safely and logs a warning instead of crashing.<\/li>\n<li>Fixed: Publishing a blog with no images could hold the WordPress REST connection open for up to 30 seconds while waiting for the DraftSEO completion callback. The callback is now sent as a non-blocking fire-and-forget request so publish completes immediately.<\/li>\n<\/ul>\n\n<h4>1.2.5<\/h4>\n\n<p>Hotfix: WordPress auto-publish no longer crashes with HTTP 500 on sites that have integer-keyed cookies in the browser.<\/p>\n\n<ul>\n<li>Fixed: On WordPress 6.2\u20136.6.x, any browser cookie with a numeric name (e.g. set by certain caching plugins or analytics tools) caused Action Scheduler's loopback dispatch to throw an uncaught <code>WpOrg\\Requests\\Exception\\InvalidArgument<\/code>, which propagated as a PHP fatal error and returned HTTP 500 to DraftSEO, failing the entire publish. The bundled <code>WP_Async_Request<\/code> no longer forwards <code>$_COOKIE<\/code> to the internal loopback ping \u2014 authentication for that request uses a nonce, not cookies, so the change is safe with no functional impact.<\/li>\n<\/ul>\n\n<h4>1.2.4<\/h4>\n\n<p>Fixes stuck \"images importing\u2026\" jobs, adds a Logs admin tab with CSV export and DB-backed structured logging, and improves error visibility across all image import paths.<\/p>\n\n<ul>\n<li>Fixed: Blog posts published before April 5 2025 could show \"images importing\u2026\" in the DraftSEO UI indefinitely if the original callback failed (e.g. the 24-hour HMAC window expired before Action Scheduler ran). Running Sync now automatically detects and resolves these stuck jobs when WordPress confirms the post exists.<\/li>\n<li>Fixed: The repair scan no longer silently discards its completion status. When it finishes importing all images for a post it now notifies DraftSEO via a new long-lived API-key endpoint, closing the loop on any syndication job whose HMAC callback URL had already expired.<\/li>\n<li>New: Posts now store the DraftSEO syndication job ID (draftseo_syndication_job_id) in post meta at publish time. This enables the repair scan to notify DraftSEO without the original (expiring) callback URL.<\/li>\n<li>New: Logs tab in the plugin settings page. Browse, filter by level\/type, search, export to CSV, copy to clipboard, or clear all entries. Logs are kept for 30 days and cleaned up automatically by Action Scheduler.<\/li>\n<li>New: Structured DB logger (wp_draftseo_logs table with level, type, message, post_id columns). All image import paths \u2014 direct, async, background, repair scan, health check, and callback delivery \u2014 now write structured log entries visible in the Logs tab in addition to WordPress debug.log.<\/li>\n<li>Improved: <code>process_images_background<\/code> (hybrid strategy, 6+ images) now logs per-URL download failures and a completion summary \u2014 previously completely silent.<\/li>\n<li>Improved: <code>import_images_direct<\/code>, <code>process_images_with_callback<\/code>, <code>import_from_temp<\/code>, <code>sequential_download_images<\/code>, <code>import_images_async<\/code>, and <code>fire_callback<\/code> now each emit structured log entries with post ID, URL, and error detail on failure.<\/li>\n<\/ul>\n\n<h4>1.2.3<\/h4>\n\n<p>Critical fix: background image health check and repair scan were silently never scheduled due to Action Scheduler initialisation timing.<\/p>\n\n<ul>\n<li>Fixed: The daily image health check was never registered and the self-healing repair scan never ran after plugin install. Both background jobs silently failed to schedule because they were called before Action Scheduler's data store was ready. Both are now hooked to the correct 'action_scheduler_init' event, which fires only when the data store is fully initialised and it is safe to call Action Scheduler APIs.<\/li>\n<\/ul>\n\n<h4>1.2.2<\/h4>\n\n<p>Bug fixes, new SEO plugin support, and automatic sync reconciliation.<\/p>\n\n<ul>\n<li>Fixed: Publishing the same blog twice \u2014 for example after a network timeout or a retry \u2014 no longer creates a duplicate WordPress post. The second request returns the existing post immediately.<\/li>\n<li>Fixed: The SEO title (the per-post SERP title override, separate from the post title) was never written to the active SEO plugin. When DraftSEO sends a <code>seoTitle<\/code>, it is now written to Yoast (<code>_yoast_wpseo_title<\/code>), Rank Math (<code>rank_math_title<\/code>), All in One SEO (<code>_aioseo_title<\/code>), and SEOPress (<code>_seopress_titles_title<\/code>).<\/li>\n<li>Fixed: Images imported with a <code>caption<\/code> field from DraftSEO now have their caption visible in the WordPress Media Library (Edit Media \u2192 Caption), in the block editor image block, and in default <code>[caption]<\/code> \/ <code>&lt;figcaption&gt;<\/code> output. Previously the caption was silently dropped.<\/li>\n<li>Fixed: The self-healing image repair scan was silently skipped when a user updated the plugin by deactivating and reactivating it \u2014 the most common manual update flow. The fix ensures the repair scan fires correctly after every update, not just when using WordPress's automatic update mechanism.<\/li>\n<li>Fixed: A logic error in the duplicate-job guard could allow the repair scan to be queued more than once simultaneously. The guard now correctly detects any pending repair job regardless of its internal batch number.<\/li>\n<li>New: SEOPress is now a fully supported SEO plugin. The meta description (<code>_seopress_titles_desc<\/code>), SEO title (<code>_seopress_titles_title<\/code>), and canonical URL (<code>_seopress_robots_canonical<\/code>) are written at publish time.<\/li>\n<li>New: Posts containing YouTube videos now have VideoObject structured data (JSON-LD) added to their page head automatically. This makes the videos eligible for video-rich results in Google Search.<\/li>\n<li>New: When you click Sync for a WordPress connection, DraftSEO now automatically restores the WordPress post link for any blog whose mapping was lost (for example after a database restore). Affected blogs immediately show the correct \"Published to WordPress\" card in their detail view.<\/li>\n<li>New: When you click Sync, DraftSEO also automatically recovers any published posts that exist on WordPress but are missing from your DraftSEO account \u2014 for example after a data restore or account transfer. All affected blogs immediately show as Published on the Posts page.<\/li>\n<\/ul>\n\n<h4>1.2.1<\/h4>\n\n<p>Internal code reorganisation. No behaviour changes.<\/p>\n\n<ul>\n<li>Improved: Plugin PHP files split into smaller, single-responsibility classes for easier maintenance and future development.<\/li>\n<\/ul>\n\n<h4>1.2.0<\/h4>\n\n<p>Image reliability fixes, automatic self-repair for all previously affected posts, and continuous background health monitoring.<\/p>\n\n<ul>\n<li>Fixed: Images were sometimes missing from the WordPress Media Library after publishing from DraftSEO. This happened silently on certain hosting environments due to differences in how the server handles external downloads. The plugin now tries an additional download method before giving up, significantly increasing import success rates across all hosting environments.<\/li>\n<li>New: After updating, the plugin automatically scans your entire site in the background for any posts where images were never properly imported from DraftSEO. Affected posts are silently repaired without any action needed from you. You can monitor progress under Tools &gt; Scheduled Actions in your WordPress admin.<\/li>\n<li>New: A lightweight check now runs automatically every 24 hours. If any post is found with images that didn't fully import \u2014 for example because a server timeout interrupted the process overnight \u2014 the plugin queues a repair automatically. No monitoring required: healthy sites see no activity and affected posts are fixed without manual intervention.<\/li>\n<li>Improved: The daily check permanently skips posts that have already been fully verified, so it stays fast regardless of how many posts are on your site. On a fully audited site the check completes in a fraction of a second. Republishing a post automatically resets it so new images are always verified.<\/li>\n<li>Improved: Image imports now run in controlled parallel batches, keeping resource usage predictable on any hosting environment. Designed and tested for sites publishing large numbers of blogs, each with many images.<\/li>\n<\/ul>\n\n<h4>1.1.6<\/h4>\n\n<p>Faster republishing \u2014 only new or changed images are re-downloaded.<\/p>\n\n<ul>\n<li>Improved: When republishing a post, images that were already imported in a previous publish are no longer downloaded again. Only new or replaced images are fetched. For a typical blog, republishing with no image changes now skips all image downloads entirely.<\/li>\n<\/ul>\n\n<h4>1.1.5<\/h4>\n\n<p>Reliable image import confirmation for all publish paths.<\/p>\n\n<ul>\n<li>Fixed: Republishing a post was blocked with \"not in completed status\" when a previous publish had images still importing in the background. Republishing now self-heals stuck jobs and always proceeds.<\/li>\n<li>Fixed: Manual publish and Republish now use the same async callback path as Auto-publish \u2014 DraftSEO is notified when all images finish importing instead of assuming completion immediately.<\/li>\n<li>Improved: The background image callback is now confirmed (blocking HTTP request) so Action Scheduler can automatically retry delivery if DraftSEO's server is temporarily unreachable.<\/li>\n<li>Improved: Republish is no longer blocked while images are still uploading \u2014 updating the post content always proceeds immediately, and image import completion is tracked in the background.<\/li>\n<\/ul>\n\n<h4>1.1.4<\/h4>\n\n<p>Cosmetic and connectivity improvements.<\/p>\n\n<ul>\n<li>Improved: Settings page now displays \"DraftSEO.ai\" with the installed plugin version shown next to the heading.<\/li>\n<li>Improved: Connection status now shows a clear \"Connection Issue\" state (instead of \"Connected\") when authentication with DraftSEO.ai fails \u2014 includes step-by-step instructions to reconnect.<\/li>\n<li>Improved: \"Go to DraftSEO.ai\" button on the connected settings page is cleaner \u2014 icon removed, label updated.<\/li>\n<\/ul>\n\n<h4>1.1.3<\/h4>\n\n<p>Reliability improvements, faster image loading, and cleaner background processing.<\/p>\n\n<ul>\n<li>Fixed: Images on published posts were sometimes not appearing on low-traffic websites \u2014 they were queued to download in the background but the background job wasn't starting until the next page visit. They now start immediately regardless of site traffic.<\/li>\n<li>Fixed: Switching the plugin off while a publish was in progress could leave background tasks running after deactivation. The plugin now cleanly stops all background jobs when it is deactivated.<\/li>\n<li>Fixed: Removing the plugin (uninstall) now properly disconnects your site from DraftSEO.ai \u2014 the connection is closed on the DraftSEO side before all plugin data is removed.<\/li>\n<li>Fixed: Plugin text was not translating correctly on WordPress sites running in a language other than English. Translation files now load properly.<\/li>\n<li>Improved: Background image jobs now use Action Scheduler instead of WP Cron. Action Scheduler runs as a true background process without requiring a page visit, retries failed jobs automatically, and shows pending and completed jobs in the WordPress admin at Tools &gt; Scheduled Actions.<\/li>\n<li>Improved: Images in background jobs are now downloaded in parallel before being imported. For a blog with 20 images this reduces total download time from roughly 60\u2013100 seconds (sequential) to 5\u201315 seconds (parallel).<\/li>\n<li>Fixed: Republishing a post was creating duplicate images in the Media Library for any image that had not changed. Only new or replaced images are now downloaded and imported \u2014 unchanged images are reused from the existing Media Library entry.<\/li>\n<\/ul>\n\n<h4>1.1.2<\/h4>\n\n<p>Security update: fixes API token authentication on WordPress sites where the Application Passwords feature or a security plugin was blocking server-to-server requests from DraftSEO.ai before they could be validated.<\/p>\n\n<h4>1.1.0<\/h4>\n\n<p>Automatic cleanup when republishing with a new image.<\/p>\n\n<ul>\n<li>When you republish a post with a new AI-generated image, the new image is swapped in automatically and the previous image is removed from your WordPress Media Library \u2014 keeps your media folder clean and saves storage space.<\/li>\n<\/ul>\n\n<h4>1.0.5<\/h4>\n\n<p>YouTube video embeds now work on WordPress.<\/p>\n\n<ul>\n<li>Fixed YouTube videos not appearing on published WordPress posts \u2014 videos are now properly converted to native WordPress embed blocks before publishing, so they show up as responsive YouTube players on your site<\/li>\n<\/ul>\n\n<h4>1.0.4<\/h4>\n\n<p>Content formatting and image fixes.<\/p>\n\n<ul>\n<li>Fixed headings appearing as raw text after images instead of being properly formatted<\/li>\n<li>Removed unwanted image captions \u2014 image descriptions were showing as visible text below every image. They are now used for accessibility only and no longer display on the page<\/li>\n<\/ul>\n\n<h4>1.0.3<\/h4>\n\n<p>Content formatting fixes.<\/p>\n\n<ul>\n<li>Fixed headings sometimes appearing as plain text instead of proper headings<\/li>\n<li>Fixed citation links being malformed in published posts<\/li>\n<\/ul>\n\n<h4>1.0.2<\/h4>\n\n<p>Citation links, external link handling, and FAQ structured data for rich results.<\/p>\n\n<ul>\n<li>In-text citations \u2014 <code>[1]<\/code>, <code>[2]<\/code> markers now render as clickable superscript links that jump to the matching reference in the References section<\/li>\n<li>References section \u2014 Converted to a numbered list with anchor IDs (<code>#ref-1<\/code>, <code>#ref-2<\/code>) for smooth in-page navigation<\/li>\n<li>External links \u2014 All external links now open in a new tab with <code>rel=\"noopener noreferrer\"<\/code><\/li>\n<li>FAQ structured data \u2014 FAQ question-answer pairs from blog content are injected as JSON-LD into the post <code>&lt;head&gt;<\/code> for Google FAQ rich results<\/li>\n<li>Theme-consistent styling \u2014 CSS is injected for citations, references, and tables so they display correctly across all WordPress themes<\/li>\n<li>Active sites filter \u2014 The WordPress site dropdown now shows only connected, active sites<\/li>\n<\/ul>\n\n<h4>1.0.1<\/h4>\n\n<p>Hotfix for content rendering in published posts.<\/p>\n\n<ul>\n<li>Fixed: YouTube embeds were being stripped during publishing \u2014 they now render as embedded players on your site<\/li>\n<li>Fixed: Data tables were displaying as raw Markdown text instead of formatted HTML tables<\/li>\n<\/ul>\n\n<h4>1.0.0<\/h4>\n\n<p>Major release \u2014 security hardening, reliability improvements, and full tag management.<\/p>\n\n<p><strong>Security<\/strong><\/p>\n\n<ul>\n<li>Webhook signatures \u2014 Disconnect and deactivation notifications are signed with HMAC-SHA256 (<code>X-DraftSEO-Signature<\/code>, <code>X-DraftSEO-Timestamp<\/code> headers); the API key is the signing secret and is never transmitted in plain text<\/li>\n<li>Replay protection \u2014 Signed requests include a Unix timestamp; requests older than 5 minutes are rejected<\/li>\n<li>API keys encrypted at rest \u2014 AES-256-CBC with a unique IV per key, derived from the WordPress site's auth salt<\/li>\n<\/ul>\n\n<p><strong>Publishing &amp; REST API<\/strong><\/p>\n\n<ul>\n<li>Tags endpoint \u2014 <code>GET \/wp-json\/draftseo\/v1\/tags<\/code> added for tag sync, matching the existing <code>\/users<\/code> and <code>\/categories<\/code> endpoints<\/li>\n<li>Server-side input validation \u2014 <code>\/publish<\/code> and <code>\/update<\/code> routes validate and sanitise all params before the handler runs<\/li>\n<li>Structured error responses \u2014 All errors return specific codes (<code>rest_forbidden<\/code>, <code>rest_missing_param<\/code>, <code>rest_publish_error<\/code>, etc.) for better debugging<\/li>\n<li>Bidirectional disconnect \u2014 Disconnecting from DraftSEO.ai calls <code>\/remote-disconnect<\/code> to clear connection settings on the plugin side automatically<\/li>\n<\/ul>\n\n<p><strong>Reliability<\/strong><\/p>\n\n<ul>\n<li>Handles security plugin blocks and maintenance pages gracefully \u2014 no silent failures when a WAF or caching layer intercepts requests<\/li>\n<li>Sync requests now have a timeout so connections never hang indefinitely<\/li>\n<li>Multi-site view: individual site connection errors are isolated so one broken connection does not affect others<\/li>\n<\/ul>\n\n<p><strong>Performance<\/strong><\/p>\n\n<ul>\n<li>Users, categories, and tags are now fetched in parallel instead of sequentially<\/li>\n<li>Retries only fire on server errors (5xx) \u2014 client errors (4xx) fail immediately without wasting retry attempts<\/li>\n<\/ul>\n\n<p><strong>Tag Management<\/strong><\/p>\n\n<ul>\n<li>Auto-create WordPress tags from AI-generated keywords at publish time (configurable, 1\u201310 tags)<\/li>\n<li>Select from existing WordPress tags, or create new ones on the fly during publishing<\/li>\n<\/ul>\n\n<p><strong>Image Handling<\/strong><\/p>\n\n<ul>\n<li>All images downloaded directly to your WordPress Media Library<\/li>\n<li>Alt text from DraftSEO.ai preserved as WordPress image alt text<\/li>\n<li>Featured image set automatically; all image URLs in post content updated from DraftSEO.ai CDN to your local Media Library URLs<\/li>\n<\/ul>\n\n<p><strong>Usability<\/strong><\/p>\n\n<ul>\n<li>\"Settings\" quick-link added to the Plugins page for faster access to plugin configuration<\/li>\n<\/ul>\n\n<h4>0.2.0<\/h4>\n\n<p>Initial beta release.<\/p>\n\n<ul>\n<li>One-click blog publishing from DraftSEO.ai<\/li>\n<li>Automatic image import from DraftSEO.ai<\/li>\n<li>SEO metadata transfer<\/li>\n<li>WordPress category sync<\/li>\n<li>Auto-create tags from keywords<\/li>\n<li>Multiple post status options (draft, publish, schedule)<\/li>\n<li>Content cleanup and formatting<\/li>\n<li>Secure API key encryption<\/li>\n<li>Background image processing for large blogs<\/li>\n<li>Remote disconnect synchronization<\/li>\n<li>OAuth-based connection flow<\/li>\n<\/ul>","raw_excerpt":"Publish AI-generated blogs from DraftSEO.ai directly to WordPress with automatic image import and SEO optimization.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/ne.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/258332","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ne.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/ne.wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/ne.wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=258332"}],"author":[{"embeddable":true,"href":"https:\/\/ne.wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/klimentp"}],"wp:attachment":[{"href":"https:\/\/ne.wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=258332"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/ne.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=258332"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/ne.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=258332"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/ne.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=258332"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/ne.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=258332"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/ne.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=258332"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}