[ic] Rewriting URLs for SEO purposes - help!
Jamie Neil
jamie at versado.net
Mon Apr 11 08:20:37 EDT 2005
Cameron G wrote:
> Which is nice, except I'm still left with a URL that isn't terribly search
> engine happy. That's why when a client wants to buy a claw hammer, I'd like
> the url for him to read
>
> http://www.store.com/hammers/clawhammer.htm
>
> Or even
>
> http://www.store.com/hammers.htm
>
> And have that invisibly map to whatever it needs to in the background, all
> the while presenting that clean, simple, keyword happy URL to both the
> client and the SE bots.
There's two stages to this:
1) Use URL rewriting to clean up the root path.
2) Use an actionmap to convert the rest of the path to a search.
Here's how we do it:
--------------------
httpd.conf
----------
...
RewriteEngine on
RewriteRule ^$ /cgi-bin/domain/index.html [PT,L]
RewriteRule ^/$ /cgi-bin/domain/index.html [PT,L]
RewriteRule ^/index\.html$ /cgi-bin/domain/index.html [PT,L]
RewriteRule ^/.*\.css - [PT,L]
RewriteRule ^/.*\.ico - [PT,L]
RewriteRule ^/robots.txt - [PT,L]
RewriteRule ^/cgi-bin/domain/.* - [PT,L]
RewriteRule ^/stats/.* - [PT,L]
RewriteRule ^/images/.* - [PT,L]
RewriteRule ^/js/.* - [PT,L]
RewriteRule ^/interchange-5/.* - [PT,L]
RewriteRule ^/(.*) /cgi-bin/domain/$1 [PT,L]
...
catalog.cfg
-----------
...
ActionMap dept <<EOR
sub {
my ($action, $deptid, $categoryid, $mfrid) = split ('/', shift);
my $dept = $Tag->data( { table => dept, field => name, key => $deptid
} );
$CGI->{deptid} = "$deptid";
$CGI->{dept} = "$dept";
$CGI->{mv_coordinate} = 'yes';
$CGI->{mv_search_file} = 'products';
$CGI->{mv_searchtype} = 'db';
$CGI->{mv_todo} ='search';
$CGI->{mv_return_fields} =
'sku,manufacturer,prod_group,category,option_type,thumb,image,description,comment,tax_category,nontaxable,price';
$CGI->{mv_sort_field} = 'category,manufacturer,price,description';
$CGI->{mv_sort_option} = 'f,f,n,f';
$CGI->{mv_search_field} = "prod_group";
$CGI->{mv_column_op} = "rm";
$CGI->{mv_searchspec} = "$deptid";
if ($categoryid) {
my $category = $Tag->data( { table => cat, field => name, key =>
$categoryid, foreign => name } );
$CGI->{categoryid} = "$categoryid";
$CGI->{category} = "$category";
$CGI->{mv_nextpage} = 'category';
$CGI->{mv_search_field} .= "\0category";
$CGI->{mv_column_op} .= "\0rm";
$CGI->{mv_searchspec} .= "\0$category";
if ($mfrid) {
my $mfr = $Tag->data( { table => manufacturers, field => name,
key => $mfrid, foreign => name } );
$CGI->{mv_search_field} .= "\0manufacturer";
$CGI->{mv_column_op} .= "\0rm";
$CGI->{mv_searchspec} .= "\0$mfr";
$CGI->{mfrid} = "$mfrid";
$CGI->{mfr} = "$mfr";
$CGI->{banner_text} = "$mfr $category";
}
else {
$CGI->{mfrid} = '';
$CGI->{mfr} = '';
$CGI->{banner_text} = "$category";
}
}
else {
$CGI->{categoryid} = '';
$CGI->{category} = '';
$CGI->{mfrid} = '';
$CGI->{mfr} = '';
$CGI->{mv_nextpage} = 'dept';
$CGI->{banner_text} = "$dept";
}
$Tag->update('process');
return 1;
}
EOR
...
--------------------
This allows URLs like this:
http://www.domain.com/dept/widgets.html ->
http://www.domain.com/cgi-bin/domain/dept.html?
deptid=widgets&
dept=Widgets&
mv_coordinate=yes&
mv_search_file=products&
mv_searchtype=db&
mv_todo=search&
mv_return_fields=sku,manufacturer,prod_group,category,option_type,
thumb,image,description,comment,tax_category,nontaxable,price&
mv_sort_field=category,manufacturer,price,description&
mv_sort_option=f,f,n,f&
mv_search_field=prod_group&
mv_column_op=rm&
mv_searchspec=widgets&
categoryid=&
category=&
mv_nextpage=dept&
mfrid=&
mfr=&
banner_text=Widgets
http://www.domain.com/dept/widgets/bigwidgets.html ->
http://www.domain.com/cgi-bin/domain/category.html?
deptid=widgets&
dept=Widgets&
mv_coordinate=yes&
mv_search_file=products&
mv_searchtype=db&
mv_todo=search&
mv_return_fields=sku,manufacturer,prod_group,category,option_type,
thumb,image,description,comment,tax_category,nontaxable,price&
mv_sort_field=category,manufacturer,price,description&
mv_sort_option=f,f,n,f&
mv_search_field=prod_group\0category&
mv_column_op=rm\0rm&
mv_searchspec=widgets\0bigwidgets&
categoryid=bigwidgets&
category=Big%20Widgets&
mv_nextpage=category&
mfrid=&
mfr=&
banner_text=Big%20Widgets
http://www.domain.com/dept/widgets/bigwidgets/acme.html ->
http://www.domain.com/cgi-bin/domain/category.html?
deptid=widgets&
dept=Widgets&
mv_coordinate=yes&
mv_search_file=products&
mv_searchtype=db&
mv_todo=search&
mv_return_fields=sku,manufacturer,prod_group,category,option_type,
thumb,image,description,comment,tax_category,nontaxable,price&
mv_sort_field=category,manufacturer,price,description&
mv_sort_option=f,f,n,f&
mv_search_field=prod_group\0category\0manufacturer&
mv_column_op=rm\0rm\0rm&
mv_searchspec=widgets\0bigwidgets\0acme&
categoryid=bigwidgets&
category=Big%20Widgets&
mv_nextpage=category&
mfrid=acme&
mfr=Acme&
banner_text=Acme%20Big%20Widgets
Notes:
------
All this is based on the standard foundation demo with an additional
"manufacturer" field and table.
Eliminating the "dept" is possible (I think) but would require more
complex rewrite rules with exceptions to avoid clashes with "static" IC
pages, so maintainance would be tricky.
In order to deal with Title Case and other naming issues, I use an "id"
for the search which is then looked up in the relevant table using the
data tag in order to get the proper name e.g. bigwidgets->Big Widgets.
The category page uses the "mfrid" cgi value to determine whether to
display _all_ products in a category or just a particular
manufacturer's. I could have done the same with prod_group, but as my
dept and category pages look quite different I decided against it.
In order to stack mv variables you need to separate them with nulls
(\0). I'm not sure how this is normally displayed in the actual query
string so I just put then in as \0 to indicate the point.
--
Jamie Neil | <jamie at versado.net> | 0870 7777 454
Versado I.T. Services Ltd. | http://versado.net/ | 0845 450 1254
More information about the interchange-users
mailing list