WordPress in a subdirectory, urls like it was in root directory

There are many reasons to install wordpress in a subdirectory and not in the root directory (for instance because it is easier to update wordpress, the files are better organized …). However, for SEO purposes, it is recommended to mask that subdirectory name in url and make wordpress look like it is installed in the root directory

So, lets suppose you install wordpress in a subdir called wordpress. Then all of your urls will look like:
http://www.yoursitename.com/wordpress/...

And we want to remove that trailing /wordpress so our urls look like:
http://www.yoursitename.com/...

Note: If you want to have permalinks active and still don’t have done this, please activate your permalinks first!!. I have set a Custom Structure (/%category%/%postname%/).

Ok, ready to go. Let's continue with the process.

You will have to change two files:

First, edit wp-config.php and add these following two lines (change the word 'wordpress for your subdirectory name):

1
2
3
// ** Hostname settings ** //
define('WP_SITEURL', "http://${_SERVER['HTTP_HOST']}/wordpress");
define('WP_HOME',    "http://${_SERVER['HTTP_HOST']}");

Then copy your /wordpress/index.php to your root directory and modify it. Change the line that says:

1
2
/** Loads the WordPress Environment and Template */
require('./wp-blog-header.php');

for

1
2
/** Loads the WordPress Environment and Template */
require('./wordpress/wp-blog-header.php');

If you had permalinks activated (this is, not default behaviour) copy the existing /wordpress/.htaccess file to root directory!. If you don't, when you try to access category links, they won't work.

That's all folks! 😉

WordPress: remove /category

If you are aware of what SEO links mean, and you have a wordpress blog configured by default, you might want to make some little changes to how urls are built.

  • Remove /category/categoryname
  • Having good Permalink Structure is very important for your Blog with respect to SEO. WordPress does nice by providing a Permalinks Section from the Settings Page in the Admin Panel.

    wordpress-no-category-base-permalinks

    But sometimes some bloggers do not want to have any category base in their Permalinks structure. WordPress does not allows you to do it. Here is how you can get it done.

    Wordpress-permalinks-no-category-base

    WP No Category Base Plug-in

    If you are using WordPress 2.7, Go to Plug-ins –> Add New –> Search for “WP No Category Base”, install it and activate it.

    If you are using previous version of WordPress, Upload the “no-category-base.php” to the “/wp-content/plugins/”, and Activate it from the Plug-ins Menu

    This plug-in does not have any Settings Page. Just activate it to use and de-activate when you don’t need it.

    Precautions

    Remember to have no Post Slug equal to your Category Slug. In case you have same slug for both then the page will get the priority and the category page will never show up.

    Links

Parse XML file into array (PHP)

Nowadays XML-based information storing is increasing its use, so usually you’ll have to parse these files. If you want a PHP function that resolves these needs, take a look at this:

<?php
/**
 * xml2array() will convert the given XML text to an array in the XML structure.
 * Link: http://www.bin-co.com/php/scripts/xml2array/
 * Arguments : $contents - The XML text
 *                $get_attributes - 1 or 0. If this is 1 the function will get the attributes as well as the tag values - this results in a different array structure in the return value.
 *                $priority - Can be 'tag' or 'attribute'. This will change the way the resulting array sturcture. For 'tag', the tags are given more importance.
 * Return: The parsed XML in an array form. Use print_r() to see the resulting array structure.
 * Examples: $array =  xml2array(file_get_contents('feed.xml'));
 *              $array =  xml2array(file_get_contents('feed.xml', 1, 'attribute'));
 */
function xml2array($contents, $get_attributes=1, $priority = 'tag') {
    if(!$contents) return array();
 
    if(!function_exists('xml_parser_create')) {
        //print "'xml_parser_create()' function not found!";
        return array();
    }
 
    //Get the XML parser of PHP - PHP must have this module for the parser to work
    $parser = xml_parser_create('');
    xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, "UTF-8"); # http://minutillo.com/steve/weblog/2004/6/17/php-xml-and-character-encodings-a-tale-of-sadness-rage-and-data-loss
    xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
    xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
    xml_parse_into_struct($parser, trim($contents), $xml_values);
    xml_parser_free($parser);
 
    if(!$xml_values) return;//Hmm...
 
    //Initializations
    $xml_array = array();
    $parents = array();
    $opened_tags = array();
    $arr = array();
 
    $current = &$xml_array; //Refference
 
    //Go through the tags.
    $repeated_tag_index = array();//Multiple tags with same name will be turned into an array
    foreach($xml_values as $data) {
        unset($attributes,$value);//Remove existing values, or there will be trouble
 
        //This command will extract these variables into the foreach scope
        // tag(string), type(string), level(int), attributes(array).
        extract($data);//We could use the array by itself, but this cooler.
 
        $result = array();
        $attributes_data = array();
 
        if(isset($value)) {
            if($priority == 'tag') $result = $value;
            else $result['value'] = $value; //Put the value in a assoc array if we are in the 'Attribute' mode
        }
 
        //Set the attributes too.
        if(isset($attributes) and $get_attributes) {
            foreach($attributes as $attr => $val) {
                if($priority == 'tag') $attributes_data[$attr] = $val;
                else $result['attr'][$attr] = $val; //Set all the attributes in a array called 'attr'
            }
        }
 
        //See tag status and do the needed.
        if($type == "open") {//The starting of the tag '<tag>'
            $parent[$level-1] = &$current;
            if(!is_array($current) or (!in_array($tag, array_keys($current)))) { //Insert New tag
                $current[$tag] = $result;
                if($attributes_data) $current[$tag. '_attr'] = $attributes_data;
                $repeated_tag_index[$tag.'_'.$level] = 1;
 
                $current = &$current[$tag];
 
            } else { //There was another element with the same tag name
 
                if(isset($current[$tag][0])) {//If there is a 0th element it is already an array
                    $current[$tag][$repeated_tag_index[$tag.'_'.$level]] = $result;
                    $repeated_tag_index[$tag.'_'.$level]++;
                } else {//This section will make the value an array if multiple tags with the same name appear together
                    $current[$tag] = array($current[$tag],$result);//This will combine the existing item and the new item together to make an array
                    $repeated_tag_index[$tag.'_'.$level] = 2;
 
                    if(isset($current[$tag.'_attr'])) { //The attribute of the last(0th) tag must be moved as well
                        $current[$tag]['0_attr'] = $current[$tag.'_attr'];
                        unset($current[$tag.'_attr']);
                    }
 
                }
                $last_item_index = $repeated_tag_index[$tag.'_'.$level]-1;
                $current = &$current[$tag][$last_item_index];
            }
 
        } elseif($type == "complete") { //Tags that ends in 1 line '<tag />'
            //See if the key is already taken.
            if(!isset($current[$tag])) { //New Key
                $current[$tag] = $result;
                $repeated_tag_index[$tag.'_'.$level] = 1;
                if($priority == 'tag' and $attributes_data) $current[$tag. '_attr'] = $attributes_data;
 
            } else { //If taken, put all things inside a list(array)
                if(isset($current[$tag][0]) and is_array($current[$tag])) {//If it is already an array...
 
                    // ...push the new element into that array.
                    $current[$tag][$repeated_tag_index[$tag.'_'.$level]] = $result;
 
                    if($priority == 'tag' and $get_attributes and $attributes_data) {
                        $current[$tag][$repeated_tag_index[$tag.'_'.$level] . '_attr'] = $attributes_data;
                    }
                    $repeated_tag_index[$tag.'_'.$level]++;
 
                } else { //If it is not an array...
                    $current[$tag] = array($current[$tag],$result); //...Make it an array using using the existing value and the new value
                    $repeated_tag_index[$tag.'_'.$level] = 1;
                    if($priority == 'tag' and $get_attributes) {
                        if(isset($current[$tag.'_attr'])) { //The attribute of the last(0th) tag must be moved as well
 
                            $current[$tag]['0_attr'] = $current[$tag.'_attr'];
                            unset($current[$tag.'_attr']);
                        }
 
                        if($attributes_data) {
                            $current[$tag][$repeated_tag_index[$tag.'_'.$level] . '_attr'] = $attributes_data;
                        }
                    }
                    $repeated_tag_index[$tag.'_'.$level]++; //0 and 1 index is already taken
                }
            }
 
        } elseif($type == 'close') { //End of tag '</tag>'
            $current = &$parent[$level-1];
        }
    }
 
    return($xml_array);
}
</code>

An example of how to use it:

Suppose you have an XML file like:

<object><name>Objeto3</name><id>003</id><referenceNumber></referenceNumber><groupIdentifier></groupIdentifier><persistentIdentifier></persistentIdentifier><masterCreationDate locale="CEST"><date format="yyyyMMdd">20090612</date><time format="HHmmssSSS">103530703</time></masterCreationDate><objectComposition>simple</objectComposition><structuralType><name></name><extension></extension></structuralType><hardwareEnvironment>x86</hardwareEnvironment><softwareEnvironment>OS: Windows XP 5.1, JVM:Sun Microsystems Inc. 1.6.0_13</softwareEnvironment><installationRequirements></installationRequirements><accessInhibitors></accessInhibitors><accessFacilitators></accessFacilitators><quirks></quirks><metadataRecordCreator></metadataRecordCreator><metadataCreationDate locale="CEST"><date format="yyyyMMdd">20090612</date><time format="HHmmssSSS">103530734</time></metadataCreationDate><comments></comments><files><file xmlns:nz_govt_natlib_xsl_XSLTFunctions="nz.govt.natlib.xsl.XSLTFunctions">
<fileIdentifier/>
<path>D:\00077-70\00077-70_0001.jpg</path>
<filename>
<name>00077-70_0001.jpg</name>
<extension>jpg</extension>
</filename>
<size>162096</size>
<fileDateTime>
<date format="yyyyMMdd">20090303</date>
<time format="HHmmssSSS">133008000</time>
</fileDateTime>
<mimetype>image/jpeg</mimetype>
<fileFormat>
<format>JPEG</format>
</fileFormat>
<image>
<imageResolution>
<samplingFrequencyUnit>2</samplingFrequencyUnit>
<xsamplingFrequency>150</xsamplingFrequency>
<ysamplingFrequency>150</ysamplingFrequency>
</imageResolution>
<imageDimension>
<width>998</width>
<length>1321</length>
</imageDimension>
<bitsPerSample>8</bitsPerSample>
<photometricInterpretation>YCbCr</photometricInterpretation>
<iccprofileName/>
<colorMap/>
<orientation>0degrees</orientation>
<compression>
<scheme>6</scheme>
<level/>
</compression>
</image>
</file>
</files></object>

Then you'll parse it like:

<code>
<strong>$xml = xml2array($contents);</strong>
$query1 = "INSERT into `master` values (" .
 		$ultimoID . ", " .
 		<strong>$xml[Object][Files][File][Size] . ", '" .
 		$xml[Object][Files][File][Filename][Extension] . "', '" .
 		$xml[Object][Files][File][Mimetype] . "', '" .</strong>
 		md5_file($listado[$i]) . "', " .
 		$xml[Object][Files][File][FileDateTime][Date] . ", " .
 		substr($xml[Object][Files][File][FileDateTime][Time],0,6) . ", '" .
 		$xml[Object][Files][File][Filename][Name] . "', '" .
 		addslashes($xml[Object][Files][File][Path]) . "', " .
 		$xml[Object][Files][File][Image][ImageResolution][XSamplingFrequency] . ", " .
 		$xml[Object][Files][File][Image][ImageResolution][YSamplingFrequency] . ", " .
 		$xml[Object][Files][File][Image][ImageDimension][Width] . ", " .
 		$xml[Object][Files][File][Image][ImageDimension][Length] . ", '" .
 		$xml[Object][Files][File][FileFormat][Format] . "', '" .
 		$xml[Object][Files][File][FileFormat][Version] . "', " .
 		$xml[Object][Files][File][Image][BitsPerSample]. ")";
</code>

Posicionamiento en Google (III)

Este artículo es una continuación de Posicionamiento en Google (I) y Posicionamiento en Google (II).

Voy a continuar dando algunos consejos básicos de cara a mejorar tu PR en Google. Como siempre hay que tomar estos consejos como unas recomendaciones básicas, no hay porqué seguirlos al pie de la letra. Ten en cuenta que a veces es mejor pecar de defecto que de exceso, pues si abusas de las medidas aquí expuestas podrás ser penalizado por los motores de búsqueda.

1. Crea headings

Los headings son items que sobresalen sobre los demás. Por ejemplo,

ésto es un heading de tamaño 1, o <h1>

ésto es un heading de tamaño 2, o <h2>

Asimismo existen el <h3>, <h4>, etc
Para los motores de búsqueda el H1 incluye contenido muy importante. Así que trata de incluir tus keywords más habituales en este H1.
Un H2 también tiene más importancia que el resto del texto.
La mayoría de editores WYSIWYG permiten la creación de este tipo de tags. En caso de que no lo permita edita el código fuente de tu aplicación y rodea las partes que quieras destacar con los tags <Hi>, siendo i el tamaño del heading.
El ejemplo de arriba tiene el siguiente código fuente:


<h1>ésto es un heading de tamaño 1</h1>
<h2>ésto es un heading de tamaño 2</h2>

Ojo! No abuses de las tags <h1> o los motores de búsqueda podrían penalizarte asignándote un bajo ranking. En general es más que suficiente con un <h1> y un par de <h2> por página.

2. Utiliza la negrita y la cursiva

La utilización de negrita y cursiva es importante ya que los indexadores consideran que el texto que este tipo de textos tienen más importancia que el resto de los existentes en la página y les asigna una prioridad mayor a la hora de mostrar páginas de resultados de búsqueda.
Localiza tus keywords principales y trata de encuadrarlas en tags e . Como siempre, no abuses o tu página resultará ilegible…

3. Obten una correcta densidad de keywords

Esto es, a menudo, una de los objetivos más difíciles de alcanzar. No te obsesiones con el tema, únicamente está bien que lo conozcas.
La densidad de palabras clave (keywords) es, en resumen, el número de veces que utilizas palabras clave en relación con el total de texto en tu página web.
Por ejemplo, imaginemos que escribes hyips 20 veces en una página que tiene alrededor de 400 palabras. Entonces tu densidad de la palabra clave hyips es 20/400=5%. Si tus densidades son superiores al 8% los motores de búsqueda te penalizarán por considerarte spammer (lo llaman Keyword stuffing).
Como norma general recomiendo no pasar del 5%. De todas formas no te obsesiones con este tema. Escribe tu página de forma normal, como si fueras a contar el contenido a otra persona. Entonces léela y observa si has abusado de alguna keyword. Si consideras que has abusado de alguna reescribe tu artículo hasta que obtengas una densidad aceptable.

4. Utiliza alt en las imágenes

Cuando incluyas una imagen dentro de tu página web, bien sea un logo, una fotografía o un gráfico de datos, asegúrate de SIEMPRE incluir el tag <alt> con información descriptiva de la imagen. El texto que va dentro de este atributo no se mostrará normalmente en tu página web -esto es, tú no lo verás-, pero los motores de búsqueda sí lo leerán. La forma de ver este tipo de textos es colocar el ratón sobre la imagen en cuestión, y el texto aparecerá.

Además, si no incluyes este tag y utilizas determinado DTD tu página no pasará la validación del W3C.
Mira éste código de ejemplo:
<img src="http://www.hyips.es/templates/siteground-j15-54/images/header_bg.jpg" alt="logo de hyips.es - inversiones de alta rentabilidad" />
Otro gran consejo: haz que el nombre de la imagen contenga las keywords más importantes de tu sitio. Por ejemplo, en vez de header_bg.jpg podría haberlo llamado hyips.jpg.

4. Utiliza metatags

Esto es absolutamente imprescindible si deseas obtener un buen PR. Rellena estos items en cada página y sé meticuloso a la hora de elegir su contenido. ¿Por qué molestarse, si existen algunos plugins que incluyen la metainformación de forma automática (por ejemplo SH404SEF). Ninguno de estos plugins hará un trabajo tan fino como podría hacerlo un humano. Estas palabras, calculadas de forma automática, pueden servir de “guia” o servir en algunos casos, pero no en la mayoría.
Lo más importante es la meta tag description. Muchos indexadores (sí, también Google) utilizarán éste campo si no son capaces de acceder a otras partes de la página. Piensa en esta descripción cuidadosamente, hazla como un pequeño anuncio 😉

Busca un tema en google y fíjate en la razón que te hace elegir en qué link pinchas (sí, ya lo sé, lo primero es el orden!). Pero si te das cuenta lo primero que miras es el título que se muestra y lo siguiente… la descripción de la página!! ¿Ves por dónde voy? 😉

5. Usa enlaces internos

Enlaza tus artículos anteriores u otras secciones de tu página siempre que puedas. Por ejemplo, como he hecho yo al principio de este artículo, donde he enlazado dos artículos anteriores. Además, utiliza títulos descriptivos para hacer los enlaces. No es lo mismo poner “este artículo viene de aquí y aquí que poner lo que yo he puesto. No utilices imágenes para este tipo de enlaces. Como siempre, intenta meter keywords en estos enlaces.
En este sentido disponer de un sitemap válido es una gran forma de realizar ese linkado interno. Eso sí, asegúrate de que el sitemap está bien! Muchas veces los generadores de sitemaps incluyen url’s no deseadas o no las muestran en el orden óptimo.

6. Enlaces externos

Conseguir que nos enlacen se ha vuelto una obsesión para algunos webmasters. La realidad es que cuantos más enlaces externos apunten a nuestro sitio, mejor ranking nos dará google. PERO si estos enlaces provienen de páginas penalizadas, de granjas de links, sitios web con pr más bajo que el tuyo, sitios cuyo contenido dista mucho del tuyo, etc… más que beneficiarte, te fastidiarán, pues google te penalizará.

Intenta localizar los sitios web que, sin competir directamente contigo, manejan temática cercana a la tuya o están relacionados de alguna manera. Pídeles de forma amable que coloquen un link a tu página a cambio de un link desde tu página. Para hacerselo más fácil, proporciónales tú mismo el código del link y trata de ser descriptivo a la hora de elegirlo. No proporciones enlaces del tipo www.hyips.es, sino más bien del tipo Inversiones de alta rentabilidad – hyips.es. Ves por dónde van los tiros? 😉

Google Analytics en SFM forums

Este artículo es una continuación de Google Analytics en WordPress.

Para añadir el código de seguimiento de analytics a los foros SMF hay que proceder del siguiente modo:

Editar index.template.php de la plantilla que estemos utilizando.

Para que no se produzcan errores en el código del foro hay que retocar ligeramente el código que nos da analytics. Supongamos que el código en cuestión es:


<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
try {
var pageTracker = _gat._getTracker("UA-6714824-2");
pageTracker._trackPageview();
} catch(err) {}</script>

Debemos añadir cuatro backslashes para que éste funcione. El código modificado sería:


<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src=\'" + gaJsHost + "google-analytics.com/ga.js\' type=\'text/javascript\'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
try {
var pageTracker = _gat._getTracker("UA-6714824-2");
pageTracker._trackPageview();
} catch(err) {}</script>

A funcionar! 😉

Google Analytics en WordPress

Para los que no saben qué es, Google Analytics es el servicio de Google para estadisticas de visitas a páginas web.

Una vez creada la cuenta en Analytics (es fácil, hay miles de manuales sobre cómo hacerlo).

Cuando finalicemos el registro en Analytics google nos devolverá un código fuente del tipo:


<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
try {
var pageTracker = _gat._getTracker("UA-8469016-1");
pageTracker._trackPageview();
} catch(err) {}</script>

Apuntamos la parte marcada en rojo, que será del tipo “UA-XXXXXXX-Y”.

A continuación vamos a añadir Analytics a nuestro WordPress de forma simple.

Para ello descargamos éste plugin (obtenido de aquí) y lo guardamos como google_analytics.php.
Después abrimos nuestro gestor de FTP (en mi caso, FileZilla), nos conectamos a nuestro blog y subimos el fichero a la carpeta /wp-content/plugins/.

A continuación entramos al menú de administración de WordPress, menú plugins y habrá uno llamado “Google Analytics”. Lo activamos. Veremos algo parecido a ésto:
Google Analytics plugin wordpress 1

Acto seguido lo editamos y buscamos la línea que pone $uastring = "UA-XXXXXXX-Y";. Sustituimos el valor entre comillas por aquél que apuntamos anteriormente, el que nos devolvió Google (en rojo):
google analytics en wordpress

Cuando terminemos pulsamos en “Update File” (abajo a la izquierda). En 24horas empezarán a aparecer las primeras estadísticas! 😉

Javascript: depurando errores

Depurar errores al programar en Javascript puede ser un verdadero engorro. Si no utilizas ningún debugger tienes que llenar el código de alerts, borrando las cachés del navegador, …

Por eso yo utilizo dos herramientas muy completas:
1. JSLint:
Es un parser Javascript. Verifica que el código es sintácticamente correcto, informa de las variables no declaradas, etc.
Modo de funcionamiento: copiar tu código fuente (encerrado en tags <html><head> ... </head></html>) y pulsar el botón JSLint (en la parte inferior de la página).
JSLint javascript

2. Firebug:
Es un plugin para Firefox. Permite ejecución paso a paso del código Javascript, la inspección de variables, …
Modo de funcionamiento: Instalar el plugin, reiniciar Firefox, ir a la página que aloja el código que deseemos ejecutar, pulsar la pestaña “Scripts” y, en el fuente, añadir los breakpoints (botón derecho). Más tarde, disparar el evento que ejecute el código y usar los controles de ejecución y el inspector de variables.

firebug -1

firebug - 2

Ajax (I): peticiones HTTP – HTTP Requests

A menudo es útil realizar peticiones HTTP al servidor, para, por ejemplo, invocar un programa (sea php, python, asp…).
El siguiente ejemplo muestra el código Ajax para realizar una petición de este estilo.
Los resultados se almacenarán en el div RESULTSDIV

<script>
         function fromServer(){
                 if( http_request.readyState==4 ){
                     if( http_request.status==200 ){
                           // results from call to the server appear here
                           // in http_request.responseText;
                           e = document.getElementById("RESULTSDIV");
                           e.innerHTML = http_request.responseText;
                     }
                     else{
                           // uncomment next line if you want to show any error messages
                           alert('error: ' + http_request.responseText);
                     }
                 }
         }

         function makeRequest(url,param){
               url = url + param;
               http_request = false;
               if(window.XMLHttpRequest){ // Mozilla, Safari,...
                  http_request = new XMLHttpRequest();
                  if (http_request.overrideMimeType){
                      http_request.overrideMimeType('text/html');
                  }
               }
               else if (window.ActiveXObject){// IE
                  try{ http_request = new ActiveXObject("Msxml2.XMLHTTP");}
                  catch (e){
                        try{
                           http_request = new ActiveXObject("Microsoft.XMLHTTP");
                        }
                        catch (e2) {}
                   }
               }
               if (!http_request){
                  // uncomment next line if you want to show any error messages
                  alert('Cannot create XMLHTTP instance');
                  return false;
               }
               //alert("makeRequest(): url='"+url+"'");
               http_request.onreadystatechange = fromServer;
               http_request.open('GET', url, false);
               http_request.send(param);
          }
</script>

Un inciso para comentar algo importante:
Ese último parametro de http_request.open() indica si la petición será síncrona o asíncrona.
Es fácil de entender.
SINCRONA: Significa que la funcion javascript no seguirá interpretandose hasta que la operacion ajax finalize.

Código PHP:
var algo = newajax();
algo.open(algo,algo,false);
algo... //blabla
#Este alert solo se ejecutara cuando todo lo de arriba se haya interpretado y finalizado.
alert(222)

ASINCRONA: Significa que la funcion javascript pasará de largo de proceso ajax sin necesidad de esperar a que esté finalizado para seguir interpretandose es por eso que se usa los onreadystatechange osea… en que estado va tu proceso.

Código PHP:
var algo = newajax();
algo.open(algo,algo,true);
algo... //blabla

#Este alert se ejecutará sin importar que el proceso ajax haya finalizado .. pasa de largo.
alert(222)

Otra definición.
ASINCRONA: le vale un pepino tu proceso ajax y continua el interprete javascript.
SINCRONA: espera a que todo termine para continuar.

En el caso que me ocupa utilizo la siguiente función para invocar el procedimiento makeRequest:


        function busca(pal){
               var valor=document.forms[0].group1y.checked;
               //alert("busca(): "+valor);
               if (valor!=true){
                  document.getElementById("RESULTSDIV").innerHTML = "";
               }
               else{
                  var base='http://olmo.unizar.es';
                  var param='/search?ln=es&sc=1&p='+pal;
                  makeRequest(base,param);
               }
           }

También puede hacerse interpretando los valores que devuelve en la función busca. Para ello el código sería:


          function fromServer(){
                 if( http_request.readyState==4 ){
                     if( http_request.status==200 ){
                           // results from call to the server appear here
                           // in http_request.responseText;
                           //e = document.getElementById("RESULTSDIV");
                           //e.innerHTML = http_request.responseText;
                           //alert('fromServer(): responseText='+http_request.responseText);
                           var salida=http_request.responseText;
                           return salida;
                     }
                     else{
                           // uncomment next line if you want to show any error messages
                           alert('error: ' + http_request.responseText);
                     }
                 }
         }

         function makeRequest(url,param){
               url = url + param;
               http_request = false;
               if(window.XMLHttpRequest){ // Mozilla, Safari,...
                  http_request = new XMLHttpRequest();
                  if (http_request.overrideMimeType){
                      http_request.overrideMimeType('text/html');
                  }
               }
               else if (window.ActiveXObject){// IE
                  try{ http_request = new ActiveXObject("Msxml2.XMLHTTP");}
                  catch (e){
                        try{
                           http_request = new ActiveXObject("Microsoft.XMLHTTP");
                        }
                        catch (e2) {}
                   }
               }
               if (!http_request){
                  // uncomment next line if you want to show any error messages
                  alert('Cannot create XMLHTTP instance');
                  return false;
               }
               //alert("makeRequest(): url='"+url+"'");
               http_request.onreadystatechange = fromServer;
               http_request.open('GET', url, false);
               http_request.send(param);
               return http_request;
          }
          function busca(pal){
               var valor=document.forms[0].group1y.checked;
               //alert("busca(): "+valor);
               if (valor!=true){
                  document.getElementById("RESULTSDIV").innerHTML = "";
               }
               else{
                  var base='http://olmo.unizar.es';
                  var param='/search?ln=es&sc=1&p='+pal;
                  var out=makeRequest(base,param);
                  if (out!==undefined){
                       document.getElementById("RESULTSDIV").innerHTML = out.responseText;
                  }
             }

Un ejemplo de todo ello funcionando a la vez como elemento programando en Python disponible para descarga [aquí]

Posicionamiento en google (I): validando tus DTD's

Antes de seguir leyendo:
– Si no sabes qué es un DTD, búscalo en wikipedia

De cara a tener un alto pagerank en google, un aspecto que debemos verificar periódicamente es la validez de nuestros DTD’s. Además, tener un código válido, limpio y organizado mejora notablemente el aspecto de nuestra página web, aportándole solidez.

Validando el DTD
Podemos utilizar múltiples herramientas para validar el código fuente de nuestras páginas. Yo suelo utilizar el Validador del W3C.

Éste validador lee el código fuente de nuestra página, consulta el DTD que estamos utilizando y valida nuestro código contra ese DTD. Si nuestro código es incorrecto nos muestra los errores que tiene y, normalmente, nos da pistas sobre cómo solventarlos.

Para mis páginas suelo utilizar el DTD Transitional.
<! DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

Por ejemplo, para validar la corrección del DTD, basta con pulsar en este enlace

Si la validación pasa sin errores, podremos incluir el siguiente logo en nuestro sitio.

Valid XHTML 1.0 Transitional

Creando sitemaps de forma automática

Si no sabes qué son los sitemaps, para de leer y consulta wikipedia.

Existen multitud de servicios para crear sitemaps [1].

Dentro de las herramientas online, me gusta especialmente xml-sitemaps.

xmlsitemaps

Este servicio crea sitemaps en formato xml, directamente importable a google, así como html. Las versiones html son especialmente útiles para verificar qué contenidos se han indexado en el sitemap. Gracias a ello podemos observar fallos en nuestras páginas (URL’s que no deberían ser visibles, enlaces que fallan, títulos de enlaces repetidos, etc).

sitemap version HTML

Por ejemplo, en esta imágen se observa que existen varias páginas con el mismo título. A las arañas de google no les gustan los títulos repetidos, por lo que habría que modificar algunas de mis páginas para que tuvieran títulos distintos. Hablaremos más adelante sobre cómo mejorar el posicionamiento web y el pagerank de tus páginas.

Las versiones gratuitas de estos servicios online no siempre satisfacen las necesidades del webmaster (indexan hasta un máximo de 500 páginas, no se permite la utilización de filtros de exclusión de contenidos por url, ni por tipos de archivo, no se permite controlar la profundidad a la que se indexa, etc).

Por todo ello resulta conveniente utilizar herramientas locales (ejecutadas directamente en el servidor, o mediante un cliente). Paso a comentar algunas alternativas para Windows y Linux

Herramientas server-side para Windows

Últimamente estoy empleando GSiteCrawler.

Éste software, que funciona bajo windows, nos permite crear varios proyectos al mismo tiempo y guardar los settings para cada uno de ellos.

Un pantallazo del programa en ejecución:
GSiteCrawler en ejecucion

Herramientas server-side para Linux
Google ha desarrollado GoogleSitemapGenerator, todavía en versión Beta. Ofrece versiones para Windows y Linux, ambas de libre distribución. En este caso comentaré la versión para linux.

Siguiendo el manual de instalación instalamos el software, ponemos una password para administración del nuevo servicio y hacemos un restart del Apache. La aplicación corre por defecto en el puerto 8181.

La aplicación permite definir filtros de inclusión/exclusión de contenidos, tamaños máximos de archivos, inclusión directa de los sitemaps en google, cambiar el nombre del fichero sitemap donde se guardan los resultados, etc.

Un pantallazo de la herramienta mientras comienza la indexación de contenidos…
google sitemap generator en ejecucion

[1] Herramientas para la generación de sitemaps, por categorías

Programas para ejecutar en el servidor

CMS y otros plugins

Herramientas descargables

Servicios de generación online

Librerías/Códigos fuente