Skip to content

Bulk topic & theme taxonomy import

Last updated on June 8, 2026

A new WP‑CLI based taxonomy import workflow was successfully implemented for the lyric CPT system. The goal was to bulk‑assign topic and theme taxonomy terms to previously created lyric entries using a CSV export structure. This solved the problem of older content existing before the newer structured tagging workflow was fully established.

The CSV format used was intentionally simple and scalable:

id,add_topics,add_themes
27298,"Earth|Change|Motion","Round and Round|The World Got Still|As the World Turns"

Each row contains:

  • the target CPT ID
  • pipe‑separated topic terms
  • pipe‑separated theme terms

A reusable WP‑CLI import script was created and tested successfully against ~100 lyric entries. The script:

  • validates the CPT type before processing
  • preserves existing taxonomy relationships
  • merges new terms safely
  • avoids duplicate term assignment
  • provides CLI logging/output during imports
  • supports repeatable/idempotent reruns safely

The import process was ultimately used to retroactively update older lyrics that had not yet received structured topic and theme taxonomy assignments.

Final usage pattern:

wp eval-file import-lyric-tags.php tags.csv

Optional dry‑run mode:

wp eval-file import-lyric-tags.php tags.csv dry-run

Key implementation detail discovered during testing: the site uses custom topic and theme taxonomies rather than native WordPress post_tag. Early tests mistakenly wrote to post_tag, creating unused “ghost” terms with zero usage counts. These were safely identified and removed afterward using WP‑CLI cleanup commands.

Critical taxonomy correction:

// WRONG
'post_tag'

// CORRECT
'topic'

Core taxonomy merge logic used by the final importer:

$existing = wp_get_post_terms(
    $post_id,
    'topic',
    ['fields' => 'names']
);

$merged = array_unique(array_merge($existing, $topics));

$result = wp_set_post_terms(
    $post_id,
    $merged,
    'topic',
    false
);

The importer can now be reused across other CPT systems (such as excerpts, fragments, chapters, etc.) simply by changing the CPT validation check:

if (get_post_type($post_id) !== 'excerpt') {
    WP_CLI::log("Skipping {$post_id} (not excerpt)");
    $skipped++;
    continue;
}

This establishes a scalable bulk taxonomy maintenance workflow for the broader structured content architecture of the site. Future imports can now be performed quickly whenever taxonomy tagging falls behind content creation.