I try to use this function i have created when a post is published for the first time.

function a_new_post($post){
  $post_id = $post->ID;

  if ( !get_post_meta( $post_id, 'firstpublish', $single = true ) ) {
      // ...run code once
      update_post_meta( $post_id, 'firstpublish', true );
add_action( 'draft_to_published', 'a_new_post' );

I can't see anything wrong with it, but when i try to create some sample posts i check the database and the field "firstpublished" has not been created.

Does anyone see anything wrong?

  • shouldn't you change the hook to publish_post. draft_to_publish won't run for all the cases Oct 19, 2012 at 7:40
  • I tried publish_post and it does not work (wordpress.stackexchange.com/questions/141779/…)
    – user11948
    Apr 21, 2014 at 22:28
  • This is the most frustrating thing I have ever dealt with in WordPress. There is absolutely now way to catch publish and block update. Now way, no how.
    – user11948
    May 1, 2014 at 20:53

2 Answers 2


The correct action is 'draft_to_publish'.

To be sure you used the correct status try to get a list of all registered post statuses (including custom statuses) with:

<pre><?php print '- ' . implode( "\n- ", array_keys( get_post_stati() ) );?></pre>

On a vanilla installation you should get:

  • publish
  • future
  • draft
  • pending
  • private
  • trash
  • auto-draft
  • inherit

Note that publish_post is called each time you edit a published post.

Note also get_post_stati() is one of these unpredictable names in WordPress: it is plain wrong. The plural of the noun status is statuses in English and statūs in Latin. :D

You could also hook into 'transition_post_status', depending on your needs. You get the new and the old status as arguments, the third argument is the post object. It will catch future_to_publish too, and also posts that were trashed once and republished now (trash_to_publish).


add_action( 'transition_post_status', 'a_new_post', 10, 3 );

function a_new_post( $new_status, $old_status, $post )
    if ( 'publish' !== $new_status or 'publish' === $old_status )

    if ( 'post' !== $post->post_type )
        return; // restrict the filter to a specific post type

    // do something awesome

Post First save Time meta value set so easy to apply on first time.

function a_new_post( $post_id, $post, $update ) {
    if ( !get_post_meta( $post_id, 'firstpublish', $single = true ) ) {
        update_post_meta( $post_id, 'firstpublish', true );
add_action( 'save_post', 'a_new_post', 10, 3 );

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.