Open cr101 opened 6 years ago
Does WordPress do this? I've always had to use the redirection plugin to achieve this functionality.
@TylerBarnes WordPress redirects old post permalink slugs automatically out of the box. To test it, first deactivate the redirection plugin, then create a new post, publish it and then view it. Then change the post's permalink slug to something else, save the post and then refresh the post and you will notice that WordPress has automatically redirected you to the new link.
WordPress saves the old post slug in the wp_postmeta
table in the _wp_old_slug
field.
I've been working with WordPress for years and I've never heard of that redirection plugin.
Weird, I just tried it and all I get is a 404. Do I have to enable something in functions.php to make it work?
@TylerBarnes no need to add anything.
Hmm, I tested it on a few sites I've already built as well as a fresh install with the 2017 theme and it doesn't do it on any of them. I do see that it's referenced on a lot of sites on google but I can't find anything in the wordpress docs about it which is weird. Anyway I found your issue on gatsby. It seems like it would be pretty easy to set this up using your plugin + a little bit of logic.
I've been looking into this and learned WordPress redirects post slugs if you make an API request using ?filter[name]
:
/wp-json/wp/v2/posts?filter[name]=sample-post
But, it doesn't redirect when you use ?slug
:
/wp-json/wp/v2/posts?slug=sample-post
This seems like an upstream bug... The issue is compounded by the fact that this project uses a custom route for posts, /wp-json/postlight/v1/post?slug=sample-post
and that route requires ?slug
.
Ultimately, this project should abandon the custom post routes & use the built-in routes with ?filter
to handle redirects automatically.
ETA Actually I had forgotten filter
depends on the plugin wp-rest-filter
since 4.7, so that will introduce another dependency. I'll try to find a way to make this work without the plugin first.
See also https://github.com/WP-API/WP-API/issues/1776 & https://github.com/WP-API/WP-API/issues/576
@TylerBarnes The permanent redirect occurs in wp_old_slug_redirect()
which is in query.php
First of all, I was incorrect thinking filter
would redirect - my test was invalid, neither filter
nor slug
redirect in the vanilla WP API.
After reading the commentary in those issues I linked earlier, it seems like this problem is not as straightforward as I first thought. The API devs don't feel it's the responsibility of the API to handle it, and every frontend app could handle it differently. That said, I tried to make it work using as little code as possible. Here's a proof-of-concept:
https://github.com/postlight/headless-wp-starter/compare/master...modelm:fix-slug-redirect
This changes the frontend so that it uses the built-in /wp-json/wp/v2/posts?slug=
endpoint. It also adds a filter that makes the API send a 301 redirect to the new slug if there was no result for the initial query and a post with that slug exists. This only redirects the API response, so the frontend displays the rewritten post, but the URL is still the old slug. Having dug into this problem this far, I'm not convinced this needs to be included in this project at this point. I'd like to see what other solutions arise from similar projects or if the WP API devs change their mind and decide to support this directly in the API itself first.
@modelm If your frontend app is hosted on a different server than your WordPress CMS then it doesn't make sense to do the permanent redirect in the WP REST API.
The post permalink redirect needs to occur in the frontend and set the headers to 301 to let the Google bot know that the old link has been permanently redirected to the new link.
For redirecting in getInitialProps
have a look at https://stackoverflow.com/questions/45099395/conditional-redirection-in-next-js and
https://github.com/zeit/next.js/wiki/Redirecting-in-%60getInitialProps%60
I agree the frontend should redirect. What's still unclear (IMO) is what the API should do to indicate this. If it does redirect, the frontend can recognize that and also redirect the client - so my fix-slug-redirect
is a partial solution, although I am still hoping someone comes up with a standard way to handle this type of thing before everyone implements their own method.
@modelm One solution would be that when you send a request to the REST API to fetch data for the post 'hello-world' but the name/slug for that post is now 'hello-world-new' then we could extend the WP REST API to find the post by old slug (see function _find_post_by_old_slug
) and return that post data instead of nothing.
For example, a user clicked on the website link www.example.com/post/hello-world
in the Google search results but that post's permalink slug has since changed and it's now www.example.com/post/hello-world-new
then in getInitialProps()
in frontend/pages/post.js
we should check if the post_name
in the post data returned by the REST API still matches the context slug. If not then we do the 301 permanent redirect to www.example.com/post/hello-world-new
I hope this makes sense.
@modelm Hi, did you come up to a solution to this?
@Emiliano-Bucci See https://github.com/postlight/headless-wp-starter/compare/master...modelm:fix-slug-redirect for a proof-of-concept. The API sends a 301 if 1) it would otherwise 404 and 2) it finds a post that exists with the requested slug using a hack filter that shortcircuits wp_old_slug_redirect
.
@modelm Thanks for the answer. The fact is that i'm not using postlight (i'm building the front end of an already existing website made it with wordpress, with next js and similar stuff that you find in postlight). So i think i just have to implement that, right?
If you add that filter to your wordpress install it will redirect API requests when there's an old slug match. It's up to your frontend to process/follow that (in the react app included in this repo, that's automatic). For example - you probably want to forward a 301 to the client and redirect them too, otherwise they'll never know the slug has changed.
@modelm Thanks again! Yes, i think that i will have to handle this thing. I'm using wp-graphql, i will see if someone implement something related to this, thanks very much for your time :)
Will there ever be a fix in Wordpress for this?
In WordPress when you change a 'post slug' in the Permalink then WordPress will automatically redirect a link containing an old slug to the new link with new slug and sets the status to 301 Moved Permanently. This is very useful especially when you change a post's slug after Google has already indexed that page otherwise you will end up with lots of 404s and that's probably not good for SEO and certainly not good UX.
Since the frontend is a headless WordPress app instead of a traditional php theme how can you redirect old post slugs on the frontend?