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 categoriesproduct_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
| Task | WP-CLI | wp-admin |
|---|---|---|
| Create 50 Categories | ~10 seconds | 15-20 minutes |
| Delete Empty Terms | ~2 seconds | 10-15 minutes |
| Bulk Recategorize | ~5 seconds | 30+ minutes |
| Export Taxonomy | Instant | Manual copy/paste |
| Hierarchy Setup | Scriptable | Manual 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
- Manage posts: Post Management
- Handle comments: Comment Management
- Learn database operations: Database Management