Thématiques :

Suivre et analyser les clics de ses utilisateurs en Php et jQuery

Posé ici le vendredi 19 décembre 2008 à 14:00 par Jay Salvat

Suivre les clics de ses visiteurs grâce à Php et jQuery

Dans la chasse aux statistiques, le comportement du visiteur sur une page donnée peut s'avérer être un élément analytique important pour en ajuster la conception. Des sites tels que Crazy Eggs l'ont compris et proposent déjà ce genre de services. J'adore ce principe et je n'ai encore pas pu résister à l'envie de tripatouiller Php et jQuery pour me rapprocher des options de base d'un tel outil.

Voir la démo

Ce que je veux

Je veux pouvoir analyser la cohérence et l'efficacité de la mise en page de mes sites en suivant le comportement de mes utilisateurs grâce à un plugin qui s'intégrerait facilement à mes pages et permettant :

  • L'enregistrement des clics de mes visiteurs sur la page entière ou sur un élément précis.
  • L'activation et la désactivation de ces enregistrements
  • La représentation graphique de ces clics en surimpression sur la page.

Mise en place

L'enregistrement des positions de clics demandent de stocker des informations dans une base de données (ici MySql). Cette table est la suivante :

Schéma de la table MySql clickmap
CREATE TABLE  `clickmap` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `x` smallint(4) unsigned NOT NULL,
  `y` smallint(4) unsigned NOT NULL,
  `location` varchar(255) NOT NULL,
  PRIMARY KEY  (`id`),
  KEY `location` (`location`)
)

Nous créons une simple table pour y stocker les coordonnées X et Y des clics ainsi que le chemin de la page concernée. Pour la clarté de ce tutoriel, je ne me consacre qu'à l'essentiel. Libre à vous d'y ajouter par la suite l'adresse IP du visiteur, la date et heure du clic pour que vos statistiques soient plus pointues.

Maintenant créons les fichiers principaux. Dans un dossier nommé clickmap, créez un premier fichier nommé clickmap.js contenant les lignes ci-dessous. Pour plus d'information sur ces lignes et sur la conception d'un plugin jQuery, je vous invite à lire Créez votre propre plugin jQuery d'infobulles.

Fichier clickmap.js
(function($) {

    // ...

})(jQuery);

Dans le même dossier, créez un nouveau fichier nommé clickmap.php contenant cette fois ci la connexion à la base de données. Remplacez les valeurs entre crochets par vos paramètres de connexion.

Fichier clickmap.php
<?php
$DB = mysql_connect("[server]", "[username]", "[password]");
mysql_select_db("[db]", $DB);    

// ...

mysql_close($DB);
?>
Fichier clickmap.css

Encore dans le même dossier, créez maintenant clickmap.css. Nous reviendrons sur son contenu en détail par la suite. Deux images seront aussi utilisée : L'image de Chargement et celle qui illustre le clic du visiteur. Ces deux images sont à placer dans un dossier images au même niveau que les autres fichiers.

Voilà pour la partie contraignante de mise en place. Le projet devrait ressembler à ça :

L'arbo

La logique

C'est très simple. Ce plugin jQuery fonctionnera conjointement avec un script Php. Les coordonnées récupérées côté client seront envoyées par des requêtes Ajax pour être enregistrées dans la base côté serveur. Pour l'interrogation, même principe. Le script client demande au serveur les coordonnées précédemment enregistrées pour les afficher en surimpression sur la page en cours.

L'enregistrement des coordonnées de clics

Pour mieux suivre le déroulement des opérations, nous allons travailler sur deux scripts en parallèle : Le clickmap.js pour la logique côté client, et clickmap.php pour l'interaction avec la base de données côté serveur.

Dans clickmap.js
$.fn.saveClicks = function() {
    $(this).bind('mousedown.clickmap', function(evt) {
        $.post('/clickmap/clickmap.php', { 
            x:evt.pageX, 
            y:evt.pageY, 
            l:escape(document.location.pathname)
        });
    });
};

Le plugin saveClicks active l'écoute des clics sur un ou des éléments de la page. A chaque clic (événement mousedown) les coordonnées de la souris (evt.pageX et evt.pageY) ainsi que l'URL de la page (document.location.pathname)sont envoyés à clickmap.php. On remarquera que l'événement prend la forme mousedown.clickmap qui nous permettra de supprimer notre événement sans supprimer d'éventuels écoutes mousedown appliquées par d'autres scripts.

Dans clickmap.php
if (isset($_POST['l'])) {
    $query = sprintf("  INSERT INTO clickmap 
                        SET x = '%s', y = '%s', location = '%s'", 
                        $_POST['x'], $_POST['y'], $_POST['l']);       
    $result = mysql_query($query);
}

Clickmap.php se content de récupérer les données postées en Ajax par clickmap.js et de les enregistrer dans la base de données. Ça y est l'enregistrement de nos statistiques est déjà en place. Je vous avez dit que ce serait très simple.

La restitution des coordonnées de clic

Passons maintenant à la méthode d'affichage des clics sur la page donnée. Cette étape est à peine plus compliquée que la précédente.

Dans clickmap.js
$.displayClicks = function() {
    $('<div id="clickmap-overlay"></div>').appendTo('body');
    $('<div id="clickmap-loading"></div>').appendTo('body');

    $.get('/clickmap/clickmap.php', { l:escape( document.location.pathname) }, 
        function(html) {
            $(html).appendTo('body');    
            $('#clickmap-loading').remove();
        }
    );
};

Contrairement à saveClicks, la méthode displayClicks ne s'applique pas à un ou des éléments particuliers. Il donc a la forme $.monPlugin() et non $.fn.monPlugin(). Il créé deux div et les ajoute au Body. L'un est nommé #clickmap-overlay et masquera la page d'un calque noire en surimpression. Le second, nommé #clickmap-loading, contient l'image d'alerte de chargement.

Une requête Ajax en méthode GET cette fois est lancée à clickmap.php pour récupérer les coordonnées des clics de la page en cours ( document.location.pathname ). Le contenu ainsi délivré par clickmap.php est à son tour ajouté au Body.

Dans clickmap.php
if (isset($_GET['l'])) {
    $query = sprintf("  SELECT x, y FROM clickmap 
                        WHERE location = '%s'
                        ORDER BY id DESC", 
                        $_GET['l']);
    $results = mysql_query($query);
        
    $html = '<div id="clickmap-container">';
    while ($row = mysql_fetch_array($results)) {
        $html .= sprintf('<div style="left:%s px; top:%s px"></div>', 
                                    $row['x'] - 10,
                                    $row['y'] - 10);
    }
    $html .= '</div>';
    
    echo $html;
}

Côté serveur on teste si une requête GET est passée. La base de données est interrogée avec le chemin de la page concernée pour ne récupérer que les coordonnées des clics de celle-ci. A partir de ces points, on créé un nouveau calque #clickmap-container qui contient autant de div qu'il y a de clics. Les coordonnées du clic sont directement appliquées dans l'attribut style. Le HTML généré ressemble à celui-ci.

HTML généré en Php à partir des données de la base
<div id="clickmap-container">
    <div style="left:515px;top:341px"></div>
    <div style="left:414px;top:214px"></div>
    <div style="left:527px;top:548px"></div>
    <div style="left:514px;top:157px"></div>
</div>

C'est cette portion de HTML qui est ajoutée au Body par clickmap.js.

Mise en forme

Un peu de coloriage maintenant pour finir de mettre la glue entre les différents éléments.

Dans clickmap.css
#clickmap-overlay {
    position:fixed;
    top:0; left:0;
    width:100%; height:100%; 
    background-color:#000;
    filter:alpha(opacity=70); opacity : 0.7;
}

Le calque #clickmap-overlay est posé en surimpression sur la page. D'un noir légèrement transparent, il est placé en haut à gauche et épouse les largeurs et hauteurs de la page.

#clickmap-loading {
    position:fixed;
    top:0; left:0;
    width:100%; height:100%; 
    background:transparent url(images/loading.gif) no-repeat center center;
}

De la même manière le calque #clickmap-loading est placé mais cette fois il contient l'image de chargement en background.

#clickmap-container div {
    position:absolute;
    width:20px; height:20px;
    background:transparent url(images/click.png) no-repeat center center;
}

Puis on applique l'image représentant le clic aux calques contenus par #clickmap-container.

Usage

Les façons d'utiliser cet outil sont multiples, faites peuvent d'imagination, d'autant que le script complet offre d'autres méthodes bien utiles.

<link rel="stylesheet" type="text/css" href="/clickmap/clickmap.css" />
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="clickmap/clickmap.js"></script>
Après l'inclusion réglementaire de jQuery et des différents fichiers clés, l'appel peut se faire ainsi pour la page entière.
$(function() {
  $(document).saveClicks();
});

Où comme ceci pour n'enregistrer par exemple que les clics sur un élément précis de la page.

$(function() {
  $('#myImage').saveClicks();
});

Pour la consultation des enregistrements, rien de plus simple. On peut par exemple utiliser un paramètre passé dans l'URL, ici mapage.php?displayClick pour déclencher l'affichage.

$(function() {
<?php if (isset($_GET['displayClick'])) : ?>
    $.displayClicks();
<?php else: ?>
    $(document).saveClicks();
<?php endif ?>
});

Trouvez ci-dessous la logique que j'utilise pour la démonstration de cet article. Tout est dans les commentaires. Cet exemple nécessite la version complète du plugin.

<script type="text/javascript">
$(function() {
    // L'enregistrement des clics est activé dès l'affichage de la page
    $(document).saveClicks();

    // Si le lien #demo est cliqué...
    $('a#demo').click(function() {
        // Je stoppe l'enregistrement des clics
        $(document).stopSaveClicks();

        // J'affiche le calque de surimpression des clics.
        $.displayClicks();

        // Si le calque est cliqué
        $('#clickmap-overlay').click(function() {
            // Le calque est supprimé
            $.removeClicks();

            // Je réapplique l'enregistrement des clics.
            $(document).saveClicks();
        });

        return false;
    });
});
</script>

Le Code dans son intégralité

Après les explications, voici le code dans son intégralité. Quelques bonus dans le code jQuery qui ajoute des fonctionnalités comme couper l'enregistrement des clics ou effacer l'affichage des coordonnées. Le code entier est téléchargeable en fin d'article.

Code
/** 
 * Suivre et analyser les clics de ses utilisateur en Php et jQuery 
 * par Jay Salvat - http://blog.jaysalvat.com/ 
 */

(function($) {

// Un clic déclenche une requête Ajax vers le script Php
// qui enregistrera les coordonnées cliquées.
$.fn.saveClicks = function() {
    $(this).bind('mousedown.clickmap', function(evt) {
        $.post('/clickmap/clickmap.php', { 
            x:evt.pageX, 
            y:evt.pageY, 
            l:escape(document.location.pathname)
        });
    });
};

// Supprime l'écoute des clics de la précédente fonction
$.fn.stopSaveClicks = function() {
     $(this).unbind('mousedown.clickmap');
};

// Une requête Ajax interroge le script Php qui renvoie les coordonnées précédemment
// enregistrées. Elles sont affichées sur un calque en surimpression.
$.displayClicks = function(settings) {
    $('<div id="clickmap-overlay"></div>').appendTo('body');

    $('<div id="clickmap-loading"></div>').appendTo('body');

    $.get('/clickmap/clickmap.php', { l:escape( document.location.pathname) }, 
        function(html) {
            $(html).appendTo('body');    
            $('#clickmap-loading').remove();
        }
    );
};

// Supprime le calque de la précédente fonction
$.removeClicks = function() {
    $('#clickmap-overlay').remove();
    $('#clickmap-container').remove();
};
        
})(jQuery);
Le script Php au niveau serveur
<?php
/** 
 * Suivre et analyser les clics de ses utilisateur en Php et jQuery 
 * par Jay Salvat - http://blog.jaysalvat.com/ 
 */

// Connection à votre base de données
$DB = mysql_connect("[server]", "[username]", "[password]");
mysql_select_db("[db]", $DB);     

// Les données reçue en POST par la requête Ajax sont enregistrées dans la base
if (isset($_POST['l'])) {
    $query = sprintf("  INSERT INTO clickmap 
                        SET x = '%s', y = '%s', location = '%s'", 
                        $_POST['x'], $_POST['y'], $_POST['l']);       
    $result = mysql_query($query);
}

// Les données reçues en GET par la requête Ajax permettent d'interroger la base
// pour en obtenir les coordonnées enregistrées.
// Une portion HTML avec les images est construite et renvoyée.
if (isset($_GET['l'])) {
    $query = sprintf("  SELECT x, y FROM clickmap 
                        WHERE location = '%s'
                        ORDER BY id DESC", 
                        $_GET['l']);
    $results = mysql_query($query);
        
    $html = '<div id="clickmap-container">';
    while ($row = mysql_fetch_array($results)) {
        $html .= sprintf('<div style="left:%spx;top:%spx"></div>', $row['x'] - 10, $row['y'] - 10);
    }
    $html .= '</div>';
    
    echo $html;
}

// Fermeture de la connexion à la base de données.
mysql_close($DB);
?>

Télécharger le code

Conclusion

Et voilà un simple mais sympathique outil réalisé en quelques minutes avec nos petits doigts gourds. Cet outil est limité mais reste idéal pour compléter vos statistiques.

Il n'est efficace que sur les pages statiques. On pourrait aller plus loin en mettant en cache sur le serveur une copie de la page analysée pour que les placements de clics restent cohérents selon les différentes version du contenu. Aussi, la différence de rendu des navigateurs peut donner de petits, voire de gros, écarts entre les zones cliquées.

Le procédé est loin d'être parfait mais l'exercice me paraissait tout de même intéressant techniquement à développer.

Trackbacks

0 trackback

Commentaires

12 commentaires

Enorme ! Je bookmark sur le champs ! Et merci ;)

1. Par Julien le vendredi 19 décembre 2008 à 14:30

Super ce tuto!! mais ca ne fonction pas chez moi

2. Par Jérôme le vendredi 09 janvier 2009 à 19:21

Bonsoir Jérôme,

Si tu ne m'en dis pas plus, je ne pourrai pas t'aider :)

3. Par Jay Salvat le vendredi 09 janvier 2009 à 19:28

bonsoir

Donc j'ai mis le dossier clickmap sur le serveur,j'ai changé les paramétre de connexion dans clickmap.php

créer une base de donnée nommée clickmap

mais aprés je ne sais quoi faire.

4. Par Jérôme le vendredi 09 janvier 2009 à 19:38

Je vais reprendre ce que j'ai fais de AàZ

-j'ai changé les parametre de connexion mot de passe,id de connexion et nom de la base de donnée
$DB = mysql_connect("[91.121.89.29]", "[ID de connexion]", "[motdepasse]");
mysql_select_db("[demo_clickmap]", $DB);

-créer la base de donnée "demo_clickmap"
-créer la table "demo_clickmap"

puis j'ai fais dans mon navigateur
Monsite.com/ind…hp?displayClick

mais ca ne fonction pas
dois-je ajouter des lignes dans mon index ?

5. Par Jérôme le vendredi 09 janvier 2009 à 22:24

Bonjour Jéröme,

Oui, tu as du zapper le chapitre "Usage".
Une fois tout mis en place, tu dois insérer jQuery et le starter.

6. Par Jay Salvat le dimanche 11 janvier 2009 à 10:23

ça c'est du tutoriel complet précis, et brut de dézipage pour le faire fonctionner. j'y vais de ce pas. ça a l'air énorme

7. Par Maison de retraite le lundi 12 janvier 2009 à 15:40

Découvrir un blog en anglais via un français c'est courant, mais découvrir un blog de qualité en français grâce à un blog en anglais c'est bien la première fois que ça m'arrive ;)

Très sympa ce tuto, et très bien expliqué, félicitations :)

8. Par Cerium le mardi 20 janvier 2009 à 17:48

Bonsoir Cerium,
Et bien, bienvenu :)
C'est vrai que c'est peu courant dans ce sens là :)

9. Par Jay Salvat le mardi 20 janvier 2009 à 22:43

Excellent, exactement ce que je cherchais, merci à toi :)

10. Par Math le dimanche 03 mai 2009 à 16:11

Bonsoir Math,
Ceci est le tutoriel.

Si tu veux une version plus aboutie, j'ai mis le source sur Github.
Github.com/jays…ker/tree/master

11. Par Jay Salvat le dimanche 03 mai 2009 à 18:56

Bonjour,
je trouve ton travai "Suivre et analyser les clics" trés interressant (et même plus !). Je te propose de le mettre en ligne sur mon site Business-internet-site.fr pour le proposer à mes visiteurs. Si tu es interressé par ma proposition envoie un mail en me donnant tes conditions.

Cordialement
Jean-Jacques Olivier

12. Par Olivier Jean-jacques le dimanche 30 août 2009 à 16:01

Obligatoire. Vrai nom apprécié.

Il ne sera ni affiché, ni spammé.

Votre blog ou votre site web.

Constructif, courtois et correctement écrit. SMS proscrit. Merci.