I'm trying to convert a bunch of posts within a CPT to items within a Custom Taxonomy, where the post titles become the taxonomy names and the post content becomes the taxonomy descriptions. I have the below code (also here) in a plugin but am not sure where to add my CPT and Tax names. Or if the code will fire properly from within the plugin. Any ideas?

 * Create slugs/terms in jjm_author_tax taxonomy for all jjm_authors posts
function make_taxonomy_from_posts($post_type, $taxonomy){
   // Get all posts
   $query_posts = query_posts(array(
                             // ... of the requested type
                             'post_type'=> $post_type,
                             // ... and it supports the taxonomy
                             'taxonomy' => $taxonomy,
                             // ... without limit
                             'nopaging' => true,

  // Reset the main query

  foreach ($query_posts as $query_post) {
      $post_id = $query_post->ID;
      $raw_title = $query_post->post_title;
      // Generate a slug based on the title.
      // We want to check for auto-draft so we don't create a term for a post with no title
      $slug_title = sanitize_title($raw_title);

      // Do the checks for empty titles
      // If the title is blank, skip it
      if ($slug_title == 'auto-draft' || empty($raw_title)) continue;
      // Get all of the terms associated with the post
      $terms = get_the_terms($post_id, $taxonomy);
      $term_id = 0;

      if (!empty($terms)) {
           $term_id = $terms[0]->term_id;

     if ($term_id > 0) {
          // If the post has a term, update the term
          wp_update_term($term_id, $taxonomy, array(
                                               'description' => $raw_title,
                                               'slug' => $raw_title,
                                               'name' => $raw_title,
     } else {
         // Otherwise add a new term
         wp_set_object_terms($post_id, $raw_title, $taxonomy, false);
  • 2
    You shoule never user query_posts(). Instead use get_posts() or create a custom query using the WP_Query class.
    – David Gard
    Feb 18, 2015 at 15:33
  • Thanks David. This only runs once so maybe using query posts isn't the end of the world. But I'm still not sure where to plug in my CPT and custom tax names.
    – Josh M
    Feb 18, 2015 at 15:58
  • 1
    This should work just fine. It converts all posts within a post type (without caring if one with the same name existed before). gist.github.com/4b163188440a3785d004
    – circuuz
    Feb 18, 2015 at 16:01
  • 1
    It's always the end of the world to use query_posts(). Maybe even the universe... But anyway, see my answer below and comment on it if you need further help.
    – David Gard
    Feb 18, 2015 at 16:02

2 Answers 2


Here's the solution that worked for me. I added the below code to a page template (page-test.php) and then created a page called "test," loaded the page, and all the CPTS were converted to taxonomies. Not sure if this happened when I created the page or when I loaded it... And then I quickly deleted the page template so I didn't end up with a bunch of duplicates.

    function cpt_to_tax($post_type, $taxonomy) {
    $posts = get_posts(array(
                 'post_type' => $post_type,
                 'posts_per_page' => -1,
    foreach($posts as $post) {
        wp_insert_term($post->post_title, $taxonomy, array(
                'description' => $post->post_content,

    cpt_to_tax('jjm_authors', 'jjm_author_tax');

The solution itself was provide by https://wordpress.stackexchange.com/users/35470/circuuz, though his post seems to be deleted now. :(

  • That's basically the same as my answer, except it users get_posts().
    – David Gard
    Feb 18, 2015 at 17:04
  • I tried your answer in functions.php and it wasn't working, not sure why. But, like the above, it might have worked if I had added it to page template. I'd test it but then if it worked I'd have to delete 462 duplicate tags. :(
    – Josh M
    Feb 18, 2015 at 17:09
  • My answer doesn't create duplicate tags. Plus, you must at the very least take a back up when doing things like this, and really it's better to test it off line - just in case...
    – David Gard
    Feb 19, 2015 at 9:32
  • Of course I had a backup, and all of this was happening on a local machine long before launch of the live site. Also, your code had all sorts of syntax errors, which I started fixing but then decided to give the other answer a shot.
    – Josh M
    Feb 19, 2015 at 12:29
  • "your code had all sorts of syntax errors" - LOL, I found that I had accidently placed a semi-colon at the end of the wrong line. It was literally a 3 second fix. Other than that, the code is tested and works 100%. If you don't want to use it, fine, but if you do you don't have to worry about duplicates because my code will not create any.
    – David Gard
    Feb 19, 2015 at 14:15

First we create a new custom query containing all published posts of type $post_type, which you pass to the function. If you don't just want published posts you can pick and choose the status' that you require - see this part of the WP_Query Codex.

Next we use The Loop to loop through the resultant posts and for each check if the post name exists as a term within $taxonomy (which you also pass to the function) using term_exists(), and if not, we add it using wp_insert_term(). Using this means that we only have to pass the name and description, while the slug will be automatically created based on the name.

Finally, just before exiting The Loop we reset the global $post using wp_reset_postdata()

Place this entire code block into functions.php in the order that it is on here. While you can just leave this code to run on every page load (duplicate category names will not be created), it's recommended for permormance reasons and you should ensure that you comment the call to add_action() when you are done.

add_action('init', 'init_make_taxonomy_from_posts');
function init_make_taxonomy_from_posts(){
    make_taxonomy_from_posts('jjm_authors', 'jjm_author_tax');

 * Create slugs/terms in jjm_author_tax taxonomy for all jjm_authors posts
function make_taxonomy_from_posts($post_type, $taxonomy){

    /** Grab the relevant posts */
    $args = array(
        'post_status'       => 'publish',
        'post_type'         => $post_type,
        'posts_per_page'    => -1
    $my_query = new WP_Query($args);
    /** Check that some posts were found and loop through them */
    if($my_query->have_posts()) : while($my_query->have_posts()) : $my_query->the_post();
            /** Check to see if a term with the same title as the post currently exists in $taxonomy */
            if(!term_exists(get_the_title(), $taxonomy)) :   // It doesn't
                /** Add a new term to $taxonomy */
                $args = array(
                    'description'   => get_the_content()
                wp_insert_term(get_the_title(), $taxonomy);
        /** Reset the '$post' global */




This code is tested and 100% working.

  • David, am I replacing @post_type and $taxonomy with my custom post name and taxonomy name throughout? And if I put this in a plugin, will it fire when I activate the plugin? Or does it have to be in a theme function file?
    – Josh M
    Feb 18, 2015 at 16:08
  • 1
    No, call the function using the - make_taxonomy_from_posts('jjm_authors', 'jjm_author_tax');. I'll update the answer to include this. Also, you can fire it in a plugin, but from now I'd recommend placing it in functions.php.
    – David Gard
    Feb 18, 2015 at 16:10
  • I don't think I'm adding make_taxonomy_from_posts('jjm_authors', 'jjm_author_tax'); correctly. Does that go on a line by itself AFTER the main function?
    – Josh M
    Feb 18, 2015 at 16:32
  • I've updated my answer, specifically on how to call the function. I assumed you'd know to wrap the call in a function and call via a hook. Hope it helps.
    – David Gard
    Feb 18, 2015 at 17:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.