Skip to content

Backfilling coauthor terms for legacy posts

Gary Jones edited this page Apr 24, 2026 · 1 revision

Co-Authors Plus stores each post's byline in a custom author taxonomy. When the plugin is first installed on an existing site, posts created before activation have a post_author but no author taxonomy terms — which means the block editor sidebar, archive queries and template tags have nothing to display.

The plugin ships a WP-CLI command that seeds those missing terms from post_author, so legacy posts appear correctly in the editor and on the front end without any manual editing.

When to run it

Run the command in the following situations:

  • Immediately after installing Co-Authors Plus on an existing site, to backfill every post that predates the plugin.
  • After a content import that created posts without going through CAP's save hooks (for example, direct database imports, wp import with a coauthor-unaware source, or some staging-to-production sync tools).
  • Occasionally as a safety net, if you have automation that writes posts through paths that may skip wp_insert_post.

You do not need to run it as part of normal day-to-day operations. Posts that are created or edited through the block editor, the classic editor, the REST API or wp post are all assigned coauthor terms automatically.

The command

wp co-authors-plus create-author-terms-for-posts [options]

Without options, the command processes post post type with publish status only, in batches of 250 posts, and skips any post that already has coauthor terms. That is the right default for most sites and can be interrupted and restarted safely — posts that were already processed will be skipped on the next run.

Options

Option Default Description
--post-types=<csv> post Comma-separated list of post types to process. Pass the slugs of every CAP-enabled post type you want to include, for example post,page,podcast.
--post-statuses=<csv> publish Comma-separated list of post statuses to process. Pass publish,future,draft,private if you want to include unpublished content.
--records-per-batch=<n> 250 Batch size. Lower values reduce per-batch memory and query cost but increase the total number of batches.
--unbatched (batched) Process every matching post in a single query rather than paging. Useful for small sites; risky for large ones.
--specific-post-ids=<csv> (none) Comma-separated list of post IDs to restrict processing to. Everything else is ignored.
--above-post-id=<id> (none) Process only posts with IDs greater than this value.
--below-post-id=<id> (none) Process only posts with IDs less than this value.

--above-post-id and --below-post-id can be combined to process a specific ID range — useful for splitting a very large backfill into chunks you can run over multiple maintenance windows. The command will throw an exception if --above-post-id is greater than or equal to --below-post-id.

Examples

Backfill every published post on a standard-blog site:

wp co-authors-plus create-author-terms-for-posts

Backfill across several post types and include drafts and scheduled posts:

wp co-authors-plus create-author-terms-for-posts \
    --post-types=post,page,podcast \
    --post-statuses=publish,future,draft,private

Dry-run style chunking — process a narrow ID range first to estimate performance before running the full job:

wp co-authors-plus create-author-terms-for-posts \
    --above-post-id=0 --below-post-id=10000 \
    --records-per-batch=100

Fix a specific set of posts flagged by a reporter:

wp co-authors-plus create-author-terms-for-posts \
    --specific-post-ids=4821,5103,5247

What the command does

For each matching post that has no coauthor terms:

  1. Load the user identified by post_author.
  2. Find or create the CAP author term for that user.
  3. Insert a row into wp_term_relationships linking the post to that term.

Posts that already have one or more coauthor terms are left untouched. If post_author points to a user that no longer exists, the post is marked with a skip flag in post meta so subsequent runs do not keep retrying it.

After all posts have been processed, the command refreshes the cached post count on each author term that was touched.

What the command does not do

  • It does not overwrite existing coauthor assignments. A post that already has coauthor terms — even a single wrong one — is skipped. If you need to fix an existing assignment, edit the post directly.
  • It does not create guest authors. post_author always refers to a real WordPress user; if you want the byline to read as a guest author, create the guest author profile first and assign it in the UI.
  • It does not infer authorship from post meta, the slug, or anywhere else. post_author is the only source of truth it consults.

Related commands

  • wp co-authors-plus create-terms-for-posts — an older, untargeted version of the same backfill. It walks the full posts table from the beginning every run, which is slower on large sites. Prefer create-author-terms-for-posts for everything except small one-shot jobs.
  • wp co-authors-plus delete-postmeta-that-skip-author-term-backfill — removes the skip meta that the backfill sets when it encounters a post whose post_author does not exist. Run this if you have restored or recreated the missing user accounts and want the backfill to re-attempt those posts.
  • wp co-authors-plus assign-coauthors — a migration helper that reads the intended author from a post-meta key (default _original_import_author). This is for importing from systems that store authorship in custom post meta, not for general backfill.

Performance notes

  • The command prints a progress message for every post. On very large sites, consider redirecting to a file (> backfill.log 2>&1) rather than watching the live output.
  • Every 500 posts, the command sleeps for one second. This is deliberate back-pressure to protect the database; do not remove it. If you need a faster run on an overprovisioned database, lower --records-per-batch and run multiple ranges in parallel with different --above-post-id / --below-post-id values.
  • Term cache invalidation happens at the end, not per-post, so a large run will show slightly stale term counts in the admin until it finishes.

Clone this wiki locally