I've a CPT (lets say Event) with a custom date field (start_date). I'm trying to generate the post slug (post_name) as start_date + post_title (separated by -).

I've tried using the filter wp_unique_post_slug as well as wp_insert_post_data to modify post_name. When I publish the post, the slug gets changed internally but it doesn't reflect on admin UI. Only when I refresh the page (edit the post again) the new slug gets displayed properly.

What could be the reason and how do I ensure that the generated slug gets displayed immediately when I publish the post?

One observation: wp_unique_post_slug filter is invoked 4 times when I publish the post. Out of the 4 invocations only 3rd invocation gets the any data in $_POST and in turn the logic for editing the slug gets executed only during 3rd invocation.

Here is the code sample that I'm using, if that helps:

public function cpt_unique_post_slug( $slug, $post_ID, $post_status, $post_type, $post_parent, $original_slug ) {
    if( ! in_array($post_type, array('Event', 'CPT2') ) ) return $slug;

    error_log(var_export($_POST, true));

    if(isset($_POST['start_date'])) {
        // remove any date from post slug
        $slug = preg_replace( '/^\d{4}-\d{2}-\d{2}-/', '', $slug );
        $slug = $_POST['start_date'] . '-' . $slug;

    return $slug;

I guess you are using Gutenberg in which case this is non-trivial problem.

Gutenberg saves post data in two steps (two separate http requests, just use developer tools in your browser to check). First, using REST API it saves Gutenberg-ready fields including title, content and slug. Problem is, REST API uses JSON and $_POST is empty array during this save action, so your wp_unique_post_slug hook runs but does nothing. Moreover, metabox/custom field values are not even sent in this JSON request.

Then Gutenberg does another POST request to save other fields, which include old-style metaboxes and Custom Fields. This time $_POST values are available, so your hook is able to update slug value. However this is too late for Gutenberg to change visible slug value in admin interface, as it was done during first request.

This is interesting problem for me, as I had similar use cases in past, but those sites are still using Classic editor. No time for complete solution now, but I would try to create Gutenberg block for your start_date field, set it to store value as meta fields (default for blocks is save inside content field) and add it as mandatory block for your Event CPT, and then try to hook wp_unique_post_slug during REST API call. Just don't forget, that you don't have $_POST values and should use $request object provided by REST API to get start_date. A lot to learn about Gutenberg blocks and REST API.

| improve this answer | |
  • 1
    Thanks for the guidelines. Will take a look at Gutenberg blocks. +1 for now. – Vivek Athalye Jan 20 at 15:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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