How To Make Dynamically Generated SEO-Friendly URLs Using PHP And .htaccess
With SEO becoming such an important part of web design, many of us will want our URLs to contain keywords wherever possible. When you create a static website, you name each page on the website manually. For example, if you had a page titled “McBonio explains SEO”, you might name it “mcbonio-explains-seo.htm”. However, in the case of single scripts that generate multiple pages of content, like the above example, our URLs don’t tend to contain the name or title of the content generated. In this case, how would we get our keywords into our URL?
The solution lies in htaccess. For those of you who don’t already know, htaccess is a configuration file that lies in the root directory of a website. Its file name is simply “.htaccess”. It has various uses, such as telling browsers (and search engines) that a website’s location has permanently changed (e.g. when you have moved a website to a new domain name). Using htaccess, we can combat our problem of generating SEO-friendly URLs dynamically.
Specifically, what we’ll be doing is directing the user to a fake URL that contains our keywords. Then, in our htaccess file, we will use the rewrite engine (this is used to modify the appearance of URLs) to redirect the user from the fake URL to the real one.
In the above example, we have a page called product.php and we are are parsing a variable to that page called “id”. When the page receives the “id” variable, it uses it to retrieve the product information from a database. What we want is the name or title of the product – we will use this for our fake URL. For the sake of argument, let’s say that our product’s ID is 37 and its name is “Pink Shirt and Tie”. The first thing we need to do is generate the fake URLs on our website – we need to do this wherever we link to the page on the website. So, with our pink shirt example, our link needs to change from product.php?id=37 to product-37-Pink Shirt and Tie. Our links therefore take the following form <a href=”product-37-Pink Shirt and Tie”>
Next, we edit our htaccess file. We need to add three lines; the first two lines turn on the rewrite engine, the third line modifies our URL. The three lines are as follows: -
RewriteEngine On
RewriteBase /
RewriteRule ^product-([0-9]+)-(.+)?$ product.php?id=$1
The first two lines are pretty straight-forward. Let’s analyse the third line – this is where the magic happens. I’ve illustrated the three key parts to this line in the image below. The first part, “RewriteRule”, simply states that we are creating a rule. We then provide two arguments; the second part is the URL we want to modify and the third part is the way in which we want to modify it:

We want to modify any URL that starts with “product-”, continues with a number, is followed by another “-”, then ends with pretty much anything. You will see that the two parts that follow “product-”, either side of a “-”, are wrapped in brackets. This identifies them as items of data for the purpose of the second argument. This is illustrated below, in red text:
RewriteRule ^product-([0-9]+)-(.+)?$ product.php?id=$1
The third and final part of the line is what we want to do to the URL – in other words, what we want to change it to. We want to load product.php and parse the variable “id”, so we take the number part of the fake URL and put it on the end of our real URL. The number part of the fake URL is the first part after “product-” (this is the first item of data illustrated in red text above). The way we retrieve this is with “$1” in the second argument – this simply calls the first item of data from the URL we wish to modify. If we wanted the second item of data, we would use “$2”, and so on. But we only need the first part, i.e. the product’s ID number, so we ignore everything after that. In other words, the following three URLs would all have exactly the same effect: -
product-37-Pink Shirt and Tie
product-37-pinkshirtandtie
product-37-Mcbonio loves wearing pink shirts!
…because we are only processing the fake URL as far as the ID number. All three of the above URLs would point to: product.php?id=37
If you are SEOing URLs within a directory, simply amend the third line of the htaccess code to include the directory as follows (I’ve used “shop” as the directory name):
RewriteRule ^shop/product-([0-9]+)-(.+)?$ shop/product.php?productID=$1
That’s it – I hope you found it easy to follow and have successfully started dynamically generating SEO-friendly URLs on your website. Please bear in mind that I’m not an expert on htaccess and, as I write this, I have had several glasses of wine (and a Jaffa Cake). However, it works perfectly on my websites – so it should work for you too. If you have any comments, suggestions, criticisms or anything else that you’d like to contribute, please don’t hesitate to scroll down and do your thing. Thanks for taking the time to read this





















November 27, 2009
Thanks for the awesome tutorial Adam, really great read
November 28, 2009
Thanks , it’s useful
November 28, 2009
Thanks for the awesome tutorial, but i read it very simple, can you make the tutorial for a complex situation?
November 28, 2009
Hi Viettel, let me know your requirements and I’ll see what I can do.
November 28, 2009
How would I make it so it’s like this:
http://www.mysite.com/product/some-product
And if the name “some-product” already existed it would change to
http://www.mysite.com/product/some-product-2
Something like that. Similar to wordpress.
November 29, 2009
Thanks for the awesome tutorial,it is so simple to make understood.
November 29, 2009
Hi Ben
What you would need to do for your example is firstly ensure that products in your database cannot have duplicate names. Then change the destination page so that it retrieves the product by its name instead of its ID number. So, you would have something like:
product.php?name=$name
Then you would direct users to a fake URL, something like:
product/product-name
Then you would use htaccess to retrieve the product name from the fake URL and parse it to the page as the $name variable, so the line in htaccess would be something like:
RewriteRule ^product/(.+)?$ product.php?name=$1
Hope that makes sense
December 2, 2009
When most bloggers see things like mod rewrite and htaccess they run for the hills, but it really isn’t that complicated and you have provided a well written and detailed tutorial!
December 3, 2009
This is great information and I can see where it would be most helpful when building a new site: however, what about an existing site that has several thousand pages indexed with Google. What impact would making this change have on those pages if any?
December 7, 2009
Hi Ray
I’ve not tried this on an existing website before so I’m not certain. However, I would expect that Google would index your new URLs just fine – it just might take some time for it to stop indexing the old URLs (especially if the website has external inbound links pointing to the old URLs).
Just make sure you update your sitemap, as well as all the links within your site, with the new URLs. You may not be able to stop Google indexing the old URLS but you can certainly make sure it starts indexing the new ones.
Adam