Hoe 301-redirect je 700+ pagina's (van een weblog)?

2007 05 19 door monchito | categorieën: seo webdesign weblog seo 

moncodeIn het kader van het redesign van je nieuwe site heb je keyword rich, zoekmachine vriendelijke urls geschreven. Je hebt ook bij de SEO les goed opgelet en wil je deeplinks, PageRanks en geschiedenis behouden en voorkomen dat er 404-pagina's ontstaan als al die oude pagina's een nieuwe url krijgen... Chapeau! Maar hoe pak je dat handig aan als je bijvoorbeeld een weblog hebt met 700+ artikelen?

Juist, je gebruikt een 301-redirect, zoals het hoort.

Er zijn meerdere manieren om een 301-redirect te maken. Bijvoorbeeld door alle regels in een .htaccess te zetten die bij iedere request opgevraagd wordt. Maar wanneer het gaat om heel veel pagina's kun je die redirect beter alleen maar gebruiken wanneer het echt nodig is. In december 2006 optimaliseerde ik MONLOG, waarbij ook de urls onder handen werden genomen. Hoe ik dat destijds aangepakt heb, is volgens mij wel een elegante oplossing.

Stap 1: Een nieuwe kolom met url-namen aanmaken in je database

De meeste weblogs draaien op een database. Zo ook MONLOG. Vóór december 2006 werd een logitem opgevraagd aan de hand van een numerieke id in de querystring van de browser: http://www.monlog.nl/logs/700.

Nu wil ik in plaats van het getal 700 een keyword rich url hebben met een duidelijke datumnotatie erin, zoals '2006-11-01-cia-wikipedia-intellipedia'. De eenvoudige manier (voor programmeurs) is het om uit een export van je database met wat search & replace werk een query samen te stellen die je datum en title kolommen combineert tot een mooie url. De bewerkelijke maar ook meer nauwkeurige manier is het om handmatig alle urls in te voeren.

Stap 2: Alleen redirecten wanneer het nodig is

Vervolgens maakte ik de volgende code:

if(isset($_GET['p']) && isset($_GET['id']) 
&& $_GET['p'] == 'logs' && ctype_digit($_GET['id']))
{
    $q = "SELECT l.id,l.url FROM table AS l WHERE 
          l.id = "".sanitize($_GET['id']).""";
    $r = mysql_query($q) 
         or die(header("HTTP/1.1 404 Not Found"));
 
    if(mysql_num_rows($r) == 1)
    {
        $a = mysql_fetch_assoc($r);
        header("HTTP/1.0 301 Moved permanently");
        header("location: http://www.monlog.nl/logs/".$a['url']."/");
        exit;
    }
    else
    {
        header("HTTP/1.1 404 Not Found");
    }
}
else {
    // doe andere dingen, bijvoorbeeld nieuwe logitems tonen
}

De programmeurs onder jullie zullen meteen zien wat het doet, maar voor de niet-programmeurs onder ons hieronder een korte beschrijving (geen uitleg):

is een oude numerieke id opgevraagd volgens de notatie die eerst gebruikt werd op MONLOG? 

if(isset($_GET['p']) && isset($_GET['id']) 
&& $_GET['p'] == 'logs' && ctype_digit($_GET['id']))
{

Zo ja: staat deze numerieke id in de database?

    $q = "SELECT l.id,l.url FROM table AS l WHERE 
          l.id = "".sanitize($_GET['id']).""";
    $r = mysql_query($q) 
         or die(header("HTTP/1.1 404 Not Found"));

Zo ja, dan met een 301 redirecten naar de nieuwe url.

    if(mysql_num_rows($r) == 1)
    {
        $a = mysql_fetch_assoc($r);
        header("HTTP/1.0 301 Moved permanently");
        header("location: http://www.monlog.nl/logs/".$a['url']."/");
        exit;
    }

Zo nee, dan naar de 404 pagina.

    else
    {
        header("HTTP/1.1 404 Not Found");
    } 

Als er in het begin al geen nette numerieke id opgevraagd werd, een 404 http header opgeven. Als er iets anders opgegeven wordt, andere dingen doen, bijvoorbeeld logitems weergeven :p

}
else {
    // andere zut doen

Tot slot

Om een lang verhaal kort te maken: ik heb 700+ redirects afgevangen met slechts een paar regeltjes code die ook alleen maar in werking worden gezet als het nodig is. Waar ik nu heel erg benieuwd naar ben, is of er ook andere manieren handig zijn, bijvoorbeeld bij een IIS server, met ASP.NET, etc.

Reacties

Bèr Kessels

door Bèr Kessels, 2007 05 19

Als de oude en nieuwe urls een duidelijk, consistent schema hebben, en beide een unieke terugkerende waarde dan kan een "redirectMatch" een veel betere, makkelijkere en schonere oplossing zijn. Met redirectMatch kun je een 301 "doen" voor bepaalde reguliere expressies (patronen, dus). http://httpd.apache.org/docs/2.0/mod/mod_alias.html#redirectmatch

Roy

door Roy, 2007 05 19

Prima artikel, echter wil ik wel opmerken dat het gewoon onjuist is om een 301 naar je 404 te doen. Dat zul je zeker merken als je 404 plots op allerlei onzin begint te ranken.

monchito

door monchito, 2007 05 19

@Ber: inderdaad! Dat zou een nog makkelijker oplossing zijn als je bijvoorbeeld automatisch de title en datum vakken in de tabel wil combineren. @Roy: inderdaad. Misschien is het verstandiger om die overgebleven items die dan op de 404 pagina terecht zouden komen door te sturen naar d eindexpagina in plaat svan de 404 pagina. De 404 pagina geeft zelf overigens wel een 404 header

monchito

door monchito, 2007 05 19

@Roy: ook maar meteen aangepast en er gewoon een normale 404 van gemaakt, zoals het hoort ;)

Baarr

door Baarr, 2007 05 19

Sanitize is een functie van jezelf neem ik aan. mysql_real_escape_string (mits je mysql gebruikt) is dan de goede optie voor menig gebruiker.if(mysql_num_rows($r) !== 0) Beter lijkt me: if(mysql_num_rows($r) == 1)Je verwacht maar 1 resultaat als ik verderop in je code kijk.Verder zit het goed in elkaar lijkt me ;-)http://www.baarr.nl

monchito

door monchito, 2007 05 19

@Baarr: sanitize() is inderdaad een functie van mezelf. Het is mysql_real_escape_string() plus nog wat extra paranoia van mijn kant ;)Je toevoeging is nuttig; ik heb het meteen aangepast, Thnx :)

Tri Pham

door Tri Pham, 2007 05 19

Een nette oplossing is het zeker. Mijn voorkeur gaat altijd uit om dit soort werk op web server level te doen, ipv van applicatie laag (PHP). Met andere woorden, liever dit afhandelen met Apache (httpd.conf en .htaccess) dan in een scriptingtaal, zoals PHP, want dat is niet bepaald snel. Natuurlijk voor zover dat kan.Je zou in dit geval zelfs een eigen Apache mod kunnen schrijven die hetzelfde doet als je PHP script :-)

sebedeus

door sebedeus, 2007 06 24   sebedeus

ik vind het wel knap verzonnen

Rants/opmerkingen/suggesties?

*
*

Let's get social

Wat is MONLOG

Sinds 2002 is MONLOG het weblog van Ramon Eijkemans, freelance SEO-gun for hire.

Dit weblog bevat how-to's, mijmeringen, soms wat humor. Het gaat vrijwel altijd over SEO. Ik herhaal geen nieuws en doe ook geen pogingen om SEO filosofisch te verklaren. Het doel van dit weblog is om jou van praktische informatie te voorzien!

En dan nog dit: guestpostings zijn welkom! Mail me als je je ei kwijt wil op dit goed rankende podium.

Laatste comments

Volgens mij is het een hele duidelijke tutorial alleen gek...
31.08.2010 door jasonz op Leer een website bouwen met PHP in 5 minuten

@chet Nice!
28.08.2010 door Ramon Eijkemans op custom RSS feeds van NU.nl en SEO

Ditzelfde grapje geldt ook voor video inhoud...
28.08.2010 door chet op custom RSS feeds van NU.nl en SEO

Hoi Kris, ik zou eerlijk gezegd niet weten waarom, maar...
28.08.2010 door Ramon Eijkemans op Gratis SEO scripts? Check MONLOG

Hallo, leuk initiatief.Ik had een vraagje mbt SEO en javas...
27.08.2010 door Kris | Spaarlampen op Gratis SEO scripts? Check MONLOG

Check ;)
27.08.2010 door Ramon Eijkemans op Gratis SEO scripts? Check MONLOG

Ja die ken ik wel :) Het schijnt nog niet mogelijk te zijn...
27.08.2010 door Bjorn van der Neut op Gratis SEO scripts? Check MONLOG

Leuk om te lezen hoe je het gehad hebt, en dan maandag écht...
26.08.2010 door renske op Op SEO avontuur in Moskou

Functioneel was het zeker :)
26.08.2010 door Ramon Eijkemans op Op SEO avontuur in Moskou

Mooi verhaal Ramon, klinkt als een functioneel bedrijfsuitje...
26.08.2010 door Roderick op Op SEO avontuur in Moskou