I am using the transition_post_status to process a post being published. I was getting inconsistent behaviour between two installations of WordPress, and I have tracked this down to the AJAX calls being made from the post compose page itself.

These are the requests being made when I transition a post from a draft to published on my two installations:

enter image description here enter image description here

As you can see, the AJAX call to post.php is not being made in the second example. It turns out that the global $post object is in a different state inside transition_post_status hook when being called via post.php, which is why my code only works on the first installation.

What I need to understand is why I have 2 installations of WordPress that are seemingly doing different things when publishing a post.

Both installations are running 5.7.2, and are stock aside from the 1 plugin that I am working on, which is the same on both installations.

Can anyone shed any light on why two different installations are triggering different AJAX calls when publishing a post?

  • 1
    That screenshot doesn't help much.. And what's your code? Have you also checked the hook reference?
    – Sally CJ
    May 24, 2021 at 20:47
  • My code is irrelevant at this point and these screenshots are the only ones I’m able to provide for the issue I’m trying to solve, which is to understand why two different installations are making different AJAX calls when publishing a post. May 24, 2021 at 21:13
  • Well, there could be many reasons... And if you could inspect the network/XHR requests and check the request and (server's) response data, headers, etc., then I believe you'd get the answer.
    – Sally CJ
    May 24, 2021 at 21:35
  • Well, not really? Inspecting the requests and data and headers doesn't tell me why WordPress didn't even make the second request, does it? The output of the first request is the same on both installations, a JSON response of the post - but this doesn't explain why one installation makes a further request to post.php and the other does not. Do you have anything constructive to suggest other than blindly checking responses and headers for nothing specific? May 24, 2021 at 21:40
  • Something constructive? 1) Share the XHR request/response data (with dummy data being replaced or maybe blurred if sharing a screenshot). 2) Share your code and we might be able to reproduce the issue in question. 3) List the exact steps you took on the post editing screen. 4) Did you use the classic editor or Gutenberg; if not, which installation uses which editor? 5) Did you try with another browser, a new window/tab? So I'm saying, provide as much details as possible and we might come up with a better constructive comments for you.
    – Sally CJ
    May 24, 2021 at 21:52

1 Answer 1


It turns out that the calls to /wp-admin/post.php are due to there being custom meta boxes on the post compose page. The initial XHR request is to the WP API to save the post, but then additional XHR calls are made to process the meta boxes. This then re-saves the post, and calls the transition_post_status hook again.

When the API first saves the post, the status is going from draft to publish, and on the secondary calls, if they run, it is going from publish to publish - that in itself makes sense.

My specific problem was that I was calling some code that required $post to be globalised, which was only the case in the second XHR call, leading to inconsistent behaviour when the hook which called that code was being run twice - one when $post was globalised and one when it was not.

  • "custom meta boxes on the post compose page" - which do not actually exist on a stock setup of WordPress. But I did forget about meta boxes, maybe because that's an old thing just as the admin-ajax.php.. And I'm a bit curious about that "calling some code that required $post to be globalised", but anyway, +1 for your efforts or the helpful findings. 👍
    – Sally CJ
    May 25, 2021 at 14:10
  • Yeah, I hadn't noticed the 1 plugin I had (which was the only non-stock thing) was adding it, and wasn't expecting it to send off a whole other request. The wider issue was I needed to use the global $post in my the_content hook and I returned early if $post didn't exist, instead of returning $content. The meta box XHR request globalised $post so masked this issue in my the_content callback. Is why I was more trying to understand why the post.php request was even being made, as once I knew why that request was there I could figure out what to do with my specific code. May 25, 2021 at 15:23
  • I see. But, "I returned early if $post didn't exist" - I hope you were not referring to something like return;, because the_content filters should always return the content. Also, in the question, you stated that you're accessing the global $post from within the transition_post_status hook, so (I don't know why you need to access that global $post, but) in case you're not aware, the hook actually has a third parameter ($post) which contains the correct data of the post being saved.
    – Sally CJ
    May 26, 2021 at 3:07
  • 1
    Yes, I was just doing return; inside the_content which was the root cause of my issue for the reason you mentioned, however that mistake was masked by the fact $post was globally available inside the_content when the XHR request to post.php was made, as it was globalised before transition_post_status ran, so my the_content code continued on and returned content further on in the code. So it was only due to the post.php request globalising $post that my the_content code ever worked at all, and the bug surfaced when the post.php XHR request wasn't made. May 27, 2021 at 13:03

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.