WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

Is it possible within the save_post action to determine whether it's a new post being created or an existing post being update?

share|improve this question
I don't think this is possible. See my comment below @moraleida's answer. Why do you need to know if it's a new post or being updated? There may be a work-around or an alternative approach. – Stephen Harris Apr 12 '12 at 18:28

Since WordPress version 3.7. - IIRC - the save_post hook - more information about the hook and its usage at Code Reference: save_post and Codex: save_post - has a third parameter $update which can be used to determine just that.

@param     int               $post_ID     Post ID.
@param     WP_Post     $post          Post object.
@param     bool            $update     Whether this is an existing post being updated or not.

share|improve this answer
up vote 6 down vote accepted

I ended up just checking for the existence of a custom value prior to setting it. That way, if it's a newly created post the custom value would not yet exist.

function attributes_save_postdata($post_id) {
  if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;
  if (!wp_verify_nonce($_POST['_attributes_noncename'], plugin_basename(__FILE__))) return;
  if ('page' == $_POST['post_type']) {
    if (!current_user_can('edit_page', $post_id)) return;
  } else {
    if (!current_user_can('edit_post', $post_id)) return;
  $termid = get_post_meta($post_id, '_termid', true);
  if ($termid != '') {
    // it's a new record
    $termid = 'update';
  } else {
    // it's an existing record
  update_post_meta($post_id, '_termid', $termid);
add_action('save_post', 'attributes_save_postdata');
share|improve this answer
For this to work, do you have to first create the custom field using add_post_meta? – MF1 Apr 9 '13 at 2:03
Per the Codex: [update_post_meta] may be used in place of add_post_meta() function. codex.wordpress.org/Function_Reference/update_post_meta – hereswhatidid Jan 20 '14 at 21:46

The way I perform this check (within a hooked function) is to compare the post date and modified date (in GMT for standardisation)

function check_new_vs_update( $post_id ){
    $myPost = get_post($post_id);
    if( $myPost->post_modified_gmt == $myPost->post_date_gmt ){
        //New Post
        //Updated Post
add_action('save_post', 'check_new_vs_update' );

This works because even at creation the post has a 'modified' date attached to it, which is exactly the same as the 'created' date.

share|improve this answer

Example to ialocin answer with "update" paremeter:

function save_func($ID, $post,$update) {

   if($update == false) {
     // do something if its first time publish
   } else {
     // Do something if its update

add_action( 'save_post', 'save_func', 10, 3 );
share|improve this answer

You can use pre_post_update action hook for the update code and save_post for the new post code. It works before a post is updated.

share|improve this answer
save_post hook is fired both when a post is created and updated (after WordPress has saved it to the database). pre_post_update is fired when a post is updated, but prior to the post being updated - this can be important. – Stephen Harris Aug 12 '12 at 18:59

As Darshan Thanki hinted (and Stephen Harris further elaborated), you can use pre_post_update to your advantage.

global $___new_post;
$___new_post = true;

  function() {
    global $___new_post;
    $___new_post = false;

function is_new_post() {
  global $___new_post;
  return $___new_post;

The reason why I used globals is because function is_new_post() use ( &$new_post ) is not valid in PHP (shocking...) so pulling in that variable into the function scope doesn't work -- hence the global.

Note that this can really only reliably be used within/after the save_post event (which is usually sufficient, at least for what we're doing with it).

share|improve this answer

When save_post is triggered, all information about that post is already available, so in theory you could use

function f4553265_check_post() {

    if (!get_posts($post_id)) {
    // if this is a new post get_posts($post_id) should return null
    } else {
    // $post_id already exists on the database

this is untested, though. =)

share|improve this answer
By the time you get to save_post the post itself would have already been saved to database - so get_posts would return the current post. – Stephen Harris Apr 12 '12 at 18:25
True, just checked it in the Codex. Thanks for the heads-up. – moraleida Apr 12 '12 at 18:59

Another approach that uses a built-in function and no addition to the database would involve get_post_status().

$post_status = get_post_status();
if ( $post_status != 'draft' ) {
} else { 
    //not a draft: can be published, pending, etc. 

Note however that it might not be appropriate if you plan to later set the status back to "draft" – your instructions would be repeated the next time you will update the post. Depending on the context, you might want to consider the various strings that can be returned by get_post_status() to build a more appropriate scenario.

See Codex for get_post_status() and Post Status

Possible values are:

  • 'publish' - A published post or page
  • 'pending' - post is pending review
  • 'draft' - a post in draft status
  • 'auto-draft' - a newly created post, with no content
  • 'future' - a post to publish in the future
  • 'private' - not visible to users who are not logged in
  • 'inherit' - a revision. see get_children.
  • 'trash' - post is in trashbin. added with Version 2.9.
share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

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