Skip to main content

Taxonomy Management

Overview

Taxonomies are WordPress's system for organizing content. WP-CLI provides powerful commands to manage categories, tags, and custom taxonomies—essential for content organization, SEO, and site structure.

Understanding WordPress Taxonomies

WordPress uses taxonomies to group and organize content:

  • Categories - Hierarchical classification (can have parent/child)
  • Tags - Flat keywords (no hierarchy)
  • Custom Taxonomies - Custom groupings (genres, locations, products, etc.)

Taxonomy Types

Built-in Taxonomies

# List all registered taxonomies
wp taxonomy list

# List with details
wp taxonomy list --format=table

# Get specific taxonomy info
wp taxonomy get category
wp taxonomy get post_tag

Common taxonomies:

  • category - Post categories (hierarchical)
  • post_tag - Post tags (flat)
  • product_cat - WooCommerce product categories
  • product_tag - WooCommerce product tags

Custom Taxonomies

Custom taxonomies are registered by themes or plugins:

# List taxonomies for specific post type
wp taxonomy list --object_type=post
wp taxonomy list --object_type=product

# Check if taxonomy exists
wp taxonomy get genre

Managing Terms

Create Terms

# Create category
wp term create category "News"

# Create with slug
wp term create category "Technology" --slug=tech

# Create with description
wp term create category "WordPress" \
--slug=wordpress \
--description="All about WordPress"

# Create tag
wp term create post_tag "tutorial"

Create Hierarchical Terms

# Create parent category
PARENT_ID=$(wp term create category "Technology" --porcelain)

# Create child category
wp term create category "Web Development" --parent=$PARENT_ID

# Create multiple levels
wp term create category "WordPress" --parent=$PARENT_ID
wp term create category "JavaScript" --parent=$PARENT_ID

Create Custom Taxonomy Terms

# Create terms for custom taxonomy
wp term create genre "Science Fiction" --slug=sci-fi
wp term create genre "Fantasy"
wp term create genre "Mystery"

# Create location taxonomy terms
wp term create location "New York" --slug=ny
wp term create location "Los Angeles" --slug=la

Listing Terms

Basic Listing

# List all categories
wp term list category

# List with specific fields
wp term list category --fields=term_id,name,slug,count

# List in table format
wp term list category --format=table

Filter and Sort

# List only terms with posts
wp term list category --hide_empty=true

# List including empty terms
wp term list category --hide_empty=false

# Order by name
wp term list category --orderby=name --order=ASC

# Order by count
wp term list category --orderby=count --order=DESC

Export Term Lists

# Export to CSV
wp term list category --format=csv > categories.csv

# Export to JSON
wp term list category --format=json > categories.json

# Get just IDs
wp term list category --field=term_id

# Get just names
wp term list category --field=name

Updating Terms

Update Term Details

# Update name
wp term update category 5 --name="Updated Name"

# Update slug
wp term update category 5 --slug=new-slug

# Update description
wp term update category 5 --description="New description"

# Update parent
wp term update category 10 --parent=5

# Update multiple fields
wp term update category 5 \
--name="Technology News" \
--slug=tech-news \
--description="Latest technology updates"

Reorganize Hierarchy

# Move category to new parent
wp term update category 15 --parent=10

# Make category top-level (remove parent)
wp term update category 15 --parent=0

# Swap parent/child relationship
CHILD_ID=15
PARENT_ID=10

wp term update category $CHILD_ID --parent=0
wp term update category $PARENT_ID --parent=$CHILD_ID

Deleting Terms

Delete Single Term

# Delete term
wp term delete category 5

# Delete tag
wp term delete post_tag 10

Bulk Delete Operations

# Delete all empty categories
wp term list category --hide_empty=false --count=0 --field=term_id | \
xargs -I {} wp term delete category {}

# Delete all tags
wp term list post_tag --field=term_id | \
xargs -I {} wp term delete post_tag {}

# Delete specific terms
wp term delete category 5 10 15 20

Getting Term Information

Get Term Details

# Get all term data
wp term get category 5

# Get specific field
wp term get category 5 --field=name
wp term get category 5 --field=slug
wp term get category 5 --field=count
wp term get category 5 --field=parent

# Get in JSON format
wp term get category 5 --format=json

Check Term Existence

# Check if term exists
if wp term get category 5 > /dev/null 2>&1; then
echo "Term exists"
else
echo "Term not found"
fi

Assigning Terms to Posts

Assign Categories

# Assign category to post
wp post term add 123 category 5

# Assign multiple categories
wp post term add 123 category 5 10 15

# Replace all categories
wp post term set 123 category 5 10

Assign Tags

# Add tags to post
wp post term add 123 post_tag 20 25 30

# Set tags (replace existing)
wp post term set 123 post_tag 20 25 30

Bulk Term Assignment

# Add category to all published posts
wp post list --post_status=publish --field=ID | \
xargs -I {} wp post term add {} category 5

# Set category for all posts by author
wp post list --post_author=2 --field=ID | \
xargs -I {} wp post term set {} category 10

Real-World Scenarios

Scenario 1: Setup Blog Categories

#!/bin/bash
# setup-blog-categories.sh

echo "Setting up blog categories..."

# Create main categories
NEWS=$(wp term create category "News" --porcelain)
TUTORIALS=$(wp term create category "Tutorials" --porcelain)
REVIEWS=$(wp term create category "Reviews" --porcelain)

# Create subcategories
wp term create category "WordPress News" --parent=$NEWS
wp term create category "Industry News" --parent=$NEWS

wp term create category "Beginner Tutorials" --parent=$TUTORIALS
wp term create category "Advanced Tutorials" --parent=$TUTORIALS

wp term create category "Plugin Reviews" --parent=$REVIEWS
wp term create category "Theme Reviews" --parent=$REVIEWS

echo "Blog categories created successfully!"

Scenario 2: Taxonomy Audit

#!/bin/bash
# taxonomy-audit.sh

echo "=== Taxonomy Audit Report ==="
echo "Date: $(date)"
echo ""

echo "Categories:"
echo " Total: $(wp term list category --format=count)"
echo " With posts: $(wp term list category --hide_empty=true --format=count)"
echo " Empty: $(wp term list category --hide_empty=false --count=0 --format=count)"
echo ""

echo "Tags:"
echo " Total: $(wp term list post_tag --format=count)"
echo " With posts: $(wp term list post_tag --hide_empty=true --format=count)"
echo " Empty: $(wp term list post_tag --hide_empty=false --count=0 --format=count)"
echo ""

echo "Top 10 Categories by Post Count:"
wp term list category --orderby=count --order=DESC --number=10 --fields=name,count --format=table

Scenario 3: Cleanup Unused Terms

#!/bin/bash
# cleanup-unused-terms.sh

echo "Finding unused terms..."

# Count empty categories
EMPTY_CATS=$(wp term list category --hide_empty=false --count=0 --format=count)
echo "Empty categories: $EMPTY_CATS"

# Count empty tags
EMPTY_TAGS=$(wp term list post_tag --hide_empty=false --count=0 --format=count)
echo "Empty tags: $EMPTY_TAGS"

if [ "$EMPTY_CATS" -gt 0 ] || [ "$EMPTY_TAGS" -gt 0 ]; then
read -p "Delete all empty terms? (y/n) " -n 1 -r
echo

if [[ $REPLY =~ ^[Yy]$ ]]; then
# Delete empty categories
wp term list category --hide_empty=false --count=0 --field=term_id | \
xargs -I {} wp term delete category {}

# Delete empty tags
wp term list post_tag --hide_empty=false --count=0 --field=term_id | \
xargs -I {} wp term delete post_tag {}

echo "Cleanup complete!"
fi
fi

Scenario 4: Migrate Categories

#!/bin/bash
# migrate-categories.sh - Export from one site, import to another

# On source site
echo "Exporting categories..."
wp term list category --format=json > categories-export.json

# Transfer file to destination site
# scp categories-export.json user@destination:/tmp/

# On destination site
echo "Importing categories..."
cat categories-export.json | jq -r '.[] | "\(.name)|\(.slug)|\(.description)|\(.parent)"' | \
while IFS='|' read -r name slug description parent; do
if [ "$parent" != "0" ]; then
# Find parent term ID on new site
PARENT_ID=$(wp term list category --slug="$parent" --field=term_id)
wp term create category "$name" --slug="$slug" --description="$description" --parent="$PARENT_ID"
else
wp term create category "$name" --slug="$slug" --description="$description"
fi
done

echo "Migration complete!"

Scenario 5: Bulk Recategorize

#!/bin/bash
# recategorize-posts.sh

OLD_CATEGORY=5
NEW_CATEGORY=10

# Find posts in old category
POSTS=$(wp post list --category=$OLD_CATEGORY --field=ID)
POST_COUNT=$(echo $POSTS | wc -w)

echo "Found $POST_COUNT posts in category $OLD_CATEGORY"
read -p "Move to category $NEW_CATEGORY? (y/n) " -n 1 -r
echo

if [[ $REPLY =~ ^[Yy]$ ]]; then
for post_id in $POSTS; do
# Remove old category
wp post term remove $post_id category $OLD_CATEGORY
# Add new category
wp post term add $post_id category $NEW_CATEGORY
done

echo "Recategorization complete!"
fi

Advanced Operations

Generate Term Hierarchy

#!/bin/bash
# generate-location-taxonomy.sh

# Create continents
NORTH_AMERICA=$(wp term create location "North America" --porcelain)
EUROPE=$(wp term create location "Europe" --porcelain)
ASIA=$(wp term create location "Asia" --porcelain)

# Create countries
USA=$(wp term create location "United States" --parent=$NORTH_AMERICA --porcelain)
CANADA=$(wp term create location "Canada" --parent=$NORTH_AMERICA --porcelain)

UK=$(wp term create location "United Kingdom" --parent=$EUROPE --porcelain)
FRANCE=$(wp term create location "France" --parent=$EUROPE --porcelain)

# Create cities
wp term create location "New York" --parent=$USA
wp term create location "Los Angeles" --parent=$USA
wp term create location "Toronto" --parent=$CANADA
wp term create location "London" --parent=$UK
wp term create location "Paris" --parent=$FRANCE

echo "Location hierarchy created!"

Merge Terms

#!/bin/bash
# merge-terms.sh - Merge two categories

SOURCE_TERM=5
TARGET_TERM=10

# Get posts from source term
POSTS=$(wp post list --category=$SOURCE_TERM --field=ID)

# Move posts to target term
for post_id in $POSTS; do
wp post term remove $post_id category $SOURCE_TERM
wp post term add $post_id category $TARGET_TERM
done

# Delete source term
wp term delete category $SOURCE_TERM

echo "Terms merged successfully!"

Rename Terms in Bulk

#!/bin/bash
# rename-terms-bulk.sh

# Rename terms based on pattern
wp term list category --field=term_id | while read term_id; do
OLD_NAME=$(wp term get category $term_id --field=name)
NEW_NAME="${OLD_NAME} Category"

wp term update category $term_id --name="$NEW_NAME"
echo "Renamed: $OLD_NAME -> $NEW_NAME"
done

Term Meta Management

Add Term Meta

# Add custom field to term
wp term meta add 5 custom_field "custom value"

# Add color to category
wp term meta add 5 category_color "#FF5733"

# Add icon
wp term meta add 5 category_icon "fa-newspaper"

Get Term Meta

# Get specific meta
wp term meta get 5 category_color

# List all meta for term
wp term meta list 5

# Get meta in JSON
wp term meta list 5 --format=json

Update Term Meta

# Update meta value
wp term meta update 5 category_color "#00FF00"

Delete Term Meta

# Delete specific meta
wp term meta delete 5 old_field

Best Practices

1. Plan Taxonomy Structure

# Document your taxonomy structure before creating
# Example: docs/taxonomy-structure.md
# - News
# - WordPress News
# - Industry News
# - Tutorials
# - Beginner
# - Advanced

2. Use Consistent Slugs

# Always specify slugs for SEO
wp term create category "WordPress Development" --slug=wordpress-dev

# Not: wordpress-development (auto-generated, too long)

3. Backup Before Bulk Operations

# Export terms before major changes
wp term list category --format=json > category-backup-$(date +%Y%m%d).json

4. Clean Up Regularly

# Monthly cleanup of empty terms
0 0 1 * * /path/to/cleanup-unused-terms.sh

5. Validate Hierarchy

# Check for orphaned child terms
wp term list category --parent=999 # Non-existent parent

Quick Reference

Essential Commands

# List taxonomies
wp taxonomy list
wp taxonomy get category

# Create terms
wp term create category "Name"
wp term create category "Name" --slug=slug --description="Desc"
wp term create category "Child" --parent=5

# List terms
wp term list category
wp term list category --hide_empty=false
wp term list category --format=csv
wp term list category --field=term_id

# Update terms
wp term update category 5 --name="New Name"
wp term update category 5 --slug=new-slug
wp term update category 5 --parent=10

# Delete terms
wp term delete category 5
wp term list category --hide_empty=false --count=0 --field=term_id | xargs -I {} wp term delete category {}

# Get term info
wp term get category 5
wp term get category 5 --field=name

# Assign to posts
wp post term add 123 category 5
wp post term set 123 category 5 10 15
wp post term remove 123 category 5

# Term meta
wp term meta add 5 key "value"
wp term meta get 5 key
wp term meta update 5 key "new value"
wp term meta delete 5 key

Comparison: WP-CLI vs wp-admin

TaskWP-CLIwp-admin
Create 50 Categories~10 seconds15-20 minutes
Delete Empty Terms~2 seconds10-15 minutes
Bulk Recategorize~5 seconds30+ minutes
Export TaxonomyInstantManual copy/paste
Hierarchy SetupScriptableManual clicking
Visual Organization❌ Text-based✅ Drag-and-drop
Automation✅ Fully scriptable❌ Manual only
Key Takeaway

WP-CLI excels at bulk operations, automation, and migrations. Use it for large-scale taxonomy management. Use wp-admin for visual hierarchy organization and individual term editing.

Next Steps