I have a custom post type "Product" and want to create a post category "A Product Name" automatically on creation of a new Product so that the post category (not custom post category) would have the same name as the new Product and so that all relevant posts could be linked to the custom post type.

I was trying to hook into the wp_publish_post but apparently it has been renamed to {$new_status}_{$post->post_type} so I imagine the tag would be publish_product?

    // adds category with name of product automatically
add_filter( 'publish_product', 'my_publish_product' );

function my_publish_product( $post ) {
    global $wpdb;
    $post_type = 'product'; 

    if ( ! $post = get_post( $post ) )

    if ( 'publish' == $post->post_status )

    $wpdb->update( $wpdb->posts, array( 'post_status' => 'publish' ), array( 'ID' => $post->ID ) );

    clean_post_cache( $post->ID );

    $old_status = $post->post_status;
    $post->post_status = 'publish';
    wp_transition_post_status( 'publish', $old_status, $post );

    /** This action is documented in wp-includes/post.php */
    do_action( 'edit_post', $post->ID, $post );
    /** This action is documented in wp-includes/post.php */
    do_action( "save_post_{$post->post_type}", $post->ID, $post, true );
    /** This action is documented in wp-includes/post.php */
    do_action( 'save_post', $post->ID, $post, true );
    /** This action is documented in wp-includes/post.php */
    do_action( 'wp_insert_post', $post->ID, $post, true );

    if ( 'post' != $post_type ) {
    } else {
        add_action( 'wp_insert_post', 'my_wp_insert_post($post->post_name)' );
function my_wp_insert_post( $post_name )
    $my_cat = array(
  'cat_ID' => 0,
  'cat_name' => $post_name, 
  'category_parent' => 'products',
  'taxonomy' => 'category' 


I'm not terribly adept at using hooks and filters so apologies if this is all wrong or makes no sense.

2 Answers 2


You are way off, if you say that wp_publish_post() has been renamed to {$new_status}_{$post->post_type}. The latter actually is a hook, while the former is a function. Where the latter is part of the former, because it's part of wp_insert_post.

The hook {$new_status}_{$post->post_type} is part of wp_transition_post_status() - additionally see the source. You might want to take a look at the codex article about the Plugin API to learn more about hooks in general. Additional specific information regarding hooks applicable when publishing, saving and so on posts - or post types - can be found at the entry about Post Status Transitions, besides above linked wp_transition_post_status(); and - as always - the source.

Regarding the code you posted, there should be no need to do my_publish_product() - or at least none that can be seen from your code. Your posts from the post type product are getting created, saved, updated and so on just fine I imagine.
You can just hook my_wp_insert_post() directly to the hook most suitable for your needs, following your code the wp_insert_post filter. Which is part of the wp_insert_post() - source - and the wp_publish_post() - source - function. Last but not least take a look at the usage of add_action().

Below code exemplary outlines how to do it:

add_action( 'wp_insert_post', 'my_wp_insert_post', 1, 3 );
function my_wp_insert_post( $post_id, $post, true ) {
    //your code
  • 1
    @PieterGoosen thanks, I guess »give a man a fish and you feed him for a day; teach a man to fish and you feed him for a lifetime« applies here :) May 20, 2014 at 12:45
  • @mantis my pleasure, that was the intention May 20, 2014 at 12:46
  • @ialocin posted my corrected version. Cheers for the fishing lesson ;)
    – mantis
    May 20, 2014 at 13:22
  • @mantis we all have to eat, right? :) one more thing, can please add the solution you came up with as answer - thanks! May 20, 2014 at 13:25
  • Certainly, I added it below the question but am happy to move it.
    – mantis
    May 20, 2014 at 13:26

Based on @ialocin 's answer:

add_action( 'wp_insert_post', 'my_wp_insert_post', 1, 2 );

    function my_wp_insert_post( $post_id, $post ) {

        $title = $post->post_title;
        $post_type = $post->post_type;
        $post_status = $post->post_status;

        // Only do this for published products 
        if ( 'product' != $post_type ) {
         } elseif ('publish' != $post_status ) {

          $my_cat = array(
              'cat_name' => $title, 
              'category_parent' => 3, //cat id of all products
              'taxonomy' => 'category' 

          wp_insert_category( $my_cat );
  • I did a little bit of code optimization, the get_post() call was unnecessary, because the $post object is already available. May 20, 2014 at 13:50
  • Thank you, I thought so but couldn't get it to work right without it as I was trying to add $wp_error (true) as well.
    – mantis
    May 20, 2014 at 15:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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