Tagged:geoposicionamiento

Opciones disponibles para aplicaciones web que necesitan geoposicionamiento

Hace poco estuve trabajando en la web afterguantanamo.com y uno de los requisitos que queríamos cubrir era la posibilidad de tener la web en varios idiomas y que en función del país desde el que se visitase (después de todo se trata de un tema internacional), la web se mostrase en un idioma o en otro de manera automática. Para conseguirlo era necesario utilizar algún sistema de geoposicionamiento, por lo que me puse a investigar las opciones disponibles.

Después de mirar por aquí y por allá, encontré que el servicio de wipmania.com era una solución rápida bastante fácil de implementar que no exigía prácticamente ningún esfuerzo. Además, el servicio es gratuito, lo que lo hizo una elección muy sencilla respecto a otras soluciones de pago. Para utilizar este servicio no hay más que pasar a su servidor la consulta con la IP de la que queremos averiguar el país, y este nos devuelve un código de 2 caracteres que representa de forma unívoca a cada país. En principio, la consulta sólo se puede realizar a través de un método GET con el formato

http://api.wipmania.com/[DIRECCION_IP]?[URL]

donde [DIRECCION_IP] es la IP de la que queremos obtener el país y [URL] es la dirección de nuestra página web.

La única pega que tiene este magnífico servicio es que limitan el número de consultas que se pueden realizar por dominio y día a 10.000 (para eso hace falta el parámetro URL). Si prevemos que nuestro website puede generar más de 10.000 consultas diarias, entonces esta solución no es válida, o habría que combinarla con algún tipo de limitación interna que previera un comportamiento por defecto una vez rebasado el límite diario.

Investigando más a fondo descubrí que el API de wipmania.com también contaba con una interfaz de consulta javascript-json y -mira qué bien- si la consulta se hacía a través de este API en vez de a través del método GET anteriormente descrito, la limitación de consultas por día desaparecía, por lo tanto esta fue la solución inicial para afterguantanamo.com: al cargar la página principal se ejecutaba un script que realizaba la consulta por ajax (con jQuery para facilitar las cosas) hacia wipmania.com y realizaba una redirección una vez averiguado el código de la ciudad. El script era algo así:

$(document).ready(function(){
  var castellano = "AR,BO,CL,..."; //países de habla castellana
  var frances = "FR,CD,..."; //países de habla francesa
  var italiano = "IT,VA,..."; //países de habla italiana
  $.getJSON("http://api.wipmania.com/jsonp?callback=?", function(data) {
    if(castellano.indexOf(data.address.country_code)>-1)
      location.href="castellano/";
    else if(frances.indexOf(data.address.country_code)>-1)
      location.href="francais/";
    else if(italiano.indexOf(data.address.country_code)>-1)
      location.href="italiano/";
    else location.href="english/";
  });
})

Para completar la información he de decir que el API javascript-json devuelve muchos más datos aparte del código del país: latitude, longitude, zoom, address.city, address.country, address.country_code y address.region. Se puede encontrar una explicación más detallada de lo que significa cada uno de estos resultados aquí : http://www.wipmania.com/en/blog/geolocation-api-json-jsonp/, y por cierto también se puede descargar un listado de todos los códigos de todos los países aquí : http://static.wipmania.com/static/countries.txt.

Esta solución funciona perfectamente excepto por un pequeño detalle : la latencia o retardo que sufre la página como consecuencia de la consulta hacia un servicio externo, que en caso de wipmania.com es muy bajo, pero aun así, son 2 ó 3 segundos que se añaden a la carga inicial de la página, y yo quería que esta fuera lo más rápida posible.

GeoIP de MaxMind al rescate

A pesar de que la página funcionaba correctamente y que después de varias semanas de prueba no nos había dado ningún problema, yo no estaba contento con esos segundos de más que se añadían siempre a la carga inicial de la página. La solución para ello era conseguir de alguna forma consultar algún tipo de base de datos local que a ser posible devolviera lo mismo que Wipmania: un código de 2 letras que me permitiese identificar los países fácilmente, y obviamente yo no estaba por la labor de crear semejante tipo de base de datos.

La búsqueda me llevó al sistema propuesto por Maxmind que es precisamente eso: una base de datos local que te puedes descargar e instalar en tu servidor y que además tiene APIs para un montón de lenguajes (C, Perl, PHP, Java, Python, C#, Ruby, VB.NET, Pascal, etc). En este caso la solución también es gratuita si te conformas con pocas prestaciones (obtener información sólo acerca del país y basándose en una BD con actualización semi-frecuente) y de pago si se desean más prestaciones (información sobre ciudades e incluso poblaciones, o actualización de la BD permanente). Mi caso estaba claro: la base de datos gratuita me bastaba y me sobraba y con el API PHP la solución era perfecta.

La instalación pasa sólo por la descarga y guardado en cualquier carpeta accesible por nuestros scripts PHP del único fichero que compone la BD de países y en mi caso la descarga del API PHP “geoip.inc.php”. Una vez instalado, sólo me hizo falta añadir el siguiente código PHP en la página de inicio:

include("geoip.inc.php");
$gi = geoip_open("[ruta_hacia]/geoip.dat",GEOIP_STANDARD);
$codigo_pais = geoip_country_code_by_addr($gi,$_SERVER["REMOTE_ADDR"]);
echo "..." . $codigo_pais . "..." //meterlo en cualquier contenedor visible por javascript

y posteriormente sólo hace falta modificar el javascript original para que en vez de tomar el código de wipmania lo tome del contenedor en el que hemos escrito nuestro código sacado de la BD local. El código javascript modificado quedaría algo así:

$(document).ready(function(){
  var castellano = "AR,BO,CL,..."; //países de habla castellana
  var frances = "FR,CD,..."; //países de habla francesa
  var italiano = "IT,VA,..."; //países de habla italiana
  var codigo_pais = $("[acceso_al_contenedor]").val();
  if(castellano.indexOf(codigo_pais)>-1)
    location.href="castellano/";
  else if(frances.indexOf(codigo_pais)>-1) 
    location.href="francais/";
  else if(italiano.indexOf(codigo_pais)>-1)
    location.href="italiano/";
  else location.href="english/";
})

Ni qué decir que la latencia por consulta externa queda eliminada y que la velocidad de carga de la página ahora sólo depende de la velocidad y carga del propio servidor web. Misión cumplida.

{ Piensa / Think }

"This is a waste of life. [...] the entire educational system in the modern day is nothing more than a cookie cutter processing plant that prepares humans for mostly predefined occupational roles. This element of human life has become so traditionally ingrained, that many falsely consider the nature of ‘having a job’ some form of human instinct. Even parents will ask their kids “What do you want to be when you grow up?” as though there was only one thing. This is disturbing and a violation of human potential." - The Zeitgeist Movement


"He aprendido que hay cosas que pueden ser comprendidas pero que nunca podrán ser explicadas con palabras sin desvirtuar su grandeza" - Andrés Pascual


"You never change things by fighting the existing reality. To change something, build a new model that makes the existing model obsolete." - Buckminster Fuller


"... I am the master of my fate. I am the captain of my soul." - William Ernest Henley