2

I am running a site where I let users create a profile, which is a custom post type, which is submitted/edited through an ACF front-end form. Everything works as expected, except when users both use the same 'headline' (which is sanitized and used as permalink).

I want the permalink to have the following 'structure': /post-type/city/{post-title}-{post-id}. My thought was to add a post id, so each link would be unique, but I now found out this is not the case.

If I would have 2 profiles: www.domain.com/profile/city/i-am-cool-123 www.domain.com/profile/city/i-am-cool-456

Then www.domain.com/profile/city/i-am-cool-456 redirects to www.domain.com/profile/city/i-am-cool-123.

I knew you can't have 2 the same permalinks, but I might have misunderstood how permalinks are 'registered'.

Below is my code.

First I've added the necessary query vars for the new vars and added custom rewrite tags.

function sd_custom_rewrite_tag() {
    add_rewrite_tag( '%city%', '([^&]+)', 'city=' );
    add_rewrite_tag( '%postname%', '([^&]+)', 'name=' );
}
add_action( 'init', 'sd_custom_rewrite_tag', 10, 0 );

function sd_add_query_vars( $vars ) {
    $vars[] = "city";
    $vars[] = "postname";

    return $vars;
}
add_filter( 'query_vars', 'sd_add_query_vars' );

To get the permalink I want, I have the following code in place.

function sd_new_profile_permalink( $permalink, $post, $leavename = false ) {

    if ( strpos( $permalink, '%city%' ) === FALSE ) {
        return $permalink;
    }

    // Get post
    if ( ! $post ) {
        return $permalink;
    }

    // Get custom info
    $city_info  = get_field( 'sd_city_selector', $post->ID );
    $post_slug  = $post->post_name;
    if ( ! is_wp_error( $city_info ) && ! empty( $city_info ) ) {
        $city_replace  = str_replace( '\'', '', $city_info[ 'cityName' ] );
        $city_replace  = str_replace( ' ', '-', $city_replace );
        $city_slug     = strtolower( $city_replace );
        $new_permalink = str_replace( array( '%city%', '%postname%', '%post_id%' ), array( $city_slug, $post_slug, $post->ID ), $permalink );

        return $new_permalink;
    }
    return $permalink;
}
add_filter( 'post_link', 'sd_new_profile_permalink', 10, 3 );
add_filter( 'post_type_link', 'sd_new_profile_permalink', 10, 3 );

So far nothing weird is happening, this is all doing what it's supposed to do, but now we get down to the issue (I think).

I update the slug through a WPDB action, after the post is submitted, as seen below.

function set_profile_title_from_headline( $post_id ) {

    if ( empty( $_POST[ 'acf' ] ) ) {
        return;
    }

    if ( ! empty( $_POST[ 'acf' ][ 'field_57e3ed6c92ea0' ] ) ) {
        $entered_title = $_POST[ 'acf' ][ 'field_57e3ed6c92ea0' ];
        $cleaned_title = preg_replace( '/[^A-Za-z0-9\-\s]/', '', $entered_title ); 
        $post_name     = sanitize_title( $cleaned_title );
        update_field( 'sd_ad_title', $cleaned_title, $post_id ); 

        global $wpdb;
        $wpdb->update(
            $wpdb->posts,
            array(
                'post_title'  => $cleaned_title,
                'post_name'   => $post_name
            ),
            array(
                'ID' => $post_id
            )
        );

        clean_post_cache( $post_id );

    }

}
add_action( 'acf/save_post', 'set_profile_title_from_headline', 20 );

And then finally I rewrite the url.

function sd_single_profile_rewrite() {
    global $wp_rewrite;
    $wp_rewrite->add_permastruct( 'profile', 'profile/%city%/%postname%-%post_id%/', false );
    add_rewrite_rule( 'profile\/([a-z-]+)\/(.+)-[0-9]+\/?$', 'index.php?post_type=profile&p=$matches[2]&city=$matches[1]&name=$matches[2]', 'top' );
}
add_action( 'init', 'sd_single_profile_rewrite' );

Basically my question is: Is there a way to 'do' what I want to do ? And if so, how :)

  • You should check if there is a redirect, and if there is which part of the core code is responsible for it. In addition did you save your permalinks? Did you actually verify that the rewrite rules are actually there? – Mark Kaplun Feb 14 '18 at 6:00
  • If I am understanding his goal, he wants /foo/this-is-a-slug/ and /bar/this-is-a-slug/ to direct to different posts. And I don't think that is practically possible. – Slam Feb 14 '18 at 8:37
  • Possible duplicate of wordpress.stackexchange.com/questions/7807/… – Slam Feb 14 '18 at 8:39
  • @MarkKaplun how to check for redirect ? Yes permalinks were saved. I checked with Monkeyman rewrite analyzer and it showed nothing unexpected.. Slam you are misunderstood. Has nothing to do with taxonomy. – Beee Feb 14 '18 at 15:06
  • you can just check the developer tools of the browser to see if the first response is a redirect (probably 302), or check the server log. If still not it, try to use the query monitor plugin to get a better idea which rewrite rule matches and with which parameters – Mark Kaplun Feb 14 '18 at 15:11
2

I was thinking too 'difficult'. Instead of rebuilding a new permalink structure I could have easily updated the new permalink the way I want to have it.

So I deleted the entire rewrite part and changed the query in acf/save_post to the following:

if ( ! empty( $_POST[ 'acf' ][ $ad_title ] ) ) {

    $entered_title = $_POST[ 'acf' ][ $ad_title ];
    $cleaned_title = preg_replace( '/[^A-Za-z0-9\-\s]/', '', 
    $entered_title ); // Removes special chars.
    $post_name     = sanitize_title( $cleaned_title );
    $city_name     = get_field( 'sd_city_search_value', $post_id );
    $new_slug      = strtolower( $city_name ) . '-' . $post_name . '-' . $post_id;

    // update acf field
    update_field( 'sd_ad_title', $cleaned_title, $post_id );

    // update post status + post title (if needed)
    global $wpdb;
    $wpdb->update(
        $wpdb->posts,
        array(
            'post_title'  => $cleaned_title,
            'post_name'   => strtolower( get_field( 'sd_city_search_value', $post_id ) ) . '-' . $post_name . '-' . $post_id
        ),
        array(
            'ID' => $post_id
        )
    );

    clean_post_cache( $post_id );

}
-1

Are /i-am-cool-123 and i-am-cool-456 actually two different posts?

If so then sure you want two different permalinks.

But your use case sounds like you have one post and you want to track visits from different pages on your site. In which case you might want to add UTM codes to the ends of you URLs to track them.

Edit: I think you mean you'd have two profiles... but in different cities? The i-am-cool-123 part is the post name and they must be unique. There doesn't seem to be a point in creating an i-am-cool-234 and redirecting it to i-am-cool-123 because no-one would be able to visit the content at i-am-cool-234 — clicking that link would take you to i-am-cool-123.

The part before the post_name, the rest of the URL... doesn't matter. red/apples and yellow/apples both would normally go to the post named apples. The path is generated by Wordpress and multiple paths can go to the same post (which is why for SEO purposes it's a good idea to define a canonical URL).

You might be able to make a custom permalink that parses the path. Maybe yellow/apples redirects to yellow/apples-yellow and red/apples redirects to red/apples-red, but your rewrite would need to grab something from the path to extract and put at the end of the post name. Sounds like a PITA.

But nothing stops you from having the same post titles. /i-am-cool-123 and i-am-cool-456 would both appear in the URL, but the title of both pages would still be I Am Cool.

  • This do not actually answer the question, it is more like a very long comment. – Mark Kaplun Feb 14 '18 at 6:02
  • It was an answer and then I realized I didn't understand the question correctly. Then it became more of a comment. I'll delete it if I'm still not understanding the OP's goals. – Slam Feb 14 '18 at 8:33
  • basically the OP wants a URL structure like it is here, part name, part numerical ID. The reason is to automatically generate a unique slug without enforcing a unique title, but still have the title part of the URL for SEO – Mark Kaplun Feb 14 '18 at 8:43
  • I think you have worded it correctly @MarkKaplun. The slug is taken from a (sanitized) user inputted acf field, as is the city. I added the post ID since I (incorrectly assumed) it would create a unique URL because I already expected some users to use the same headline. I'm open to any solutions/suggestions, but ideally I want to create a unique URL so two profiles can have the same headline. edit it just hit me... since I already change the post_name. Can't I easily add the post id there ?? – Beee Feb 14 '18 at 13:47
  • btw SEO is not involved here. I just like pretty links without the -2 addition ;) – Beee Feb 14 '18 at 13:55

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.