Abr 152013
 
Artículo Administración de Servidores

A medida que un sitio web va evolucionando,  es habitual ir incorporando al mismo cambios en el diseño o en la funcionalidad que se ofrece a los usuarios.

Pero para comprobar que un cambio supone una mejora, es conveniente utilizar lo que se conoce como un test A/B.

En este artículo comentamos una posible implementación de este tipo de test en un sitio web desarrollado en lenguaje PHP.

En un test A/B, seleccionamos un porcentaje de usuarios (grupo A) a los que se les va a presentar el sitio con las modificaciones que se van a probar, mientras que al resto de usuarios (grupo B) se les sigue presentando el sitio sin modificaciones.

En paralelo, definimos las métricas que nos interesa mejorar (nº de páginas por sesión, nº de clicks por sesión,…).

Tras implementar el test, analizaremos los resultados obtenidos al cabo de un cierto tiempo que consideremos suficientemente significativo (varios días, o varias semanas), obteniendo las métricas resultantes para cada uno de los grupos. Comparando las métricas, tomaremos la decisión de implementar para la totalidad de los usuarios las modificaciones que han sido evaluadas, o bien de descartarlas.

Asignación de usuarios a grupos: Cookies

Como hemos comentado, para implementar el test debemos asignar un grupo A o B a cada usuario que visita el sitio. Como mínimo, esta asignación debe mantenerse durante toda la sesión. Idealmente, la asignación debe ser permanente, de modo que si un mismo usuario realiza varias visitas al sitio a lo largo del tiempo, siempre esté asignado al mismo grupo que se le asignó en su primera visita.

El protocolo HTTP permite implementar este mecanismo mediante Cookies.

Un cookie es una breve información que el servidor entrega al cliente, junto con la página solicitada, la primera vez que éste realiza un acceso.

En cada nuevo acceso que realiza al servidor, el cliente envía el cookie junto con la solicitud.

De este modo, en el primer acceso que realiza un cliente, el servidor puede asignarle, aleatoriamente o por algún otro criterio a uno de los grupos, y enviarle un cookie que indique el grupo al que ha sido asignado.

En los siguientes accesos, el servidor recibirá el cookie y entregará al cliente la página que ha solicitado, generando su contenido en función del grupo al que pertenezca el cliente.

Cuando se crea un cookie, se le asigna también un tiempo de vida. Por lo tanto, para que la asignación de un usuario a un grupo de test se mantenga a lo largo del tiempo, basta con asignar un tiempo de vida largo (por ejemplo, un año) al cookie

Manejo de cookies en PHP

El siguiente es un ejemplo de tratamiento de un cookie para la implementación del test A/B. Normalmente, este código formará parte del código de inicialización de la página (por ejemplo, en un fichero “header.php”).

En el ejemplo, el sitio web “www.midominio.com” utiliza un cookie llamado “midominio_grupo_ab”. Un 10% de los usuarios serán asignados al grupo “A”, y el resto al grupo “B”:

global $grupo_ab;
$grupo_ab = "";
$nuevo_grupo_ab = "";
if (array_key_exists("midominio_grupo_ab",$_COOKIE)) {
    $grupo_ab = $_COOKIE["midominio_grupo_ab"];
} else {
    $nuevo_grupo_ab = "A";
    if (rand(1,100) > 10) {
        $nuevo_grupo_ab = "B";
    }
}
if (array_key_exists("ab",$_GET)) {
    $nuevo_grupo_ab = $_GET["ab"];
}
if ( $nuevo_grupo_ab) {
    setcookie ( "midominio_grupo_ab", $nuevo_grupo_ab, time()+365*24*60*60,
                "/" , "www.midominio.com", false , false);
    $grupo_ab = $nuevo_grupo_ab;
}
  • Líneas 1-10:

El servidor web pone a disposición del script PHP una variable global $_COOKIE, en donde están todos los cookies recibidos del cliente correspondientes al dominio del sitio web (en el ejemplo, “www.midominio.com”)

En primer lugar, se comprueba si se ha recibido un cookie llamado “midominio_grupo_ab”. Si es así, el grupo al que pertenece el usuario es el valor del cookie.

Si no se ha recibido el cookie, se asigna aleatoriamente el usuario al grupo “A” o “B” con una probabilidad de un 10%/90%.

  • Líneas 11-13:

Opcionalmente, y para poder depurar la implementación, se le puede añadir un argumento “ab” a la url con la que se accede al servidor, forzando a que el grupo al que sea asignado el usuario sea el indicado por el valor del argumento (por ejemplo, accediendo con la url “http://www.midominio.com/?ab=A”).

  • Líneas 14-18:

Si el acceso que realizó el cliente no incluía el cookie, el servidor llama a la función setcookie() para crear el cookie que será enviado al cliente junto con la respuesta a la solicitud recibida. El nuevo cookie se llama “midominio_grupo_ab” y tiene un tiempo de vida de un año.

Inclusión en el log de accesos del grupo asignado.

Naturalmente, para poder extraer métricas detalladas por grupo, la información del grupo a que pertenece cada acceso debe estar incluida en los logs de acceso del servidor web.

Para ello, debemos definir un “custom format” en el fichero de configuración del servidor web Apache.

La manera de hacerlo depende de la manera en que el servidor web ejecuta el código php: mediante mod_php o como un cgi (p.ej., con mod_fcgid).

Caso 1. mod_php

En este caso, se puede utilizar el API de apache en PHP para comunicar el script PHP con el servidor Apache.

Utilizamos la llamada a apache_note:

apache_note('AB', $grupo_ab);

Y definimos un “custom format” para el log de accesos de la forma:

LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\" \"%{AB}n\"" combined_ab

Caso 2. CGI

En este caso, la comunicación mediante el API no es factible, pero todavía es posible la comunicación entre PHP y el servidor Apache mediante los headers HTTP que el CGI entrega en la respuesta.

Añadimos un header:

header('AB: ',$grupo_ab);

Y definimos el “custom format” del log de accesos de la forma:

LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\" \"%{AB}o\"" combined_ab

Generación del contenido en función del grupo asignado

Una vez que el sistema de asignación de usuarios a grupos está operativo, podemos empezar a probar cambios en el contenido que se entrega a los clientes. Para ello, utilizamos la variable global $grupo_ab. Por ejemplo, si queremos probar un cambio en el pie de página:

– Colocamos el código PHP que genera el pie de página para el grupo A en un fichero “footer_A.php”, y el que genera el pie de página para el grupo B  en un fichero “footer_B.php”

– Incluimos uno u otro footer en el CGI principal (“index.php”) de la siguiente forma:

global $grupo_ab;
if ($grupo_ab =="A") {
    include("footer_A.php");
} else {
    include("footer_B.php");
}

Indice de artículos sobre programación en lenguaje PHP

 Publicado por en 6:00 pm

 Deja un comentario

(requerido)

(requerido)