The WordPress Hook That Only Fires Half the Time
A plugin cache watcher instantiated only on is_admin() or wp_doing_cron(). Fine, until every post on the site started arriving over the REST API instead.
The Dog Habit publishes automatically — a scheduled job researches a topic, writes the piece, generates an image, and posts it through the WordPress REST API. No editor ever opens wp-admin. That is the entire point of the pipeline. It is also exactly the assumption a popular SEO plugin did not expect anyone to break.
The plugin caches the generated sitemap XML to disk and rebuilds it when a post changes — sensible, standard behaviour. What we found, days after the automation had been running cleanly, was a sitemap frozen at roughly half the actual post count. New posts were live, correctly formatted, fully indexed on the site itself. They just never made it into the file search engines were told to trust.
Reading the plugin instead of guessing
The cache-invalidation watcher — the class that listens for a new post and clears the stale sitemap — is only constructed under one condition, buried in the module's bootstrap:
if ( is_admin() || wp_doing_cron() ) {
new Cache_Watcher();
}Reasonable for how WordPress is normally used: a human publishing through wp-admin, or a scheduled WordPress-internal job. A request to the REST API is neither. It is not an admin screen, and it is not WordPress's own cron system — it is an ordinary HTTP request from an external script, indistinguishable to this check from a visitor loading the homepage. The watcher was simply never in the room.
The fix, and why it was one hook, not a plugin change
Editing the plugin was the wrong move — an update would overwrite it silently. Instead, one small must-use plugin listens for the WordPress core hook that fires after any REST-created or REST-updated post, regardless of who is making the request, and calls the sitemap cache's own invalidation method directly:
add_action( 'rest_after_insert_post', function ( $post ) {
if ( class_exists( 'RankMath\\Sitemap\\Cache' ) ) {
\RankMath\Sitemap\Cache::invalidate_storage();
}
} );Verified by firing the exact same core hook manually and watching the stale cache files disappear on the spot — then confirming the sitemap was current after the very next scheduled publish, with no further intervention.
A gate that reads "is a human doing this, or is WordPress doing this to itself" has a blind spot exactly the size of "an API doing this on a schedule" — which is precisely what an autonomous pipeline is.
This came out of building The Dog Habit — Read the case study ↗
Have something like this to fix?
Describe the problem and we will tell you what it takes.
Get in touchAll posts