I can't seem to find a solution for this. I have found the save_post hook but this fires after the post is saved to the database.

I have an appointments custom post type and what I want to do is validated some stuff before the post is created, other wise if it fails the validation disregard creating the post.

Is there a hook similar to save_post but instead of firing after creating post, it fires before creating the post. Maybe something like before_save_post

4 Answers 4


Yep, it looks like there is no option how to stop post saving. I am checking wp-includes/post.php, and all I see is wp_insert_post_data filter where you can check and modify post data (before saving), but that's all.

Or ... you can hook to save_post, and if there is something wrong with the post, then call wp_delete_post() and remove it right away :-)


If you want the user to know his post has some problem, the validation should be done in JS.

Once the user posted the post, user expects it to be stored on the server but the side effect of posting is that the page is reloaded and if the data wasn't saved due to validation, how will the user know what was his content that was rejected as the reload will probably show old content.

If you don't think JS based validation is enough for your use case, you can implement a server side one that does two things

  1. prevent the post status from being set to published
  2. show error message using the WP error API by validating before the post is being editted.

but this should be in addition to JS validation, not instead of it.


Here is a very basic and crude way to achive what you need.

I sometimes use this myself for quick validations, helps the client not miss anything important.

I created the same custom post type slug so the css/js targets would be as similar to yours.

Once you get the concept, change this how ever you need. Move css and js code to proper files, add relevant comments, you have alot of room to do what you need.

add_action('admin_footer', 'bt_before_submit_validation');
function bt_before_submit_validation () {
    .post-type-appointments .custom-error {
        padding: 10px;
        box-sizing: border-box;
        display: block;

    .post-type-appointments #publishing-action {
        position: relative;
        width: 100%;

    .post-type-appointments #publishing-action .vbs-btn {
        width: 100%;
        height: 100%;
        position: absolute;
        z-index: 1;
        top: 0;
        left: 0;

($ => {
    // add facade submit button
    // This button will be used to trigger validation before submit
    // (change "Validate and Publish") to what ever you want
    $('.post-type-appointments #publishing-action [type="submit"]').before('<button type="button" class="vbs-btn button button-primary">Validate and Publish</button>');

    // now that we have a button we can use it to start validating
    $(document).on('click', '.post-type-appointments #publishing-action .vbs-btn', e => {
        // we will do a basic validation for title

        const $this = $(e.currentTarget);

        // remove all previous errors

        // will indicate if validation was successful
        // by default we assume everything is good, once we encounter a problem we will change this to false
        let isValid = true;

        // get the elements
        const $title = $('[name="post_title"]');

        // get the value
        const titleVal = $title.val().trim();

        // validate title field
        if (!titleVal) {
            isValid = false;
            $title.after('<span class="custom-error notice notice-error">Title field cannot be empty</span>');
        } else if (titleVal.length < 10) {
            isValid = false;
            $title.after('<span class="custom-error notice notice-error">Title field must contain at least 10 characters.</span>');
        } // continue adding as many validations as needed

        // validation faild, return
        if (!isValid) return;

        // everything is ok, lets continue
        // trigger click on submit button

        // remove the facade button, this is optional

If something doesn't work, make sure to check the css/js targets.

Everything was tested on a new wordpress install with the cptui plugin in order to create the appointments post type


You can use wp_insert_post_empty_content filter to bypass post save/update. More info https://developer.wordpress.org/reference/hooks/wp_insert_post_empty_content/

  • 1
    While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - From Review
    – cjbj
    Commented Oct 14, 2022 at 7:22

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.