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

Scroll to Top jQuery plugin illustration

If you happen to have on your site some pages that are a bit long, and therefore will lead your users to scroll down quite a bit to read your content, they may not have the patience to scroll again to get back up to the top. That's where this little plugin, hand made by NOE interactive comes in handy. Just put it on your website, and it will help your users get back to the top of pages with a single click, and with a small smooth animation (how nice is that :) ).

In this article featured on NOE interactive, you'll learn how you can install the jQuery plugin on your website. There's a complete step by step guide as well as a demonstration. If you wish to download the plugin, it's also hosted on Github.

Read more
How to create your own rss feed illustration

RSS is a way of easily keep your site's readers up to date with your latest content. That's a reason why it is widely used by the famous blogs and big sites. Once someone subscribes to an RSS feed, he'll get a notification every time you post some new content to your site. It helps fidelizing your users, therefore improving your traffic. It is definitely worth implementing. This tutorial will guide throught the steps involved in the creation of your own RSS feed from scratch, and based on your site's existing platform.

Read more
Getting started with React.js illustration

As a lead developer, I watch the web development market for solid trends (not the hype ones), and see if they could be a tangible addition to our workflow. Like Angular a few years ago, React has gained enough momentum to catch my attention. I decided to try it out in a side project to get a better understanding of how it works. Here are a few things I've noted from our first encounter. This is a beginner's point of view, not a React expert's one, so if you see any mistakes, don't hesitate to let me know, I'll update the article accordingly.

Read more
RT @DavidCormand: 2040. C’est effectivement un signal très « fort » et très « concret »: Vous pouvez continuez comme avant à produire et ut…10 Dec / 17:55