Using .htaccess to make search engine-friendly URLs – “There is no spoon”

User Jan wrote me with the following query about optimizing database driven websites.


Hi there,

I have a question about search engine friendly sites in regard to your article here about SEO of Database-driven Websites. I’m trying to make a website search engine friendly, using descriptive urls. Currently every link to a subpage looks like this: www.dom.ain/?visit=cat

So I only have 1 index file that provides information the user wants. Is there any way to improve this without creating a new php for every page on the site?

I thought about creating a *.htm that will route to the corresponding php url.

E.g. company.htm file routes to /?visit=comp

But I gathered that search engines don’t like links that are opened via Java Script.

Thx for any help, it would be greatly aprechiated.

Kind Regards, Jan


I replied:

When we have a website that uses variables in the domain names, we usually
use a system called Mod Rewrite on a Linux/Apache/mySQL/PHP (LAMP) server
to make more user-friendly URLs. This doesn’t work the same a Windows IIS
server, but works well on a LAMP server. Most websites nowadays are on LAMP
servers.

It works like this:

In the .htaccess file put these lines for each of the pages of the site.
(Contact a web programmer for a quote on doing this if it is beyond your
technical skills — it should be fairly fast and cheap to get done.)

—-
RewriteEngine On
RewriteRule ^airport.php /community.php?unit=airport.php&language=english [L]

—–
You only need to tell it “RewriteEngine On” once. For every page you want to rewrite like this, you add another line.

So when someone goes to airport.php, what they actually get is the community.php page, with all its variables. What Google “sees” is airport.php. What a visitor “sees” in his browser address bar is airport.php.

What’s actually displaying to both Google and your visitor is

community.php?unit=airport.php&language=english

This allows you to have a shorter URL that is more search engine friendly.

Here’s a better example:

RewriteRule ^big-green-widgets.php /product-display.php?productid=widgets&productstyle=blue&productsize=big[L]

There IS no page named big-green-widgets.php on the server. (Like Neo learns in The Matrix movie, “There is no spoon.”)

The server sees a request for the page “big-green-widgets.php” and because of this line in the .htaccess file, the server goes and gets the info it
needs to create the page on-the-fly.

Also, don’t use JavaScript for your links. In your navigation menus, link to the names of the pages you set up in the .htacess file, like “big-green-widgets.php“. Even if that actually mod rewrites over to www.dom.ain/?visit=cat1324, it doesn’t matter. As far as Google and your visitors are concerned, you have a page called big-green-widgets.php.

Mod rewrite is a wonderful tool for anyone trying to optimize a site that is built using only a single page with variables, or using a long string of variables and a database.

Make sense?

Best,

Jeré Matlock
https://www.wordsinarow.com
Website Design & Marketing / SEO

27 Responses to Using .htaccess to make search engine-friendly URLs – “There is no spoon”

  1. Jere Matlock November 15, 2009 at 5:40 pm #

    Wow thanks a lot for your reply, not used to getting feedback this fast, and such excellent one too.

    This is pretty much exactly what I was looking for. I guess any further information, for example on dynamic generation of the .htaccess files
    should be available via google.

    Thanks again,

    -Jan

  2. Jim Gaudet December 8, 2009 at 1:40 pm #

    Thanks for the info, but I have a different question more database related. I would like to have the url like this;

    domain.com/products/category/product-title

    category and product-title with be tables in the database. How can I get it to search the database for the proper category and product?

    How could I get the .htaccess file to forward the variables to the PHP page,which can search for the category and product-title, then generate the page?

    Thanks in advance,

    Jim

  3. Jere Matlock December 8, 2009 at 3:03 pm #

    If you want to have your website using page names something like this:

    www. hubcaps.com /plymouth/ 66-valiant-hubcaps

    that’s fairly easy to set up using a RewriteRule in .htaccess

    RewriteEngine On
    RewriteRule ^plymouth/66-valiant.php /display.php?category=plymouth&year=66&model=valiant [L]

  4. Mark February 19, 2010 at 12:33 am #

    This is great. Thank you.

    It obviously allows people to get routed to the right part of your database but how does a search engine know what to look for? Does it spider the .htaccess file?

  5. Jere Matlock February 20, 2010 at 11:19 pm #

    No – Google never sees the .htaccess file (it’s inaccessible through normal browsing).

    Instead, when Google requests the page, in much the same fashion as a person browsing the page would request it, the server creates it “on the fly” and gives it to Google based on the action of Google requesting the page. It’s fast and it works. This is how to show elegant, search-engine-friendly URLs while having the actual content come from a database by using question marks, product ids, category ids, and so on. In practice, it works great!

  6. abbas February 23, 2010 at 6:00 am #

    hi
    i have any dynamic page like this in my site:
    http : / /mirsoft.net/detail.php?siteid=433

    how can i change to this : http : // mirsoft.net/detail-433.html by .htaccess file.

    thanks.

  7. Jere Matlock February 23, 2010 at 10:39 am #

    Hi, Abbas –

    Test this code in your .htaccess file, to see if it works:

    RewriteEngine On
    RewriteRule ^detail-433.htm /detail.php?siteid=433 [L]

    —————-

    Here are some tutorials on using .htaccess that you may find useful:

    http://softexpert.wordpress.com/2007/10/15/learn-htaccess-in-10-minutes/

    http://www.thejackol.com/htaccess-cheatsheet/

    http://www.javascriptkit.com/howto/htaccess.shtml

    Good luck!

    Best,

    Jere Matlock

  8. Admin June 10, 2010 at 12:49 am #

    Thanks for pointing it out – broken by a blog plugin malfunctioning. I’ve repaired the problem.

  9. Jere Matlock October 27, 2010 at 10:41 am #

    Hi, Jim –

    I’ve run into this before.

    Try setting the “base” HTML command within cat.php.

    Or try setting up a Rewrite Rule that sends the “include” request to the correct folder.

    Note: You can have multiple .htaccess files within the different folders on your server at different levels on the server.

    Best,

    Jere Matlock

  10. Eric November 30, 2010 at 9:54 am #

    Hi

    Great tut, but all the time I’m reading your post and Q&A I have a question I still am very keen to confirm.. lets take the following case for example;
    ————————————–
    Hi, Abbas –

    Test this code in your .htaccess file, to see if it works:

    RewriteEngine On
    RewriteRule ^detail-433.htm /detail.php?siteid=433 [L]
    ————————————–
    so the above solution is just for id number 433… does that mean we have to do this for every id 1 to 433? And what about the future where it is quite possible for ids to go up all the way to thousands.. and what if the website gets 10 new ids an hour, do we manually create a mod rewrite for each new id? Wouldn’t that take just take up all of our time?

  11. Jere Matlock November 30, 2010 at 11:44 am #

    Hi, Abbas –

    No, you don’t have to do this by hand for each entry.

    When you have a very large, very active database-driven site, it is best to set up something we have given the name of “dispatcher”.

    Basically, you route the traffic through to a php file called dispatcher.php, that does a lookup in a mySQL database and provides the appropriate name.

    We just did this for a big media room (call it media.website.com) with several thousand pages, which we routed over to a blog (blog.website.com). Most of the pages of the media room were moved, but not all of them. Requests for those pages that were not moved are served a generic page with a 301 code. Requests for pages that were moved are given a 301 redirect to the exact page name in the blog that we want to serve up instead.

    To give credit where it is due, we “lifted” this system from the xCart shopping cart, which uses a file called “dispatcher.php” to do exactly the same thing. That’s how it makes search-engine-friendly URLs.

    Dispatcher.php, when called by the htaccess file, becomes part of the process of determining the page name to be displayed. The .htaccess file sends all traffic to it, it does a lookup in the database, finds the right file name, and sets the “location”. It’s much, much faster than trying to do all this redirection through the .htaccess file.

    So the thing to do is make a search-engine-friendly URL for any page that you create (even if it is done automatically) and store that in a database table, then use the dispatcher.php file to go get that file name and serve it up instead of the funky variable-filled URL that is not friendly to the search engines.

    If you need more help on this, we would be happy to consult with you on it. Contact me directly for a free initial consultation.

  12. Eric December 7, 2010 at 1:18 am #

    could you please give a code sample for dispatcher and htaccess as ho how this is implemented?

  13. Jere Matlock December 7, 2010 at 3:57 pm #

    Hi, Eric –

    If you need to set this up, you need someone to do it who knows what they are doing. It’s not for the faint of heart.

    Here’s an example: We had a “media. website. com” sub-domain, which was being hosted on another server. We consolidated hosting and moved all of the “media” content over to a blog, at “blog. website. com”

    In the “media” folder, we put an .htaccess with this code in it:

    Options +FollowSymLinks

    AddType text/html .html
    AddType text/html .htm
    AddType text/xml .xml

    AddHandler server-parsed .html
    AddHandler server-parsed .htm
    AddHandler server-parsed .xml

    RewriteEngine On

    RewriteCond %{HTTP_HOST} ^media.website.com
    RewriteCond %{REQUEST_URI} !^/dispatcher.php
    RewriteRule (.*) /dispatcher.php?file=$1 [R=301,L,QSA]

    That’s what does the “heavy lifting” for us.

    ——————–

    Then we have in “dispatcher.php” the following code to pull apart the pieces of the URI being requested, and look for it in the little table in the database with the old and new page names in it, and then set the location. The result is a clean shift from one URL to another, with a 301 code sent and the right URI being served for the request. Note that this replaces about 400 lines of .htaccess file.

    $request = $_SERVER[REQUEST_URI];
    $request = trim($request);
    $uriparts = explode('?', $request);
    $vars = explode('&', $uriparts);
    if ($uriparts[1])
    {
    parse_str($uriparts[1], $vars);
    }

    $file = array_shift($vars);
    $var = array_shift($vars);
    $pagevars = "";

    foreach ($var as $key => $value)
    {
    $pagevars .= "&$key=$value";
    }

    $pagevars = str_replace(" ","+", $pagevars);
    $pagevars = substr_replace($pagevars,"", 0,1);

    $query="SELECT * FROM redirs
    WHERE page = '/$file'
    AND qry = '$pagevars'
    LIMIT 1";
    echo "

    Query = $query

    ";
    $result = mysql_query($query);
    /*if (mysql_num_rows($result) == 1)
    {
    $row = mysql_fetch_array($result);
    $redirect = "http : // blog .thiswebsite .com" . $row[direct];

    header("Location: $redirect");
    }
    else {

    header("Location: http : / /blog. thiswebsite. com/default-page.php");
    } */

  14. sarala February 15, 2011 at 9:00 am #

    this is really wonderful and good and clarity explanation about the ht access. thank you for sharing.
    http://www.seoupdates-sarala.blogspot.com

  15. Calvin March 29, 2011 at 2:48 pm #

    KUDOS!!!

    I have looked for how to do what you describe in your last comment for 3 weeks with no luck. I never though it would be as easy as routing through a PHP script! I was trying to figure out a way to get .htaccess to read a database ( hits forehead with palm ).

    Thanks a lot!!

  16. Jere Matlock March 29, 2011 at 9:41 pm #

    Hi, Calvin –

    Yes, we went that route, too. We tried for a week to get our .htaccess file to do a lookup (which it is supposed to be able to do) but we could NOT get it to work on our server, despite involving Tier II tech support and calling in an outside “expert”. Nothing doing! So we had to regroup. They say “Necessity is the mother of invention” but I think it is more like “Necessity is the mother of circumvention” in this case.

    Best,

    Jere

  17. Archana September 29, 2011 at 5:48 am #

    Hey,

    I am working in .net … Could you please help me how can I make the search engine friendly URLs without making HTML pages for them please
    ..IF you find any answer then please mail me at:

    Archanazohns@gmail.com

  18. Jere Matlock September 30, 2011 at 12:03 am #

    Hi, Archana – I have no idea how to do this in .net. Not my area of expertise at all. I would be very surprised if it is possible in .net.

    Best of luck to you

  19. Geoff January 18, 2012 at 2:34 pm #

    What is the code for the mod rewrite I would use to eliminate part of a URL so it’s more user friendly? I do not want a rewrite or redirect of one URL. I want all 5000 dynamic pages to be displayed and rewritten without a section of the URL.

    Every single page of my dynamic search pages has a prefix of /m/12794/ such as http://pdx.pohlrealestate.com/m/12794/pdx_home_search or http://pdx.pohlrealestate.com/m/12794/homes_for_sale_downtown_portland

    Is it possible to set up a rule or condition in the .htacess file so that everytime a /m/12794 is called that is goes to that page and rewrites these URL’s to

    http://pdx.pohlrealestate.com/pdx_home_search or http://pdx.pohlrealestate.com/homes_for_sale_downtown_portland

    without the /m/12794 instead? Any help is appreciated.

  20. Vivek February 18, 2012 at 2:59 pm #

    Hey i am trying something like this in my .htaccess file
    RewriteEngine On
    RewriteRule ^/blog/where_is_session_information_stored /blog/post_detail.php?id=34 [L]
    it means when i go to /blog/post_detail.php?id=34 i will see /blog/where_is_session_information_stored in the browser right ? it doesnt work like that or if i go to /blog/where_is_session_information_stored, directly from the browser i dont see anything there as well. is there anything i am doing wrong ?

  21. Joanne April 3, 2012 at 5:35 pm #

    Hi…so far seems pretty straightforward. i have an eCommerce site that uses pages like:

    http://apricotking.com/detail.php?prodid=DF-21

    If I have to manually enter the SEO friendly URL manually into the .htaccess file, doesn’t that go against the point of having a datadriven site? Is there a way to generate an .htaccess file on the fly so that the rewrites were updated to the current data in the database?

    Thanks.

  22. Jino R Krishnan April 8, 2012 at 4:28 am #

    Hi,
    Nice Tutorial, but unfortunately not convienient for starters/beginners for beginners you gave link in the comment area [http://www.javascriptkit.com/howto/htaccess.shtml ] that should be read first…
    Any way Thanks dude…

  23. Jere Matlock August 29, 2012 at 8:14 pm #

    We use xCart when we build ecommerce sites, because it has this feature built into it. It’s called “clean urls” in xCart, and there is a field for each page, which is the preferred “clean” URL that you want for each product page. If your site were built in xCart, this page:

    http://apricotking.com/detail.php?prodid=DF-21

    would look like this:

    http://apricotking.com/dried-blenheim-apricots

    Not only is the page name more informative to humans who see it, it is very understandable to Googlebot.

    It also uses the “clean” URLs in the canonical tag instead of the non-comprehensible detail.php?prodidDF-21.

    This is not meant to be a commercial for xCart – it just points out the fact that other shopping carts SHOULD do this. See if those options are available in your shopping cart.

    If not, you might want to set up your .htaccess as I have advised in the post above, so that you have your own version of clean URLs for your customers, and for Google and Bing.

  24. Jere Matlock August 29, 2012 at 8:27 pm #

    It’s hard for me to debug individual code samples remotely.

    The thing to do is study the available sites on .htaccess out there. I have two that I go back to a lot when trying to make something work:

    http://softexpert.wordpress.com/2007/10/15/learn-htaccess-in-10-minutes/

    http://www.thejackol.com/htaccess-cheatsheet/

    There are also some very good books on the subject: I have a copy of “The Definitive Guide to Apache mod_rewrite” by Rich Bowen. It has helped me out of more than one bind.

  25. Jere Matlock August 29, 2012 at 8:33 pm #

    Yes, I believe it is possible. I do not have the exact code at my fingertips.

    See the sites I’ve mentioned above that offer basic tutorials on .htaccess.

    Using .htaccess itself is fairly straightforward — what is NOT so straightforward is the use of regular expressions (regex) within the .htaccess file to match the strings you want to change or rewrite. That’s where it gets tricky.

    “The Definitive Guide to Apache Mod_rewrite” by Rich Bowen is worth purchasing if you are trying to do things like this on a regular basis.

    For a one-off programming task, go to fivr.com or elance.com and put out a request for someone to code it for you. There are code monkeys out of work out there who can use the work, even on a small project like this.

  26. Sanjay Sharan November 14, 2013 at 11:32 am #

    Sir,

    I have some of the pages in site which is displayed as “http://www.excellup.com/Story/Default.aspx?storyId=16”.
    How to rewrite this in .htaccess.

  27. Jere Matlock November 14, 2013 at 2:36 pm #

    Hi, Sanjay –

    Your site is hosted in the Microsoft IIS 6.0 environment. It does not use .htaccess files, which are only used in the Unix/linux environment. So you cannot use the .htaccess tricks I have outlined to do these things. You should talk with a Microsoft IIS developer and see if you can do something similar to what I outline here.

    Best regards,

    Jere Matlock

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

All Rights Reserved.