=== BinaryPH AI SEO === Contributors: BinaryPH Tags: seo, ai, schema, sitemap, redirects Requires at least: 6.5 Tested up to: 6.9 Requires PHP: 8.0 Stable tag: 2.6.3 License: GPL2 A complete WordPress SEO plugin powered by AI. Focus keywords, meta descriptions, alt text, schema, sitemap, redirects, and 1-click optimization. == Description == BinaryPH AI SEO is a complete, standalone SEO plugin built for non-technical site owners. Click one button and we set up your site. Click another and we fix every page that needs attention. = What it does = * **1-Click Optimize.** Fixes missing focus keywords, meta descriptions, SEO titles, image alt text, schema, and canonicals across your whole site in one go. Live progress, pause/cancel, retry on failure. * **Quick Setup with best-default config.** Pick a profile (Blog / WooCommerce / News) or hit "Apply best defaults" — sitemap, schema, social tags, daily automation, robots.txt all configured for you. * **AI focus keywords + search snippets** for posts, pages, and WooCommerce products. * **AI-powered image alt text** using vision-capable providers (Gemini, OpenRouter vision, Pollinations, Ollama llava). * **XML sitemap.** A real sitemap-index that scales to large sites. * **Schema (rich result info).** Article, Breadcrumb, and Organization JSON-LD out of the box. * **Open Graph and Twitter Card** tags for nice link previews on Facebook, X, LinkedIn. * **Per-post meta box** with focus keyword, SEO title, search snippet, canonical, "Hide from Google" toggle, and a live SERP preview. * **301 redirects + 404 logger.** When pages move, redirect them. We log 404s so you can fix them with one click. * **robots.txt editor.** No file editing required. * **SEO Health Score (0-100)** on the dashboard so you always know where you stand. * **Audit log.** Every change tracked, with old → new diffs. * **Import from Rank Math, Yoast, AIOSEO.** One-click migration of focus keywords, snippets, SEO titles, canonicals, noindex flags, redirects, and 404 logs. Tools → Import. * **Cost tracker + monthly budget cap** for paid AI providers. * **Provider fallback chain.** Tries Pollinations (free), then OpenRouter, then Gemini — so generation almost never fails. = AI providers supported = * Pollinations — free tier, key from https://enter.pollinations.ai (default) * Google Gemini — free tier, key from https://aistudio.google.com/app/apikey * OpenRouter — free models available, key from https://openrouter.ai/keys * xAI Grok — paid, key from https://console.x.ai/ * Ollama — local, no API key needed * OpenWebUI — self-hosted, your own instance + key = Designed for everyone = * Plain-language labels everywhere ("Search snippet", "Hide from Google") with the technical name in tooltips. * Beginner mode by default — power-user fields stay hidden until you ask for them. * Dark mode supported. Responsive admin pages. * Fully translatable. * Encrypted API keys at rest (libsodium). * Works alongside Yoast, Rank Math, and All in One SEO if you want — or replace them. = How it pairs with Yoast / Rank Math / AIOSEO = By default, fresh installs run standalone. If we detect Yoast or Rank Math when you activate, we switch to "defer" mode and fill in their fields instead of duplicating. Pick your preferred mode in Settings → Advanced. == External Services == This plugin connects to third-party AI APIs to generate SEO content based on the post, page, product, or image you choose. Requests are made only when you trigger them or when scheduled automation runs. The default provider is Pollinations; a free API key from enter.pollinations.ai is required, and the Setup Wizard links you to the signup page. Each provider runs on the user's own account — the plugin never proxies, stores, or resells AI usage. * Google Gemini — https://ai.google.dev/gemini-api/docs/ — Privacy: https://policies.google.com/privacy * OpenRouter — https://openrouter.ai/docs — Privacy: https://openrouter.ai/privacy * xAI Grok — https://docs.x.ai/ — Privacy: https://x.ai/legal/privacy-policy * Pollinations — https://gen.pollinations.ai/ — Get a free key at https://enter.pollinations.ai — Privacy: https://pollinations.ai/privacy * Ollama (local) — https://ollama.com/ — Runs on your own server. * OpenWebUI (self-hosted) — https://openwebui.com/ — Runs on your own server. == Installation == 1. Upload the plugin to `/wp-content/plugins/binaryph-ai-seo/`. 2. Activate. The Setup Wizard opens automatically. 3. Click **Quick Setup — apply best defaults** for instant configuration. 4. Click **Optimize my whole site** on the dashboard to fill in everything missing. == Frequently Asked Questions == = Do I need an API key? = Yes — most providers require one, but several offer free tiers. Pollinations (the default), Gemini, and OpenRouter all have free tiers; signup takes about 30 seconds. The Setup Wizard will link you to the right page. Ollama runs locally with no key. = Does this conflict with Yoast or Rank Math? = No. We detect them on activation and switch to "defer" mode by default — we fill their fields rather than duplicate. You can change to standalone mode any time. = Will the optimizer cost money? = If you stay on the free tier of Pollinations / Gemini / OpenRouter, or use Ollama locally, no. If you exceed those tiers or pick a paid provider, set a monthly budget cap (in cents) in Settings → AI Providers (Advanced) and we will stop before exceeding it. = Where are my API keys stored? = Encrypted at rest using libsodium (sodium_crypto_secretbox). If your PHP build is missing libsodium we fall back to plaintext and show an admin notice. = Can I undo a change? = Yes. Every change is recorded in the Audit Log with old and new values. == Changelog == = 2.1.1 = * Migration: Rank Math and Yoast term-level SEO (focus keyword, search snippet, SEO title, canonical, noindex on every category/tag/custom taxonomy term) is now copied into BinaryPH's term meta. Previously term archives reverted to defaults after switching to Standalone. * Migration: per-post primary category is now copied (Rank Math `rank_math_primary_category`, Yoast `_yoast_wpseo_primary_category` → `_bps_primary_category`). * Schema: breadcrumb category selection now honors the user's primary category instead of always picking the first attached category. Applies to both posts and WooCommerce products. * Migration preview now lists detected per-post schema customizations from Rank Math (FAQ, HowTo, Recipe, Event, Course, JobPosting, Product) and Yoast (Article-type / Page-type overrides) so users see *before* importing what will need to be re-entered manually after switching to Standalone. We deliberately do not auto-copy these — the source plugins' serialized schema field shapes vary across versions and a bad mapping would corrupt rich snippets. * New: when in Standalone mode and we detect leftover SEO data from Rank Math / Yoast / All in One SEO that has not been migrated, a friendly dismissible admin notice now nudges the user to run Tools → Import. Catches the common foot-gun where someone switches to Standalone before running the importer. * Fix: a bad `/sitemap-{unknown-type}-N.xml` URL no longer returns an HTML body under an `application/xml` Content-Type header. We now validate the post-type slug *before* setting the XML header. * Security: removed JSON_UNESCAPED_SLASHES from JSON-LD output so a stray "" inside any user-supplied custom JSON-LD value can no longer break out of the script tag. * Security: optimizer now checks the per-post `edit_post` capability before rewriting any post's SEO fields — a user with `bps_manage_seo` can no longer touch posts they cannot otherwise edit. The bulk-apply REST endpoint now whitelists the `field` parameter against `focus_kw / meta_desc / seo_title / canonical`. * Fix: cron lock now uses an atomic option insert instead of read-then-write, so two concurrent cron workers can no longer both pass the check and run (which previously could double-bill an AI provider). Stale locks (>5 min) are auto-cleared. * Fix: Quick Setup re-run no longer silently overwrites user customisations. First run still applies all defaults; subsequent runs only fill in genuinely missing options. An explicit "force reset" path is available for a deliberate reset action. * Fix: provider fallback chain no longer breaks when a custom AI model name is set. The `bps_ai_model` setting now applies only to the primary provider; fallback providers use their own default model. * Fix: cancelling the optimizer no longer triggers the "Done!" toast + confetti + page reload as if the run had succeeded. * Fix: settings JSON import now coerces each option to its expected type (booleans → '1'/'0', integers, URLs, textareas, sanitize_key, sanitize_text_field). Type-mismatched values are skipped instead of corrupting the option. * Fix: when ciphertext exists but libsodium is no longer available on the server, a distinct red admin notice now tells the user to re-enter their API keys, instead of the misleading "no API key configured" error. * Fix: when no custom robots.txt is set, the plugin now actually appends the `Sitemap:` line to whatever WordPress core produced (previously a dead `if` block did nothing). * Fix: switching coexistence mode (e.g. Defer → Standalone after a Rank Math import) now flushes WordPress rewrite rules automatically so `/sitemap.xml` routes immediately. Previously users had to visit Permalinks → Save to force a flush before our sitemap was reachable. * Codebase: full Plugin Check / WPCS sweep — 59/59 PHP and 9/9 JS files lint-clean with documented suppressions for safe-by-construction patterns (custom-table queries, registered-prefix names, etc.). = 2.1.0 = * Schema expansion: FAQ, HowTo, Product (auto-detected on WooCommerce), Recipe, Event, Course, Job Posting, plus per-post Custom JSON-LD pass-through and a structured multi-location LocalBusiness editor. * Term-level SEO on every public taxonomy (focus keyword, SEO title, meta description, canonical, noindex). * New AI helpers — all run on YOUR own provider account: FAQ extraction from content, slug optimizer, readability scorer (Flesch + AI tips), internal-link suggestions. * Orphan-page detector with AI-powered link suggestions; new dashboard tile (lazy-loaded so first visit is never blocked). * /llms.txt generator — markdown index of your site for AI crawlers, with live preview in Tools. * Search engine verification meta tags for Google, Bing, Yandex, Pinterest, Baidu, Norton, Alexa (paste-friendly: full tags are auto-stripped). * Native GA4 snippet with admin-exclude and IP-anon defaults on. * Smart capitalize titles, strip /category/ base, redirect attachments to parent (default ON), nofollow + new-tab external links, archive noindex (date/search ON by default). * Redirect engine extended: 307 / 410 / 451 status codes, regex sources (~...~) with $1 back-reference support in the target. * CSV redirect import (drop-zone or paste) with header auto-detection. * Settings JSON export/import (drop-zone) — API keys deliberately excluded. * Find & Replace tool across post titles, content, excerpts, image alt/title/caption, with dry-run + diff preview. * Tools page reorganized into 6 tabs: Import / Redirects CSV / Find & Replace / Orphan pages / llms.txt preview / Settings IO. * Settings: 3 new tabs (Schema, Tracking & Verification, Links & Archives) using a card-grid + toggle-switch picker. * Per-post metabox: AI helper panel, FAQ items with add/remove, primary category picker (when 2+ cats), custom JSON-LD with live validation badge. * All "Start" actions are now "Stop"-able mid-flight: Media bulk alt, Content bulk-generate, Content bulk-apply, Migrator imports — all with server-side cancel transients and instant UI feedback. * Loading bars converted to layered indeterminate animation (sliding gradient + diagonal stripes) so motion is guaranteed even when backend percentages stall. Skeleton-line and bouncing-dot loaders added. * Mobile UX overhaul: feature cards collapse to single column, tabs horizontal-scroll, forms get 16px font (no iOS zoom-on-focus), tap targets ≥40px. * Light-mode-only UI (dark-mode CSS overrides removed; they were the cause of unreadable text on systems with OS dark mode). * Quick Setup defaults now explicitly enumerate every v2.1 option so a fresh install has every safe feature on without needing user input. * Prominent "AI runs on YOUR account" notice in setup wizard, AI Providers settings, and per-post metabox. = Bug fixes in 2.1.0 = * Settings export now downloads a clean JSON file (was double-encoded via WP_REST_Response wrapper). * Schema::should_emit() exposed to public so v2.1 schema modules can gate their output (was private — would fatal on every page). * Redirect engine: explicit exit; after wp_die() on 410/451 to guarantee no later hooks fire. * Native-fetch path of BPS.rest() now preserves WP_Error code and data, fixing the "Open settings" modal that reads err.code === 'no_provider'. * Orphan-detector scan moved off the synchronous dashboard render path — large sites no longer block on first visit. * Archive noindex feature actually emits the meta tag (was wired to a filter nothing applied). = 2.0.0 = * MAJOR REWRITE: full standalone SEO plugin. * New 1-Click Optimize button on the dashboard with live progress, pause, cancel, retry, and score-delta feedback. * New Quick Setup wizard with three profiles (Blog / WooCommerce / News). * New SEO Health Score (0-100) on the dashboard, score-component breakdown, and SEO health WP dashboard widget. * New: standalone XML sitemap, Article/Breadcrumb/Organization schema, Open Graph + Twitter cards, canonical, noindex, robots.txt editor, 301 redirects + 404 logger. * New per-post meta box with SERP preview, character counters, regenerate buttons. * New consolidated Content page (replaces separate Posts/Pages/Products pages). * New Audit Log of every AI change. * New AI provider fallback chain (Pollinations → OpenRouter → Gemini by default). * New cost tracker + monthly budget cap. * New vision support for image alt text (Gemini, OpenRouter, Pollinations, Ollama llava). * SEO data adapter system supports BinaryPH (Native), Yoast, Rank Math, and AIOSEO. * API keys now encrypted at rest with libsodium (auto-migrated on upgrade). * Brand-new admin UI with design tokens, dark mode, accessibility (WCAG AA), responsive layouts, toast notifications, modals, empty states. * Full i18n support — every string translatable. Domain Path: /languages. * New uninstall.php that fully cleans up options, transients, custom tables, capabilities, and post meta. * New "Import from another SEO plugin" tool — copies post meta, redirects, and 404 logs from Rank Math, Yoast SEO, or All in One SEO into BinaryPH AI SEO's native storage. Source plugin data is never modified, so it serves as a backup. = Bug fixes in 2.0.0 = * CRITICAL: Gemini API was failing silently due to wrong auth method. Now uses ?key= query string per Google docs. * Prompt injection hardening — post titles are now sanitized before going into the prompt. * AI responses are cleaned up (strips quotes, asterisks, "Focus keyword:" prefixes, takes only first line). * AI responses are cached for 1 hour to avoid re-billing on transient failures. * Concurrency lock on the cron worker prevents overlapping runs from double-billing. * Cron worker context is now cleanly split (no more $_POST inspection inside cron). * Fixed unindexed JOIN in the missing-keywords query (now casts attachment ID and guards against malformed values). * Activation no longer schedules cron when scheduling is disabled. * All admin notices include error details parsed from provider JSON, not silent failures. * Pollinations endpoint set to https://gen.pollinations.ai/v1/chat/completions per the latest API docs. * Pollinations now requires an API key (free tier from enter.pollinations.ai) — wizard guides users through signup. * Asset cache-busting now uses file mtime + plugin version constant. * Multisite-aware uninstall (cleans every site on network deletes). = 1.0.5 = * Added meta description generation, image alt text injection, better detection of missing fields. = 1.0.4 = * WP 6.9.1 compatibility, Pollinations.AI provider, WP Cron improvements, nonce fix. = 1.0.3 = * WooCommerce, Yoast, and Rank Math optimization. == Upgrade Notice == = 2.0.0 = Major rewrite. API keys auto-migrate to encrypted storage. The legacy menu items redirect to the new pages. Fixes a critical Gemini bug — Gemini calls in 1.x were silently failing.