I am trying to implement a webhook in a plugin which should fire everytime a user saves a post. It works fine, but I recive two requests on frontend api. The first request has got a wrong slug. I wonder why this is happening or what I am doing wrong here. The second call works perfect.

 defined('ABSPATH') or die('Unauthorized access');

 add_action('save_post', 'update_front_end', 10, 2);
 function update_front_end($post_id, $post){

   $exovias_webhooks_options = get_option( 'exovias_webhooks_option_name' ); // Array of All Options
   $secret_0 = $exovias_webhooks_options['secret_0']; // Secret
   $frontendurl_1 = $exovias_webhooks_options['frontendurl_1']; // FrontendUrl

  $slug = basename(get_permalink($post_id));
  $url = $frontendurl_1 . '/api/revalidate?secret=' . $secret_0 .'&slug=' . $slug;


  • 1
    You should probably use the wp_after_insert_post hook instead - just replace the save_post with wp_after_insert_post. I don't guarantee the hook doesn't run twice or more, but with that hook, you should be able to get the correct slug, regardless the post was edited via the block/Gutenberg editor or the classic editor. And why didn't you use the actual post slug, i.e. $post->post_name, and instead, parse it from the post's permalink URL?
    – Sally CJ
    Oct 15, 2022 at 15:00
  • @SallyCJ Thanks a million for trying to help me out. I tried your beautiful solution. Looks and sounds cleaner. But unfortunately the hook is still running twice. And the first run provides a slug of "46-revision-v1" while the scnd provides the correct slug. Oct 16, 2022 at 9:39
  • 1
    I posted an answer, which might help?
    – Sally CJ
    Oct 16, 2022 at 13:09
  • 1
    @SallyCJ This helped a lot. Wonderful. Thanks a million. Now just one request is left. Deep bow concerning your depth of wp knowledge. Oct 18, 2022 at 10:40

1 Answer 1


I wonder why this is happening or what I am doing wrong here

WordPress has a revisions system which stores a record of each saved draft or published update, and a post can have one of a number of statuses like auto-draft when a new post is created and saved automatically in the background, draft (e.g. when the post is autosaved) or publish (e.g. when the publish button is clicked). So the save_post hook (and other hooks like wp_after_insert_post) can run multiple times while editing a post, and thus you should check whether WordPress is doing an autosave and whether the post being saved is a revision, before running your remote HTTP request.

Here's an example which also checks whether WordPress is doing cron (/wp-cron.php) or AJAX (wp-admin/admin-ajax.php), and whether the post status is publish or private:

function update_front_end( $post_id, $post ) {
    $doing_autosave = ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE );

    if ( $doing_autosave || wp_is_post_revision( $post_id ) ||
        wp_doing_cron() || wp_doing_ajax()
    ) {

    if ( in_array( $post->post_status, array( 'publish', 'private' ) ) ) {
        // your code here; define the $url, etc.

        // now run your remote HTTP request
        wp_remote_post( $url );

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.