0
votes

Website has changed its url names due to SEO reasons, e.g. it was:

/category/filter1/f00/filter2/123/filter3/100-500/filter4/36.html

now:

/category/color/red/size/big/price/100-500/style/classic.html

I know the old and new names, they're fixed. Please help me to build a rewrite rule which will result in 301 redirect from old urls to new. I did research and I see that I cannot make it using RewriteMap for example, so I ended up making something like RewriteRule (.*)filter1(.*) $1color$2 [L] etc. Not only I don't like the way it looks, but also it doesn't give me a 301 redirect.

UPDATE: Note that at the moment I have several rules, one per filter name/value, e.g.:

RewriteEngine on

# make sure it's a catalog URL, not anything else
RewriteCond %{REQUEST_URI} !^/(category1|category2|category3|category4)
RewriteRule .* - [L]

# rewrite filter names
RewriteRule (.*)filter1(.*) $1color$2 [L]
RewriteRule (.*)filter2(.*) $1price$2 [L]
...etc...

It works as expected - changing all the names in URL, but setting R flag causes the stop on first rule and redirect to URL like:

/var/www/vhosts/site/htdocs/category/color/red/filter2/123/ etc...

I separated rules because any of filters may or may not exist in the URL. I will greatly appreciate the better solution.

2

2 Answers

2
votes

Here is my own answer: it is possible to do with environment variables. We need to replace old filter names and values with new ones, and then make only one 301 redirect to new URL. Here what I've done using mod_rewrite and environment variables:

RewriteEngine on

RewriteRule /filter1/               - [E=filters:/color/]
RewriteRule /f00[.\/]               - [E=filters:%{ENV:filters}red]
RewriteRule /0f0[.\/]               - [E=filters:%{ENV:filters}green]
RewriteRule /00f[.\/]               - [E=filters:%{ENV:filters}blue]

RewriteRule /filter2/               - [E=filters:%{ENV:filters}/size/]
RewriteRule /123[.\/]               - [E=filters:%{ENV:filters}big]
RewriteRule /32[.\/]                - [E=filters:%{ENV:filters}small]

RewriteRule /filter3/([^/^\.]+)     - [E=filters:/price/$1]

RewriteRule /filter4/               - [E=filters:%{ENV:filters}/style/]
RewriteRule /36[.\/]                - [E=filters:%{ENV:filters}classic]
RewriteRule /37[.\/]                - [E=filters:%{ENV:filters}urban]

RewriteCond %{REQUEST_URI} ^/(category1|category2|category3|category4)/
RewriteCond %{ENV:filters} !^$
RewriteRule ^([^/]+)/ /$1%{ENV:filters}.html [L,R=301]

Basically, I've reformatted whole the URL in environment variable filters then checked if it's a category and not some else part of the website, and finally made redirect to this category+filters variable, appended .html at the end.

0
votes

Even though the new URL looks prettier to a human, I'm not sure if there's a need to change the existing URL for SEO reasons.


To get a redirect instead of a rewrite, you must use the R|redirect flag. So your rule would look like

RewriteRule (.*)filter1(.*) $1color$2 [R,L]

But if you have multiple redirects, this might impact your SEO results negatively, see Chained 301 redirects should be avoided for SEO , but Google will follow 2 or 3 stacked redirects

  • Remember that ideally you shouldn’t have any stacked redirects or even a single redirect if you can help it, but if required Google will follow chained redirects
  • But every additional redirect will make it more likely that Google won’t follow the redirects and pass PageRank
  • For Google keep it to two and at a maximum three redirects if you have to
  • Bing may not support chained redirects at all

This means try to replace multiple filters at once

RewriteRule ^(.*)/filter1/(.*)/filter2/(.*)$ $1/color/$2/size/$3 [R,L]

and so on.


When the filters may come in an arbitrary order, you may use several rules and do a redirect at the end

RewriteRule ^(.*)filter1(.*)$ $1color$2 [L]
RewriteRule ^(.*)filter2(.*)$ $1price$2 [L]
RewriteRule ^(.*)filter3(.*)$ $1size$2 [L]

RewriteCond %{ENV:REDIRECT_STATUS} 200
RewriteRule ^ %{REQUEST_URI} [R,L]

RewriteCond with REDIRECT_STATUS is there to prevent an endless loop.


When it works as it should, you may replace R with R=301. Never test with R=301.

A final note, be very careful with these experiments. I managed to kill my machine twice (it became unresponsive and I had to switch off) during tests.