Forum Moderators: phranque

Message Too Old, No Replies

ZenCart - redirect multiple URLs for 1 product?

         

KoolRifz

4:46 pm on May 21, 2011 (gmt 0)

10+ Year Member



I'm migrating 700+ products from ZenCart to Prestashop and thought I was almost finished with the redirects but have this sinking feeling I've only just begun.

Here is a zencart URL for a product in a sub-sub-category:

[url]musicplace.com.au/catelogue/index.php?main_page=product_info&cPath=112_80_184&products_id=935[/url]

Notice the "Path=112_80_184"? They are the categories this product lives in. If I remove the 112 from the URL I can still get to the product. If I reorder the cat numbers I can still get to the product. As long as I leave one category number I can reach the product. This is an absolute disaster for redirecting the products URL. There seems to be several combinations of URLs that I will have to prepare for each redirection. I don't know what to do.


So my questions are?
  1. Is there some clever code that will allow me to redirect any version of the category numbers to reach my URL friendly page in Prestashop?
  2. Do I need some code that deals with then Zen session ID?


Any help would be greatly appreciated. I've been at this for a week.

Thanks,
Rob


Here some of my .htaccess file.

Options +FollowSymLinks
RewriteEngine On

RewriteCond %{QUERY_STRING} ^main_page=product_info&cPath=112_80_184&products_id=942$
RewriteRule ^index\.php$ http://store.musicplace.com.au/clarinet-ligatures/401-rovner-clarinet-ligature-and-cap-set.html? [R=301,L]
RewriteCond %{QUERY_STRING} ^main_page=product_info&products_id=942$
RewriteRule ^index\.php$ http://store.musicplace.com.au/clarinet-ligatures/401-rovner-clarinet-ligature-and-cap-set.html? [R=301,L]
RewriteCond %{QUERY_STRING} ^main_page=product_info&cPath=112_80_184&products_id=951$
RewriteRule ^index\.php$ http://store.musicplace.com.au/clarinet-ligatures/410-vandoren-masters-bass-clarinet-ligature.html? [R=301,L]
RewriteCond %{QUERY_STRING} ^main_page=product_info&products_id=951$
RewriteRule ^index\.php$ http://store.musicplace.com.au/clarinet-ligatures/410-vandoren-masters-bass-clarinet-ligature.html? [R=301,L]
RewriteCond %{QUERY_STRING} ^main_page=product_info&cPath=112_80_184&products_id=954$
RewriteRule ^index\.php$ http://store.musicplace.com.au/clarinet-ligatures/403-vandoren-optimum-silver-plated-eb-clarinet-ligatures.html? [R=301,L]
RewriteCond %{QUERY_STRING} ^main_page=product_info&products_id=954$
RewriteRule ^index\.php$ http://store.musicplace.com.au/clarinet-ligatures/403-vandoren-optimum-silver-plated-eb-clarinet-ligatures.html? [R=301,L]
RewriteCond %{QUERY_STRING} ^main_page=product_info&cPath=112_80_184&products_id=945$
RewriteRule ^index\.php$ http://store.musicplace.com.au/clarinet-ligatures/407-vandoren-masters-alto-clarinet-ligature.html? [R=301,L]
RewriteCond %{QUERY_STRING} ^main_page=product_info&products_id=945$
RewriteRule ^index\.php$ http://store.musicplace.com.au/clarinet-ligatures/407-vandoren-masters-alto-clarinet-ligature.html? [R=301,L]
RewriteCond %{QUERY_STRING} ^main_page=product_info&cPath=112_80_184&products_id=935$
RewriteRule ^index\.php$ http://store.musicplace.com.au/clarinet-ligatures/409-vandoren-optimum-silver-plated-bass-clarinet-ligatures.html? [R=301,L]

g1smd

8:28 pm on May 21, 2011 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Just detect the
(^|&)products_id=([^&]+)(&|$)
part and redirect based on that value.

You need to get any combination of parameters with the parameters in any order correctly redirected.

KoolRifz

1:00 am on May 22, 2011 (gmt 0)

10+ Year Member



Thank you g1smd for your promt reply. In trying to be precise I may have inadvertantly misrepresented my level of experience. I'm 10 days old to these regular expressions and am hanging on by a hair.

Would you please rewrite this redirect into one that looks like the one you advised?

RewriteCond %{QUERY_STRING} ^main_page=product_info&cPath=112_80_184&products_id=942$
RewriteRule ^index\.php$ http://store.musicplace.com.au/clarinet-ligatures/401-rovner-clarinet-ligature-and-cap-set.html? [R=301,L]


Also am I reading you correct, are suggeting taking a product url and sending it based on it's catagoy path like 112, 80 or 184 to a specific user friendly URL in new site?

I really have to preserve our good google ranking at all costs.

Sorry but I'm not following the logic. If this is a basic question answered many times please point in the right direction. I don't really know what to search...

Thank you again for your help,
Rob

g1smd

1:47 am on May 22, 2011 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



ZenCart is renowned for the number of Duplicate Content URLs that can be accessed for each and every product. For the first line of your first redirect use this code:

RewriteCond %{QUERY_STRING} (^|&)products_id=942(&|$)


It now redirects based on purely the product ID. and you don't need the second redirect.

On your new website I would recommend NOT having category data in the URL for products. It creates a lot of issues.

You should also dispense with the .html extension.

KoolRifz

2:17 am on May 22, 2011 (gmt 0)

10+ Year Member



THANK YOU! In Summary, would the following be correct?

RewriteCond %{QUERY_STRING} (^|&)products_id=942(&|$) 
RewriteRule ^index\.php$ http://store.musicplace.com.au/clarinet-ligatures/rovner-clarinet-ligature-and-cap-set? [R=301,L]


Then in my bew cart Prestashop I know there is some code to get rid of the category like "401" (above).

Lastly do I need to change the file extension to any aother like .php or just leave as text "http://store.musicplace.com.au/clarinet-ligatures/401-rovner-clarinet-ligature-and-cap-set"

Thank you very much for your help! If I've understood you correctly then my job of redirecting is almost done. Just a few text searches and deleting.

g1smd

2:21 am on May 22, 2011 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



In the redirect code I would also change from using
^index\.php$
to
^(index\.php)?$
too.

On your new site I would recommend removing "clarinet-ligatures/" from the URL.

The "401" I would leave in. Yes, use NO extension (no .html, no .php, nothing).

KoolRifz

12:48 am on May 23, 2011 (gmt 0)

10+ Year Member



I've used this excel spread sheet bt Ted Bradley from [mbstrategic.com ] to redirect my dynamic URLs to static ones. However, I'm not up to speed with excel forumals or regular expressions yet to alter the code to produce the RewriteCond URL that I need.

Next (and hopefully the last) question:

Do you have a clever way of searching my RewriteCond strings and replacing:

RewriteCond %{QUERY_STRING} ^main_page=product_info&cPath=112_80_184&products_id=945$


With

RewriteCond %{QUERY_STRING} (^|&)products_id=945(&|$) 


?

If not no worries, I'll start the process of rearch and replace.

I'm working on regular expression tutorials but it's all swimming around in my head and needs time to consolidate. However, time is one thing I don't have so any help is totally appreciated.

Thanks,
Rob

g1smd

8:50 am on May 23, 2011 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



By having all the rules in your .htaccess file you have several disadvantages. Firstly, the file becomes a nightmare to maintain, and a single typo could bring the whole site down. Secondly every rule has to be parsed for every request which leads to performance problems.

There is another alternative way of doing this, with several advantages.

Rewrite (that's rewrite, not redirect) all of your products_id=nnn URL requests to a special script that then looks up (in an array or in a database) what the new URL should be. The PHP script then sends the Redirect headers.

This ruleset goes near the beginning of the .htaccess file, before any other redirects.
RewriteCond %{QUERY_STRING} (^|&)products_id=([0-9]+)(&|$)
RewriteRule ^(index\.php)?$ /my-special-script.php?oldID=$1[L]


and then in your special script you simply have an array listing all the new URLs against their old ID number:

<?php
$server = $_SERVER['HTTP_HOST'];
IF (preg_match('/^www\./', $server_url)!==true)
{$server = "www." . $server_url; };

$old_ID = GET['oldID'];

$URL_map = array(
942 => '401-rovner-clarinet-ligature-and-cap-set',
951 => '410-vandoren-masters-bass-clarinet-ligature',
954 => '403-vandoren-optimum-silver-plated-eb-clarinet-ligatures',
945 => '407-vandoren-masters-alto-clarinet-ligature',
935 => '409-vandoren-optimum-silver-plated-bass-clarinet-ligatures'
);

IF ($URL_map[$old_ID] == "")
{
HEADER "Status: HTTP/1.1 404 Not Found";
}
ELSE
{
$new_URL = $server . '/' . $URL_map[$oldID];

HEADER "Status: HTTP/1.1 301 Moved Permanently";
HEADER "Location: " . $new_URL;
}
?>

KoolRifz

10:12 am on May 23, 2011 (gmt 0)

10+ Year Member



What a great exercise! I got your previous example working and used excel to convert the URL's. Here is what I was up to for 700 products:

RewriteCond %{QUERY_STRING} (^|&)products_id=1183(&|$)
RewriteRule ^index\.php$ [store.musicplace.com.au...] [R=301,L]

However, I really dig what you've just sent me. Thank you for your very kind help. A couple of prelim points to settle first.

1. will my-special-script.php reside in the root of old site?

2. I'm rewriting from a subdirectory to a subdomain.
old URL - "http://musicplace.com.au/catalogue"
new URL - "http://store.musicplace.com.au"
How will this effect $new_URL?

3. Not every rewrite will be a products_id=nnn. Some will be categories like: musicplace.com.au/catalogue/index.php?main_page=index&cPath=112

and others will be support pages like: musicplace.com.au/catalogue/index.php?main_page=contact_us

Would you recommend a .htaccess redirect for pages OTHER than products_id=nnn ?

Many thanks,
Rob

g1smd

10:46 am on May 23, 2011 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



The script can go in the root, or you can make a /sekrit-folder/ for it. As long as the rewrite target points at the right place from within the .htaccess file, it will work.

You won't need the little bit of "add www to the domain name" line of code in my example. You can just do:
$server = 'store.musicplace.com.au';
(my initial example was for where you were staying on the same domain and changing only the URL structure).

There's at least one logic and syntax error in my example script above (which I wrote from my head without testing it). Certainly,
$new_URL = $server . '/' . $URL_map[$oldID];

should be:
$new_URL = 'http://' . $server . '/' . $URL_map[$old_ID];


For categories, make another "special script" and add another ruleset to the .htaccess file in order to rewrite "cPath=nnn" requests to the second script. If you put this new rewrite AFTER the products one, it will activate only for category requests.

For single pages, such as 'contact' and 'about' and the site root, just have a single redirect rule for each one in the .htaccess for doing that. There's little point having one line of code in the .htaccess file rewriting to a one line PHP script that then issues the redirect. Just have a one line redirect directly in the .htaccess file and be done.

Be very clear on the differences between a rewrite and a redirect, otherwise you might misinterpret the above explanations.

Make sure the 404 error document on the old site contains a clickable link to the new site and a big message that says "we have moved to a new site" as well as the expected "page not found" error itself.

Additionally, after the line of code
HEADER "Status: HTTP/1.1 404 Not Found";

you should expand out with
<html><head>
<title>Page Not Found</title>
</head><body>
<h1>Page Not Found</h1>
<p>We're moving to a new site -</p>
<p><a href="http://store.musicplace.com.au/">store.musicplace.com.au</a></p>
<p>Update your bookmarks.</p>
</body></html>

for the human visitor to read and take action on.
In fact, you might prefer to upgrade to "410 Gone" here instead of the more general "404 Not Found".

[edited by: g1smd at 11:16 am (utc) on May 23, 2011]

KoolRifz

11:11 am on May 23, 2011 (gmt 0)

10+ Year Member



Wow! So logical and mind blowing. I'm off...hopefully I'll be back with good news.

g1smd

11:22 am on May 23, 2011 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Make sure you pick up a couple of corrections in the previous post.

You didn't "waste" much time doing it the other way to begin with. You learnt a bit about RegEx along the way, and can apply that method to small numbers of URLs in the future. The rewrite to a "special script" is a good method for "bulk moves" and has many advantages.

Using an array for a "one time move" is simple enough. When you're continually updating the mapping on a live dynamic site, you use a database table integrated with the main site data, instead of an array.

KoolRifz

3:05 pm on May 23, 2011 (gmt 0)

10+ Year Member



I'm under the hammer to get this new site operational but really want to get this special script right. I'm learning heaps and advantages are glaringly obvious. I feel very close - I've got the .htaccess and product-script.php uploaded but nothing is happening. Here are the contents of the files with only a few arrays showing.

.htaccess

RewriteCond %{QUERY_STRING} (^|&)products_id=([0-9]+)(&|$)
RewriteRule ^(index\.php)?$ /sekrit-folder/product-script.php?oldID=$1[L]


/sekrit-folder/product-script.php

<?php
$server = 'store.musicplace.com.au';
IF (preg_match('/^www\./', $server_url)!==true)
{$server = "www." . $server_url; };

$old_ID = GET['oldID'];

$URL_map = array(
1183 => '449-breakthrough-to-improv-the-secrets-of-improvising'
1184 => '450-i-love-the-trumpet'
1757 => '726-francois-louis-ultimate-ligature-clarinet'
935 => '409-vandoren-optimum-silver-plated-bass-clarinet-ligatures'
945 => '407-vandoren-masters-alto-clarinet-ligature'
953 => '398-vandoren-optimum-silver-plated-alto-clarinet-ligatures'
954 => '403-vandoren-optimum-silver-plated-eb-clarinet-ligatures'
1016 => '413-vandoren-optimum-tenor-saxophone-ligature'
957 => '433-francois-louis-the-ultimate-ligature-'
);

IF ($URL_map[$old_ID] == "")
{
HEADER "Status: HTTP/1.1 404 Not Found";
<html><head>
<title>Page Not Found</title>
</head><body>
<h1>Page Not Found</h1>
<p>We're moving to a new site -</p>
<p><a href="http://store.musicplace.com.au/">store.musicplace.com.au</a></p> </p>Update your bookmarks.</p>
</body></html>
}
ELSE
{
$new_URL = 'http://' . $server . '/' . $URL_map[$old_ID];

HEADER "Status: HTTP/1.1 301 Moved Permanently";
HEADER "Location: " . $new_URL;
}
?>

KoolRifz

3:37 pm on May 23, 2011 (gmt 0)

10+ Year Member



OK. Forgot to turn on the Rewrite Engine
Doh!

Getting:
Parse error: syntax error, unexpected '[' in /home/musicpla/public_html/catalogue/sekrit-folder/product-script.php on line 6

KoolRifz

3:41 pm on May 23, 2011 (gmt 0)

10+ Year Member



Here is line 1-6:
<?php
$server = 'store.musicplace.com.au';
IF (preg_match('/^www\./', $server_url)!==true)
{$server = "www." . $server_url; };

$old_ID = GET['oldID'];

KoolRifz

3:49 pm on May 23, 2011 (gmt 0)

10+ Year Member



Fixed that:
$old_ID = $_GET['oldID'];

Just fixing a few more errors and...fingers crossed

KoolRifz

4:09 pm on May 23, 2011 (gmt 0)

10+ Year Member



Ok, Got rid of the errors and now getting through to the custom 404 page but its not making it to the new URL. The rewriting doesn't seem to be working. Any ideas?

<?php
$server = 'store.musicplace.com.au';
IF (preg_match('/^www\./', $server_url)!==true)
{$server = "www." . $server_url; };

$old_ID = $_GET['oldID'];

$URL_map = array(
1183 => '449-breakthrough-to-improv-the-secrets-of-improvising',
1184 => '450-i-love-the-trumpet',
1757 => '726-francois-louis-ultimate-ligature-clarinet',
935 => '409-vandoren-optimum-silver-plated-bass-clarinet-ligatures',
);

IF ($URL_map[$old_ID] == "")
{
HEADER ("Status: HTTP/1.1 404 Not Found");
?>
<html><head>
<title>Page Not Found</title>
</head><body>
<h1>Page Not Found</h1>
<p>We're moving to a new site -</p>
<p><a href="http://store.musicplace.com.au/">store.musicplace.com.au</a></p> </p>Update your bookmarks.</p>
</body></html>
<?php
}
ELSE
{
$new_URL = 'http://' . $server . '/' . $URL_map[$old_ID];

HEADER ("Status: HTTP/1.1 301 Moved Permanently");
HEADER ("Location: " . $new_URL);
}
?>

g1smd

6:24 pm on May 23, 2011 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



The "IF" bit adds www to the new URL. You don't need those two lines as I mentioned earlier.

Apologies for the couple of typos in the code. Really, the code was out of my head without reference to the exact syntax required.

Check to see if the syntax and logic of this bit is OK:
IF ($URL_map[$old_ID] == "")

I suspect you might want to test for "not digits" or something, rather than "" blank.


Parallel discussion showing the database method: [webmasterworld.com...]

KoolRifz

12:32 am on May 24, 2011 (gmt 0)

10+ Year Member



Sorry for not being able to capitalise on all the help you've given me. I'm feeling a little embarassed...

Would I use "\D" to test for non digits in the IF statement below?

Here is what I'm up to. Starting to panic as I'm over my head. Also do I need to take into account that zencart adds that silly zenid to it's url?:
musicplace.com.au/catalogue/index.php?main_page=product_info&cPath=112_77&products_id=1405&zenid=9e78620f0b7c8ab74d8fd3c1dfaf9293

.htaccess

Options +FollowSymLinks
RewriteEngine On

RewriteCond %{QUERY_STRING} (^|&)products_id=([0-9]+)(&|$)
RewriteRule ^(index\.php)?$ /catalogue/sekrit-folder/product-script.php?oldID=$1[L]

RewriteCond %{QUERY_STRING} (^|&)cPath=([0-9]+)(&|$)
RewriteRule ^(index\.php)?$ /catalogue/sekrit-folder/category-script.php?oldID=$1[L]


product-script.php

<?php
$server = 'store.musicplace.com.au';
$old_ID = $_GET['oldID'];

$URL_map = array(
111 => 'store.musicplace.com.au',
112 => '98-woodwind-mouthpieces',
121 => 'store.musicplace.com.au',
116 => '72-trumpet-mouthpieces',
99 => '52-soprano-sax',
);

IF ($URL_map[$old_ID] == "\D")
{
HEADER ("Status: HTTP/1.1 404 Not Found");
?>
<html><head>
<title>Page Not Found</title>
</head><body>
<h1>Page Not Found</h1>
<p>We're moving to a new site -</p>
<p><a href="http://store.musicplace.com.au/">store.musicplace.com.au</a></p> </p>Update your bookmarks.</p>
</body></html>
<?php
}
ELSE
{
$new_URL = 'http://' . $server . '/' . $URL_map[$old_ID];

HEADER ("Status: HTTP/1.1 301 Moved Permanently");
HEADER ("Location: " . $new_URL);
}
?>

g1smd

1:09 am on May 24, 2011 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



No. I don't think you can use \d unless you use preg_match, preg_replace or somesuch.

Even if it could be used the logic would currently read "IF the oldID is digits send the 404 stuff". You might need a "NOT" operator in there somewhere.

With your example code showing the
<p>Update your bookmarks.</p>
part positioned way over to the right of the page, instead of on a separate line, I can see you copied that code before I had edited the post. You should read every post in this thread again just in case something has changed and you haven't seen the new version.

If the value of ZenID changes, do you want to redirect to a different place?

KoolRifz

4:58 am on May 24, 2011 (gmt 0)

10+ Year Member



I'm feeling quite guilty asking you to fix this problem for me only to come back with more questions. I would be very grateful if I could engage your services to fix this for me once and for all. I would like the URL's stored in a database with a web intereface so all subsiquent URLs could be entered with ease. If this is suitable, how much would you charge?

Hope I'm not out of line asking you but I feel as if I have many more questions and so many other things to work on, plus I don't want to take advantage of your generosity. I did try to send you a StickyMail but your mailbox is full.

Cheers,
Rob

KoolRifz

6:42 am on May 24, 2011 (gmt 0)

10+ Year Member



I must be making progress as I'm getting though to a blank page. Instad of checking if the $URL_map is not a number I'm checking if it is greater than zero. If yes, then perform the rewrite. If false perform the 410 Gone header. However I still can't get through to rewriting the URL.

I haven't set up Prestacart to accept URLs without the .html file extension so I'll try adding that back into the URL to see if I can get it to work. I need to minimise the problems.

I'll update the 410 Gone page with the suggestions at DevShed when I get this working.

here's where I am now:

IF ($URL_map[$old_ID] >=0 )
{
$new_URL = 'http://' . $server . '/' . $URL_map[$old_ID];

HEADER ("Status: HTTP/1.1 301 Moved Permanently");
HEADER ("Location: " . $new_URL);
}
ELSE
{
HEADER ("Status: HTTP/1.1 410 Gone");
?>
<html><head>
<title>Page Gone</title>
</head><body>
<h1>Page Not Found</h1>
<p>We have moved to our new site </p>
<p><a href="http://store.musicplace.com.au/">store.musicplace.com.au</a></p>
<p>Update your bookmarks.</p>
</body></html>
<?php
}
?>

KoolRifz

6:57 am on May 24, 2011 (gmt 0)

10+ Year Member



I'm going to go with putting all the redirections into the .htaccess file as it actually works. My client is sweating bullets. At least I can launch the new web site and continue to optomise the code. I'm so happy to have discovered all that you have shown me.

I'm going to now concentrate on getting the code to work in a php file then I'll get the database version working. I'll be around here for a while...

We start and stop new products all the time and in the past our URLs just went into the ether. I can see that non-method is very amaturish. I hope to fix it.

Now I've got to get that IF statement working...