Saw a post over on the WordPress Stack Exchange site a while back, and though I sorta went into it in my answer there, I figured it would make a decent topic.

Custom taxonomies are great. But they’re not great for everything. When designing a custom solution, it’s helpful to understand this in advance, so you can choose what goes where properly.

What is a Taxonomy?

According to Wikipedia, Taxonomy is the practice and science of classification. I like this definition a lot, because it really points out what you’re doing with taxonomies. You’re classifying things. Or better yet, grouping them.

That word is important: Grouping. You’re putting things into groups. The taxonomy is the sum of those groups.

In the case of WordPress, you’re putting posts into groups. Maybe they’re custom post types of some kind (actually, they probably are if you’re doing it properly), but they still fit into the wp_posts table, so lets call them posts. You’re grouping posts together.

Categories group posts together. Tags group posts together. The way that these two are used is somewhat different, but that’s the basic end result here, right?

The group itself is the important bit. Not the term, the term you use for that group is just a label. It has no real significance whatsoever.

Now, I know that we often display the term, and I think that this is what confuses people. The category or tag is probably a word, in English (or your own language), and words have meaning. So yes, it does matter when I add “php” as a tag, or use the “Rants” category. But what’s important to realize is that that word only has meaning to people, not to the computers, and certainly not to our data design.

Enter Postmeta, Stage Left

Let’s say I’m building a new site, and I want to make, say, television shows be a custom post type. TV Shows are a pretty good choice for this example, as well as what the original SE question was about.

What makes sense as a taxonomy for a TV Show? Title? Actors? Episode numbers? Season numbers? For each item, you need to consider whether it makes more sense as a taxonomy or as pure post meta, or (rarely) both.

Titles makes perfect sense for a taxonomy. You’re grouping all the episodes of that show together, and people will want to see an episode listing. So yes, it’s a taxonomy.

Actors also makes sense as a taxonomy. Actors act in many roles, it would be nice to see what various shows and episodes they’ve been in.

Season and Episode numbers is another one. Every show has it’s own season and episode number. Usually this is represented as Season 1, Episode 1, sort of thing. At first glance, season numbers kinda makes sense as a taxonomy, since you can pull all of season 1 out. But on further reflection, no it doesn’t, because it doesn’t stand alone. Every TV series has a season 1. We don’t want to pull out all season 1 shows from all series, it’s not something we’ll need to do. Same goes for episode numbers, when are we going to make a query based on episode numbers, to get all the first episodes of all shows? Makes no sense. These should be postmeta (or “Custom Fields” as some people insist on calling them).

The difference is one of grouping. For Titles and Actors, we’re grouping individual things together in a meaningful way that stands alone. Sure, our labels (terms) will have meaning to us humans, but not to the act of the grouping itself. The group is a natural one. For seasons, the grouping is meaningful, but less so because it’s shared among non-similar things (different shows). It doesn’t stand alone. You could get around that by saying that your term would be title-season# or similar, but it really makes more sense as postmeta, since the season and episode number, taken together, are unique to the item we’re storing.

Postmeta as Unique Information

That’s the difference: Postmeta is bits of information that are specific to the post item itself. Taxonomies are bits of information shared, in a meaningful manner, by many different items. Title is shared across all episodes of a TV Show, and defines a meaningful relationship to all those episodes. Season number is shared, but it’s not meaningful because all shows have similar season numbers.

Notably, there’s easy ways to order by postmeta, but not by a taxonomy. Ordering by a taxonomy makes no real sense, because lots of items will share the same terms in that taxonomy. If I have 20 items all with “foo” as a term in a taxonomy, then what am I ordering them by? They’re all “foo” items.

As for querying, I can query based on either postmeta or taxonomy, if I really want to. Ideally, I’d do both. For example, if I wanted Firefly, Season 1, Episode 13, then I could specify both a tax_query for title and a meta_query for “S01E13″ and get that one unique item. If I wanted all episodes of it in order, then I specify the tax_query for title and the meta query to select the season/episode metadata, then use the orderby to put them in the right order.

Choose Wisely

So if I can query by them both, but only order by postmeta, then what’s the difference? Why not use postmeta for everything?

Speed. Querying for a taxonomy is loads faster than querying for posts with certain meta information. Even better, I can use both to make things even speedier. The meta_query for S01E13 is going to be loads faster when I specify that title taxonomy, because now it’s only looking for S01E13 amongst Firefly episodes, not amongst all episodes of all shows.

The bottom line is that it’s best to use a taxonomy for attributes that a) define a natural grouping of your items, and b) which are natural labels and not inherently useful data to your methods. The title is not inherently a useful data (it’s just text, could be anything), but the episode number is a number which you will want to order by and display/change/set. You use that episode number for doing something.

Also, it’s perfectly understandable for individuals to disagree on any given example. There is no “right” answer, there’s only the answer that satisfies your own personal use cases. When designing your taxonomies, just remember to think about grouping of items and how you’re going to use the data you’re defining. If it’s a group in how you are going to use it, then a taxonomy works better than postmeta. But if you need the attribute to be manipulated in some manner, then a postmeta works better.



  1. Hi Otto,
    thanks for the great post – this has cleared up a fair bit of my confusion about taxonomies.
    It also made me rethink my approach about a specific case though, and I’d love to hear your opinion on it:

    I’m working on a website for a community radio station and am trying to create a list of shows and a schedule.
    My current approach is a custom post type (CPT) “shows”, a CPT “schedule”, a taxonomy (TAX) “frequency” and a hierarchical TAX “genre”. So a show could be classified as “weekly” and “music”->”world”,”jazz”,”funk”.

    A schedule entry would require to choose the show name and contain postmeta for start and end time in addition to a description field for the show’s “episode”. In order to choose the show name I was intending to use Scribu’s Posts2Posts plugin.

    Your post made me think whether I should rather use a show TAX to group schedule entries together (but then that’d either mean creating a TAX and a CPT for every show, or maybe using something like (scrapping the “shows” CPT altogether).

    What would be your approach in a case like this?


  2. You appear to be describing a database system, as opposed to a blog.

    Is this dBase IV we’re talking about, or WordPress?

  3. Well, main problem is people reaching taxonomies more easily then custom meta boxes etc, you know. When we have a core meta box system like CCK or something, people will use it rather then taxonomy imo.

  4. Thanks.

    I’m the guy that asked the question :) Thank you for your help and advice.

    Enjoy the beer ;)

  5. Thank you so much for this post Otto, it’s just the thing I’ve been looking for regarding Taxonomies vs Postmeta.

    Here’s an idea I’ve got for being able to order by a taxonomy:

    Can you have a taxonomy term ALSO entered in as postmeta? I’m sure there’s probably some way to automate that, but taking from your TV shows example, yes every TV show has an Episode 1. So it makes sense to keep that as postmeta for ordering the episodes chronologically per each season.

    However I could see cases where maybe you also want to query every Episode 1 from Season 1 of each TV show. Maybe somebody wants to check out all the pilot episodes… that doesn’t seem too out of the question to me. You’d then want to have a taxonomy for episode number in that case for easy querying.

    Of course I guess this would only work with a taxonomy where you select/enter only 1 term. Otherwise I don’t think it would make sense.

    Another example is I’m working on a Pokemon card database site. One piece of data I’m working with is the card name. I’d like to allow the user to sort cards alphabetically, so in that case it’s good to have the card name be postmeta.

    But I can also see instances where a user might want to view all the Pikachu cards ever made (so card name = Pikachu). It would be easier to query if I ALSO had a Card Name taxonomy (non-hierarchal, only 1 term added for each post).

    So I think there are a lot of cases where it could be good to have both postmeta and taxonomy term for certain items… what do you think? Any disadvantage to doing that rather than making complicated query/sorting functions?

  6. Hey Otto, quick thanks for a clear breakdown of this topic. Really made it understandable. I would buy you a beer but alas, at the time of this writing, it is now an empty glass.


  7. Thanks Otto. Very helpful.

    I’m working on geo websites at the moment that each cover one UK county. I’m using a place taxonomy structure to group villages round major towns to form local mini sites within each county. Meanwhile I’m using categories to describe types of entity (eg attractions, types of business), so giving two dimensions to the data.

    Once again, thanks…

  8. Indeed great article and agree taxonomies are a great way to manage everything in the WordPress. While there are more to improve for recently implemented taxonomies (since 3.0) here is a great tool to help you order all terms for a given taxonomy, either by custom drag and drop or automatically by title, date, id, count, random etc Advanced Taxonomy Terms Order some of you might find this very useful as it already helped me allot.

  9. Great article. Have been trying to get an understanding of the relationship between taxonomies and custom posts – very helpful

  10. i think i have been looking for exactly this. i have a taxonomy that i’ve limited to only 3 terms and have created my own tax metabox to make sure that a post can only ever have 1 value: featured, normal or excluded. it struck me that this is sort of post_meta territory but if querying by tax is significantly faster i think i will leave it as is.

  11. Hi Otto, I’m coming back to your post months later. :) i still think there is a valid reason to sort by taxonomy. What if you have a post type “Articles” with a “subject” taxonomy and you wanted to show all the articles grouped by subject

    Apple Subject
    apple article 1
    apple article 2

    Bacon Subject
    bacon article 1
    bacon article 2

    and so on. the subject taxonomy is still a ‘grouping’ of articles, where the terms are shared across more than one article. do you think this is possible with enough magic thrown at the posts_join and posts_orderby filters?

  12. thanks for this post. in summary – taxonomy = groupings vs postmeta = unique

  13. iam confused what is the different now between custom fields and tags???

  14. thanks for the post. your approach is really clear and helpful

  15. Thanks for that Otto.

    So it can come down to the basic idea: CF = manipulate the data and CT = querying/listing the data.

    Let’s just say I need to use the data in both ways (manipulation AND querying)… what would you recommend if you HAD to choose ONE method. CFs or CTs?

    Cheers, Pete

Leave a Reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Need to post PHP code? Wrap it in [php] and [/php] tags.