Keyword Coverage — WordPress Plugin Build Specification

Keyword Coverage — WordPress Plugin Build Specification

1. Purpose

Build a WordPress plugin called Keyword Coverage that helps bulk-content bloggers/affiliate sites decide *what to write next* and *where to publish it*, using semantic embeddings (not just exact-string matching) to compare a bulk list of keywords against a site’s existing published content and category taxonomy.

The plugin has three features, all built on the same core primitive: embed text → compare via cosine similarity.

1. Keyword Coverage Search — classify each input keyword as `Covered`, `Weak`, or `Gap` against existing published posts.
2. Semantic Grouper — cluster a bulk keyword list into groups of meaningfully-identical keywords so duplicates can be eliminated with one click.
3. Keyword Grouper (Category Mapper) — assign each surviving keyword to the best-matching existing WordPress category, or flag it as needing a new category.


2. Core Architecture

2.1 Embedding provider

  • Use an embeddings API (OpenAI `text-embedding-3-small`, or Voyage AI, or Google `text-embedding-004`). Store the API key in a plugin settings page (`Settings > Keyword Coverage`).
  • – Abstract the provider behind a single PHP class `KC_Embedding_Client` with method `embed( array $texts ): array` so the provider can be swapped later.

    • Batch requests (provider limits, e.g. 100–2000 inputs per call) with retry/backoff.
    • 2.2 Storage

      Custom table `wp_kc_embeddings`:
      | column | type | notes |
      |


      |


      |


      |
      | id | bigint PK | |
      | object_type | varchar(20) | `post`, `category`, `keyword_cache` |
      | object_id | bigint | post ID or term ID (nullable for ad-hoc keyword cache) |
      | source_hash | varchar(64) | md5 of the text that was embedded, to detect staleness |
      | embedding | longtext (JSON array) or use a vector-capable table if MySQL/MariaDB version supports it | |
      | updated_at | datetime | |

      Post embeddings: generated from `post_title + focus_keyword (Rank Math/Yoast meta if present) + first ~300 words of content`. Regenerate on `save_post` hook (debounced) or via a manual “Rebuild Index” button, since re-embedding all posts on every request is too slow/expensive.
      Category embeddings: generated from `category name + category description + titles of up to N posts in that category`. Rebuild on `create_category`/`edited_category`/manual refresh.
      Keyword embeddings: computed on-demand per request (bulk keyword pastes aren’t reused often enough to justify permanent caching, but cache for the duration of a session/job in a transient or the same table with `object_type = keyword_cache`).

      2.3 Background processing

      Bulk jobs (thousands of keywords × embedding calls + similarity math) must NOT run synchronously in a single HTTP request.
      – Use Action Scheduler (bundled with WooCommerce/many plugins, or pull in as a library) or a simple custom queue table + WP-Cron, to process keyword batches (e.g. 200 at a time) in the background.

      • Admin UI polls a REST endpoint for job progress and shows a progress bar.
      • – Store job results in a custom table `wp_kc_jobs` (job_id, type, status, input, result JSON, created_at).

        2.4 Admin UI

        Three tabs under one top-level admin menu “Keyword Coverage”:

        • Tab 1: Coverage Search
        • – Tab 2: Semantic Grouper

          • Tab 3: Category Mapper
          • Common UI pattern per tab:

            • Large `