After being requested to write a tutorial a few times, I've finally found the time to create a mod_rewrite tutorial for vBulletin 3. What this tutorial will allow you to do is make your vBulletin forum search engine spiderable - for Google and all the others.

<< update >>

This hack is now obsolete! Please visit the new version:

http://www.daniweb.com/techtalkforums/thread35147.html


<< end update >>

Step One

My version of making vB 3 search engine spiderable is unique because I rename the actual URLs for each forum forum-name.html instead of just forum1.html, forum2.html, etc. Therefore, the first thing that needs to be done is to tell the vBulletin forum to parse the names of each forum and create an equivalent that can be used in a URL. This can be done by editing the file includes/functions_forumlist.php.

In that file, do a search for:

// do light bulb
	$forum['statusicon'] = fetch_forum_lightbulb($forumid, $lastpostinfo, $forum);

Directly above that, add the following code:

// added by dani
	$forum['url'] = strtolower(
	 str_replace(" ", "-",
	 str_replace("/", "-", $forum['title'])
	 )
	);
// added by dani

By adding that code, we did a few things. The first thing that we did was parse the title of each forum and replace each instance of a space or the / character with a dash, and then convert all characters to lowercase. Therefore, a forum with a title "PHP/ASP" will be parsed as "php-asp" and a forum with a title "DaniWeb Community" will be parsed as "daniweb-community". The second thing that we did here was store the parsed version in the $forum variable, which we can now use in the vB3 templating system. In other words, the same way as we have always been able to use $forum in vB3 templates, we can now use $forum wherever we want as well.

Step Two

The next step is to update all of the vB3 templates. To do this, first go into the vB Admin control panel. Then, click the Style Manager, and select to Edit Templates for the style you'd like to use. The following templates will need to be edited:

Within the FORUMHOME template group:

forumhome_forumbit_level1_nopost

<a href="forumdisplay.php?$session[sessionurl]f=$forum[forumid]">

forumhome_forumbit_level1_post

<a href="forumdisplay.php?$session[sessionurl]f=$forum[forumid]">

forumhome_forumbit_level2_nopost

<a href="forumdisplay.php?$session[sessionurl]f=$forum[forumid]">

forumhome_forumbit_level2_post

<a href="forumdisplay.php?$session[sessionurl]f=$forum[forumid]">

forumhome_subforumbit_nopost

<a href="forumdisplay.php?$session[sessionurl]f=$forum[forumid]">

forumhome_subforumbit_post

<a href="forumdisplay.php?$session[sessionurl]f=$forum[forumid]">

All need to be replaced with the following:

<a href="$forum[url].html">

Something even simpler than making all those changes in multiple templates is to use the vBulletin replacement manager feature. In fact, all of the above steps would only require one replacement :)

Step Three

Now that we have made all the changes to point to our forums, we will need to make changes to point to the threads. Our thread URLs will be in the form of thread123.html.

A few changes will need to be made to the forumhome_lastpostby template, which we just finished editing above.

PART 1

<a href="showthread.php?$session[sessionurl]goto=newpost&amp;t=$lastpostinfo[lastthreadid]" title="<phrase 1="$lastpostinfo[lastthread]">$vbphrase[go_first_unread_in_thread_x]</phrase>"><strong>$lastpostinfo[trimthread]</strong></a>

will need to be replaced with:

<a href="newpostinthread$lastpostinfo[lastthreadid].html" title="<phrase 1="$lastpostinfo[lastthread]">$vbphrase[go_first_unread_in_thread_x]</phrase>"><strong>$lastpostinfo[trimthread]</strong></a>

PART 2

<a href="showthread.php?$session[sessionurl]goto=lastpost&amp;t=$lastpostinfo[lastthreadid]"><img class="inlineimg" src="$stylevar[imgdir_button]/lastpost.gif" alt="$vbphrase[go_to_last_post]" border="0" /></a>

will need to be replaced with:

<a href="lastpostinthread$lastpostinfo[lastthreadid].html"><img class="inlineimg" src="$stylevar[imgdir_button]/lastpost.gif" alt="$vbphrase[go_to_last_post]" border="0" /></a>

PART 3

<a href="showthread.php?$session[sessionurl]goto=lastpost&amp;t=$lastpostinfo[lastthreadid]"><img class="inlineimg" src="$stylevar[imgdir_button]/lastpost.gif" alt="$vbphrase[go_to_last_post]" border="0" /></a>

will need to be replaced with:

<a href="lastpostinthread$lastpostinfo[lastthreadid].html"><img class="inlineimg" src="$stylevar[imgdir_button]/lastpost.gif" alt="$vbphrase[go_to_last_post]" border="0" /></a>

Step Four

We will also need to edit the threadbit template in four locations.

PART 1

<a href="showthread.php?$session[sessionurl]goto=lastpost&amp;t=$thread[threadid]">

will need to be replaced with:

<a href="lastpostinthread$thread[threadid].html">

PART 2

<a href="showthread.php?$session[sessionurl]goto=newpost&amp;t=$thread[threadid]">

will need to be replaced with:

<a href="newpostinthread$thread[threadid].html">

PART 3

<a href="showthread.php?$session[sessionurl]t=$thread[threadid]$thread[highlight]">

will need to be replaced with:

<a href="thread$thread[threadid].html">

PART 4

<a href="showthread.php?$session[sessionurl]t=$thread[threadid]&amp;goto=lastpost$thread[highlight]">

will need to be replaced with:

<a href="lastpostinthread$thread[threadid].html">

Step Five

This next part is the most important, because it actually uses an .htaccess file to do the mod_rewrite. I am assuming that you have an Apache web server with mod_rewrite enabled.

Create a file called .htaccess and upload it to the root of your forum (the same directory as your forumdisplay.php and showthread.php files). Edit this file to include the following:

RewriteEngine on
Options +FollowSymLinks
RewriteRule ^thread([0-9]+).html$ showthread.php?t=$1 [L]
RewriteRule ^lastpostinthread([0-9]+).html$ showthread.php?goto=lastpost&t=$1 [L]
RewriteRule ^newpostinthread([0-9]+).html$ showthread.php?goto=newpost&t=$1 [L]
RewriteRule ^forum([0-9]+).html$ forumdisplay.php?f=$1 [L]

Step Six

However, we also need to add more to this .htaccess file => one line for each and every forum we have. Remember how above we told vBulletin to parse our forum titles and convert them to forum URLs? Well, we have to unfortunately do this manually now for each forum we have. Follow the example below:

RewriteRule ^forum-one.html$ forumdisplay.php?f=1 [L]
RewriteRule ^forum-two.html$ forumdisplay.php?f=2 [L]
RewriteRule ^forum-three.html$ forumdisplay.php?f=3 [L]

A RewriteRule line should be created for each forum you have, and should always remain uptodate (should you edit/remove forums). Keep in mind that all spaces in a forum name should be replaced with dashes and all forward-slashes in a forum name should be replaced with dashes as well.

The reason why we have to do it this way is because suppose we have a forum called "DaniWeb PHP". It would be really great if we could create a custom php script called forumjump.php which would allow us to do forumjump.php?f=daniweb-php. The php file would then convert daniweb-php to "DaniWeb PHP". It would then search the MySQL database for a forum whose title is "DaniWeb PHP". It would then find the corresponding forum number. And then redirect the user to forumdisplay.php?f=XX. However, the overhead for doing that would be ridiculous. Every single time any user on your forum would visit a new forum or thread page, they would first need to have a php page do a database lookup and then a redirect.

To eliminate that overhead, we create a new entry in the .htaccess file for each forum. This way, we let Apache handle the forum name to forum ID number conversion. While it's true that mod_rewrite does have a lot of overhead, I don't think it would be as bad as if were done the other way.

If these last two paragraphs went over your head, don't worry about it. It was just a bit of a sidetracked explanation of why I have chosen to do things the way I have.

Step Seven

There are some more changes that need to be made, and these are in editing the navbits on the forumdisplay and showthread pages. We start by editing the navbar template within the Navigation / Breadcrumb templates group.

There are two instances of the following in that template:

<a href="$vboptions[forumhome].php?$session[sessionurl]" accesskey="1">

Both instances should be replaced with:

<a href="./" accesskey="1">

Step Eight

To finish editing the navbit breadcrumb, we must edit the .php files directly. To do this, we edit both the forumdisplay.php as well as the showthread.php files:

Do a search in forumdisplay.php for:

// draw nav bar

and do a search in showthread.php for

// draw navbar

A few lines below those lines, in both files, you will see a loop that looks somewhat like

foreach ($parentlist AS $forumID) {...}

Replace that loop with the following:

foreach ($parentlist AS $forumID)
{
$forumTitle = $forumcache["$forumID"]['title'];
$navbits["forum$forumID.html"] = $forumTitle; // edited by dani
}

Unfortunately, what we're doing here, is making the forums in the breadcrumb point to forum1.html and forum2.html. Due to reasons that are beyond the scope of this tutorial, it is impossible for us to use forum-name.html here. Basically, the way that vBulletin uses recursion to generate the breadcrumb, the forum ID numbers must be in the URL for it to work correctly. If you did use $navbits["forum$url.html"] instead of $navbits["forum$forumID.html"] then vBulletin would create all navbar breadcrumbs assuming that the forum you're currently browsing is a top-level forum. In other words, it is not a subforum of anyone. The way I figure it, at least forumXX.html is better than forumdisplay.php?f=XX.

Step Nine

Take a deep sigh of relief! You're done :) Now comes the hard part. You'll have to wait for google to spider your new clean URLs. ;)

Edited 3 Years Ago by Dani

Comments
this post needs to be green. it

My site has well over 300 forums and subforums so the idea of making an entry for each one is no good...

Wouldn't it be easier just to give the forums numeric ids and use modrewrite to redirect based upon that information so you didn't have to keep updating htaccess?

Yes, here at DaniWeb we have over 90 forums, and therefore we use numeric IDs, which eliminates creating a custom line for each forum in the .htaccess file. However, named forum URLs (especially ones which are keyword-rich) are very good for SEO purposes.

Regardless, the following are the differences should one want to go about using numeric forum IDs:

Step One => not needed

Step Two => All instances should be replaced with:

<a href="forum$forum['forumid'].html">

instead of with

<a href="$forum['url'].html">

Step Six => not needed

Everything else would remain the same as the above tutorial.

I really liked the idea of the titles in the url so I played aroung with modrewite and came up with this:

RewriteRule ^/f([0-9]+)-(.*)\.html$ /forumdisplay.php?forumid=$1 [L]

This tells modrewrite to forward any url fXID-XTEXT-.html to the forumdisplay.php?forumid=$XID url, this way you can have any text you want but since the ID is used in the URL, it is possible to use one rewrite rule for every forum.

To go along with this, you need to modify your forumbit templates to use the link

<a href="f$forum[forumid]-$forum[url].html">

No files need to be changed as far as I can recall.

So far I am testing this on a template that my users don't access so please confirm this works for you before putting it on a live site.

Thanks for the wonderful hack, I had limited spidering in the past and it worked wonders so I can only expect even better results from this deep spidering system.

Thanks so much Ted for your addition. At first glance, it looks like it should work fine. To everyone else out there, what Ted is proposing is that the URL look like this, given that forum #2 has the name DaniWeb Community: f2-daniweb-community.html - The forum system parses the forum id as 2 (hence no need for a loooong .htaccess) and the URL is still keyword rich.

Thanks for this fantastic hack, cscgal :)

I suppose this will work for VB3.0.3 and would you provide help if vBulletin releases a new version and this hack needs to be updated ?

This hack should work for all gold versions of vB 3. I'll offer as much assistance as I possibly can. However, I can't guarantee support for not-yet-released versions of vB as just last week my vBulletin license to the members area expired :) But there shouldn't be any problems anyways - and if they are, just give any of the great guys over here a hollar.

Since I can't seem to edit my post, I have a little update... if you use my code please change [L] to [R] in your htaccess file which redirect to a url instead of naming the page to that url. This is less optimal for your SEO placement but it won't harm things like the quick style chooser which rely on a dynamic url existing.

Thanks cscgal

Ted, if i didnt allow style changes then i should continue to use [L] ?

Yes, [L] is much better than [R] for SEO reasons. By using [R], the user is actually physically redirected to the php? URL. I don't enable style changes, and have never ran into any problems with any other forum feature.

Ted, I will look into modifying the code that generates the style dropdown so that everyone can use [L].

I see, btw is there a demo of this hack somewhere ? Or is this forum already the working example without any extra hacks :)

Also, i noticed announcements are still using the normal URL ?

The quickstyle chooser is run via javascript using the following code:

function switch_styleid(selectobj)
{
	var styleid = selectobj.options[selectobj.selectedIndex].value;

	if (styleid == "")
	{
		return;
	}

	var url = new String(window.location);
	var fragment = new String("");

	// get rid of fragment
	url = url.split("#");

	// deal with the fragment first
	if (url[1])
	{
		fragment = "#" + url[1];
	}

	// deal with the main url
	url = url[0];

	// remove styleid=x& from main bit
	if (url.indexOf("styleid=") != -1 && is_regexp)
	{
		re = new RegExp("styleid=\\d+&?");
		url = url.replace(re, "");
	}

	// add the ? to the url if needed
	if (url.indexOf("?") == -1)
	{
		url += "?";
	}
	else
	{
		// make sure that we have a valid character to join our styleid bit
		lastchar = url.substr(url.length - 1);
		if (lastchar != "&" && lastchar != "?")
		{
			url += "&";
		}
	}
	window.location = url + "styleid=" + styleid + fragment;
}

I have no idea how to make it work properly so for now I must stick with [R] flags.

Thanks for sharing this, I just got it setup on my forums. I'm using V3.0.3 and found a couple of the instructions didnt work for me.

Heres what I changed.

In step two it asks to replace all with the following:

<a href="$forum['url'].html">

But I got an error so had to change to:

<a href="$forum[url].html">

In Step four Part one I had to use:

<a href="lastpostinthread$thread[threadid].html">

Instead of the instructed:

<a href="lastpostinthread[threadid].html">

All works fine now.

I also used the rewrite rule Teds posted:

RewriteRule ^/f([0-9]+)-(.*).html$ /forumdisplay.php?forumid=$1 [L]

But as my .htaccess file is in my forum directory I had to remove the /'s to make it work:

RewriteRule ^f([0-9]+)-(.*).html$ forumdisplay.php?forumid=$1 [L]

Thanks again :mrgreen:

It may be the way I posted it:

<a href="lastpostinthread[threadid].html">

That is the code as instructed in the first post.

I had to chage it to this:

<a href="lastpostinthread$thread[threadid].html">

Also, theres no reply with quote buttons in any of the posts apart from the first post of this thread. :?:

Yes, that makes much more sense! As to your question, that's because there are limited features available to the DaniWeb tutorial threads. The idea is that all replies be comments / responses to the original article.

I've been testing this on a new install, but for some reason I have the simple issue of "forumdisplay" is showing as the normal dynamic link, rather than the HTML form. It's probably a small mistake, but if there are any pointers to which part of the instructions I possibly messed up on, that would be most appreciated.

Look at all of the templates in the FORUMHOME template group and replace all occurrences of <a href="forumdisplay.php?..."> with <a href="$forum['url'].html">

Edited 3 Years Ago by Dani: Formatting fixed

I tried this and joined here after your post at seoforums. I need your help. There were a few changes from your vb 3.0.1 to vb 3.0.3.

I put the changs in that you states through your steps. First off thanks for the post and the mod, it is outstanding. I was wondering if you could help me! Is there anyway that you would be willing to look at my test forums and tell me what is wrong with what I did

Mike

http://www.sportsrant.com/testforums


this is what my htaccess file looks like!

RewriteEngine on
Options +FollowSymLinks
RewriteRule ^thread([0-9]+).html$ showthread.php?t=$1 [L]
RewriteRule ^lastpostinthread([0-9]+).html$ showthread.php?goto=lastpost&t=$1 [L]
RewriteRule ^newpostinthread([0-9]+).html$ showthread.php?goto=newpost&t=$1 [L]
RewriteRule ^f([0-9]+)-(.*).html$ forumdisplay.php?forumid=$1 [L]

I sent this email to another VB member here to see one problem with this tweak

he only thing that gets me about this is from the forums home page! (EXAMPLE)

This link here: http://www.sportsrant.com/forums/newpostinthread3501.html takes you to the latest thread like it should: http://www.sportsrant.com/forums/showthread.php?p=58579#post58579 and I do not believe this is good for SEO! If you go into that forum, even on your site, and click on http://www.sportsrant.com/forums/thread3501.html which is the same post and actually goes to the thread. Do you understand where I am coming from! Can this be fixed or tweaked to work, there has to be away. It will make it even more SEO!!

The current way of doing things is where the links to newpostinthreadXXX.html and lastpostinthreadXXX.html redirect to their showthread.php? counterparts. The following mini-tutorial will fix that:

STEP ONE

Add the following line to your .htaccess file:

RewriteRule ^post([0-9]+).html$ showthread.php?p=$1 [L]

STEP TWO

All of the following changes need to be made to the showthread.php file:

exec_header_redirect("showthread.php?$session[sessionurl_js]p=$getlastpost[postid]$highlightwords#post$getlastpost[postid]");

should be replaced with

exec_header_redirect("post$getlastpost[postid].html#post$getlastpost[postid]");

exec_header_redirect("showthread.php?$session[sessionurl_js]p=$posts[postid]$highlightwords#post$posts[postid]");

should be replaced with

exec_header_redirect("post$posts[postid].html#post$posts[postid]");

exec_header_redirect("showthread.php?$session[sessionurl_js]t=$threadinfo[threadid]&goto=lastpost$highlightwords");

should be replaced with

exec_header_redirect("lastpostinthread$threadinfo[threadid].html");

exec_header_redirect("showthread.php?$session[sessionurl_js]t=$thread[pollid]");

should be replaced with

exec_header_redirect("thread$thread[pollid].html");

$firstunread = 'showthread.php?' . $session['sessionurl'] . 't=' . $threadid . '&goto=newpost';

should be replaced with

$firstunread = 'newpostinthread' . $threadid . '.html';

Edited 3 Years Ago by Dani: Formatting fixed

that latest fix is the perfect fit and everything works as you posted. I REALLY appreciate your dedication and hard work. For people that want to have SEO type forums, You're an angel!!


Mike :mrgreen:

Thank you so so much for your kind words. And thank you for your generous donation to DaniWeb, as well!

Excelent modification, congratulations :D

But :( i have a problem >.<

In my online appears Unknown Location for example:

Unknown
/foro/thread26600.html <-----

or

Unknown
/foro/thread9721.html <----

Any idea to how fix this problem?

This article has been dead for over six months. Start a new discussion instead.