How to make SEO friendly urls

How to make SEO friendly urls

It's now quite common to swap the old url format containing file extensions and non explicit query strings by SEO friendly ones, only made of keywords and slashes, hence their name.

There are several techniques to do so, and I certainly do not have the pretention to say that this one is the best of all, but it is the one I use in personal projects as it works nicely, and it is robust and dynamic.

It makes use of an .htaccess file to rewrite the urls, of a php function to parse the given parameters, and a content manager to serve the appropriate content according to them.

Before we start I'd like to make a personal thanks to Josh Moont for his precious help.

Thank You for Downloading

I'm glad that you found my work useful. If you did, it might help some other people too. So why not helping me spread the word with a tweet? You could also buy me a coffee to thank me for my code and explanations if you prefer ;).
I hope you'll enjoy your download. Regards. Jeremy.

How to setup

Step 1: The .htaccess file

As we've said in the introduction, the first element that stands in the process of rewriting is the .htaccess file. If you do not already have one on the root of your website, just create a file with no name and the extension .htaccess there. Open that file, and copy the following code in it:
  1. RewriteEngine On
  5. ErrorDocument 206 /Error/206
  6. ErrorDocument 301 /Error/301
  7. ErrorDocument 400 /Error/400
  8. ErrorDocument 401 /Error/401
  9. ErrorDocument 403 /Error/403
  10. ErrorDocument 404 /Error/404
  11. ErrorDocument 500 /Error/500
  12. ErrorDocument 503 /Error/503
  14. ## Page rewrite ##
  16. RewriteCond %{REQUEST_FILENAME} !-f
  17. RewriteCond %{REQUEST_FILENAME} !-d
  18. RewriteRule ^(.*)$ index.php?path=$1 [NC,QSA]
Ok so what does that actually mean? Simple. On line 1, we specify that we want to turn on an Apache functionality called Mod_Rewrite. Mod_rewrite is an Apache-based rewrite engine for dynamically rewriting URLs. It's built into Apache servers natively, though not enabled by default, that's why we turn it on here. The lines 3 to 12 are actually beyond the scope of this tutorial but I left them there anyway as they are still useful. In fact they allow you to create a custom error page and to redirect to that page when a specific error happens on your server, the 404 error for example. It's nicer for the user to face a custom error page than the default ones. Let's get back to our rewrite now. On line 16 and 17, we have 2 lines that tell the server NOT to rewrite the urls leading to files that exist on the server, such as images for example, or js files, stylesheets on so on. So in fact, all those files will be accessed in the old fashioned way, and the rewrite will only be focused on pages, which saves a lot of time as you'll understand later on. And Finally, on the last line, that expression specifies that every url, that is not a file, will be sent to the file index.php for analysis under the name "path". NC means it's not case sensitive, and QSA that the redirect still keeps the $_GET variables so in your urls, you can use slashes and also old fashioned query strings. (which is not the point really, but it still works...) This step marks the end of the .htaccess role in our rewrite. To summarize, it doesn't deal with files, and redirects any other url to the index.php under the name "path".

Step 2: Dealing with the parameters

Now that the urls are redirected from the .htaccess, we are going to use slashes in our urls and not query strings anymore. Because this format of url is not understood by the server in the first place, we need a mechanism to parse the given parameters into a form that is going to be useful for the server. In order to do so, we'll use the function get_url_params showed below:
  1. function get_url_params(){
  3. //Get the query string made of slashes
  4. $slashes=explode("/",trim(htmlentities(array_shift($_GET),ENT_QUOTES),"/"));
  6. //Extract the asked page from those parameters
  7. switch(count($slashes)){
  8. case 0:
  9. $params['page'] = "home";
  10. break;
  11. case 1:
  12. $params['page'] = array_shift($slashes);
  13. break;
  14. case ((count($slashes) % 2)==1):
  15. //odd
  16. $params['page'] = array_shift($slashes);
  17. break;
  18. default:
  19. //even
  20. $params['page'] = array_shift($slashes);
  21. $params['myparam'] = array_shift($slashes);
  22. break;
  23. }
  25. //Process the parameters by pairs
  26. $cpt=1;$param="";
  27. if(!empty($slashes)){foreach($slashes as $get){
  28. switch($cpt){
  29. case 1: $param=htmlentities($get,ENT_QUOTES);$cpt=2; break;
  30. case 2: $params[$param] = htmlentities($get,ENT_QUOTES);$cpt=1; break;
  31. }}}
  33. //Process the $_GET parameters if any
  34. if(!empty($_GET)){foreach($_GET as $name=>$get){
  35. $params[$name] = htmlentities($get,ENT_QUOTES);
  36. }}
  38. return $params;
  39. }
Again I remind that there are several methods to do so, but this is the way I like to do. Explanation: First of all, on line 4, we get the "path" sent by the .htaccess file, for analysis, meaning that we split it according to the slashes and we count how many different parts it gives. Here's the principle (there are 4 different possible cases). If we do not have any parameter, the path is empty, we'll therefore display the home page.(lines 8-10) If we only have ONE parameter, it will be the page to display.(line 11-13) If we have an ODD number of parameters, the first one will be the page, and then we'll match up the other parameters by key=>values pairs.(lines14-17) And finally, if we have an EVEN number, the first one will be the page, the second one the subpage, and afther that, again we'll match up the parameters by key=>values pairs.(lines 18-22) Now that we've extracted the page to display from the parameters, we match them up by pairs (lines 25-31). As we've said in the introduction, this method is quite robust as it works with $_GET parameters too. So if there are any specified in the url, we match them up by pairs here, so they will be available later on (lines 33-36). For example, the url /resource/param1/value1/param2=value2, mixing slashes and query strings, will return $params = array("page"=>"resource","param1"=>"value1","param2"=>"value2"); To summarize this step, first we get the path from the .htaccess, we work out the page we want to display from it, and we match the other parameters by key=>values pairs. The parameters are now ready to be used by the content manager.

Step 3: The Content Manager

Once we've nicely reordered the parameters, we need to display the page targeted by the given url. To do so, I like to use a content controller, in order to have an MVC structure. My controller is structured as shown:
  1. require_once("Path_to/Globals.php");
  2. $params = Globals::get_url_params();
  3. $module = $params['page'];
  4. if (!empty($module)) {
  5. switch ($module) {
  6. case "home":
  7. $page = "Path_to/home.php";
  8. break;
  10. case "resources":
  11. $page = "Path_to/resources.php";
  12. break;
  14. case "Error":
  15. $page = "Path_to/error.php";
  16. break;
  17. .
  18. .
  19. .
  20. default:
  21. $page = "Path_to/home.php";
  22. break;
  23. }
  24. } else {
  25. $page = "Path_to/home.php";
  26. }
  29. require_once("Path_to/header.php");
  30. require_once($page);
  31. require_once("Path_to/footer.php");
The get_url_params() function has been put into a separate class called Globals, that's why include that file on line 2. We can then call that function to get the parameters (line 3), and especially the page we want (line 4). We then have a switch case statement that figures out what file needs to be included according to the wanted page. This is how we match the parameters given in the url with the corresponding files. When you want to add a new page to your site, you just have to add a case in this content manager. In lines 34,35 and 36, the manager will finally include the pages for display. I like to use a separate header and footer, containing the code common to every page, it is easier to maintain. There we go, 3 easy steps to make your own friendly url system from scratch! No excuses for those endless and meaningless query strings any more now!

5 Responses to How to make SEO friendly urls

  1. Thanks I wil ltry this at my Tibia aCcount website thanks so much I hope it works with no problems. Its just htat I dont know where to put the php codes.

  2. Great tutorial.

  3. Thanks for the tutorial, you explained it very clearly!

  4. Thanks a lot. I'm mainly using WordPress so I won't need it but once I start making custom websites I'd definitely use this.

    • tesdt

Leave a Reply

Your email address will not be published. Required fields are marked *

Other Useful Resources

Retour sur Blend Web Mix 2015 illustration

Blend Web Mix, c'est la conférence Lyonnaise du Web. C'est une chance d'assister à des des conférences enrichissantes et motivantes, de rencontrer des gens intéressants, le tout dans le cadre toujours très agréable de la cité internationale. Cette année encore, l'édition a été riche en enseignements. Retour sur les conférences auxquelles j'ai assisté, et ce que j'ai pu en retirer.

Read more
A guide to Ajax Interactions with jQuery illustration

The fantastic jQuery library revolutionized the way javascript is being written around the globe. It's been globally acclaimed and adopted, resulting in an award for best open source project in the end of 2009.

In this article, we are going to see how we can use the power of this library to create your own Ajax request effortlessly, to make pages communicate in a user friendly way. Thank you jQuery team, the days of javascript darkness are over!

Read more
Standardizing development environments with Vagrant illustration

This is the first article of a series in which we'll explain our development process industrialisation. We'll describe how we went from a team of individuals doing things together but artisanally, to a more industrial and qualitative approach. This first topic talks about how we standardized our development environments with Vagrant.

Read more
@Cabaroc Pour ceux que le sujet intéresse, cette marque et cette page sont cités en exemple dans cet article intére… May / 11:05