RSS

Vous vous demandez comment suivre le nombre de lecteurs sur votre flux RSS / Atom de manière programmatique ? Voici une petite astuce basée sur l'injection d'une image dans le contenu d'un flux RSS / Atom.

Le concept se repose sur le fait que le Javascript et les iFrame sont généralement bloqués sur les lecteurs de flux RSS pour des raisons de sécurité. L'astuce consiste donc à injecter une image dans tous les articles que vous publiez sur votre flux de syndication.

<img src="http://monsite.com/tracker.php?content_id=12345" alt="tracker" />

Ainsi à chaque chargement de l'image pointant vers "tracker.php", le script comptabilisera la lecture et réalisera une redirection vers une image transparente ou tout simplement le logo de votre blog. Dans mon cas, j'ai retenu le logo de mon blog que j'ai positionné en bas à droite de tous mes articles publiés sur mon flux de syndication. J'utilise ce logo comme pseudo watermark du contenu publié.

L'injection de cette image dans l'ensemble des contenus exposés sur les flux de syndication a été réalisée via une modification des fichiers template de mon thème Dotclear utilisés pour générer des flux Atom et RSS2 (respectivement les fichiers atom.xml et rss2.xml):

<description>
    {{tpl:EntryExcerpt absolute_urls="1" encode_xml="1"}}
    {{tpl:EntryContent absolute_urls="1" encode_xml="1"}}
   &lt;a href=&quot;http://www.geeek.org&quot;&gt;&lt;img src=&quot;http://monsite.com/tracker.php?content_id={{tpl:EntryID}}&quot; alt=&quot;geeek&quot;  /&gt;&lt;/a&gt;
    </description>

Mon script dépose un cookie d'une durée d'un an qui permet d'identifier chaque lecteur de manière unique, le "referer" est utile pour identifier l'origine des personnes qui lisent votre contenu, on peut parfois tomber sur des URL de portails Intranet.

Enfin, un identifiant de contenu est passé en paramètre de l'image pour identifier de manière unique la lecture d'un contenu. Dans mon cas, sur Dotclear, le tag "EntryId" me permet d'identifier de manière unique chaque contenu publié.

<?php

// L'image qui s'affichera dans chaque article du flux RSS
$redirect = "http://monsite.com/monlogo.png";

$referer = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '';

// On vérifie que l'identifiant du contenu en cours de lecture est bien passé en paramètre
if (!isset($_GET['content_id'])){
        die("Missing content id");
} else {
        $content_id = $_GET['content_id'];
}

// On vérifie l'id du lecteur stocké dans un cookie
if (!isset($_COOKIE["reader_id"])){
        $reader_id = uniqid('rid_');
        setcookie("reader_id", $reader_id, time()+60*60*24*365);
} else {
        $reader_id = $_COOKIE["reader_id"];
}

// On se connecte à la base de données
$bdd = new PDO('mysql:host=localhost;dbname=feeds', 'username', 'password', array(
    PDO::ATTR_PERSISTENT => true
));

// On insère une entrée indiquant qui a lu quel contenu à quelle heure
$req = $bdd->prepare('INSERT INTO stats(reader_id,content_id,ip,referer) VALUES(:reader_id, :content_id, :ip, :referer)');
$req->execute(array(
        'reader_id' => $reader_id,
        'content_id' => $content_id,
        'ip' => $_SERVER['REMOTE_ADDR'],
        'referer' => $referer
        ));

// On redirige le navigateur avec une image transparente ou un logo
header("Status: 302 Moved Temporarily", false, 302);
header('Location: '.$redirect);
header("Connection: close");

Voici le schéma SQL utilisé pour le stockage des données :

CREATE TABLE IF NOT EXISTS `stats` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `reader_id` varchar(16) NOT NULL,
  `content_id` int(10) unsigned NOT NULL,
  `read_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `ip` varchar(16) NOT NULL,
  `referer` varchar(128) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `reader_id` (`reader_id`,`content_id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;

Il ne reste plus qu'à exploiter les données récupérées pour obtenir un comptage du nombre de lecteurs uniques sur votre flux de syndication. Voici un script PHP "stats.php" qui retournera le nombre d'adresses IP distinctes et le nombre de lecteurs identifiés au travers des cookies déposés.

<?php

$bdd = new PDO('mysql:host=localhost;dbname=feeds', 'username', 'password', array(
    PDO::ATTR_PERSISTENT => true
));

$req = $bdd->prepare('SELECT count(distinct(reader_id)) as readerCount,count(distinct(ip)) as ipCount  FROM `stats` where read_time > (NOW() - INTERVAL 30 DAY)');
$req->execute();
$rows = $req->fetchAll(PDO::FETCH_ASSOC);
header('Content-Type: application/json');
echo json_encode ($rows[0]);

Ce script vous retournera une structure JSON directement exploitable par un script Javascript :

{"readerCount":"4000","ipCount":"3000"}

Voici un exemple de récupération du nombre de lecteurs en Javascript avec JQuery, cet appel peut se faire depuis n'importe quel endroit de votre site Internet. Je vous conseillerai cependant de mettre en cache le résultat du script 'stats.php' dans un serveur Memcached ou dans la zone mémoire APC de votre serveur PHP pour économiser de la CPU sur votre base de données.

$.getJSON( "stats.php", function( json ) {
  console.log( "Nombre de lecteurs: " + json.readerCount );
 });

Le delta du nombre d'IP trouvées par rapport au nombre de cookies est lié aux réinitialisations annuels de cookie (environ 8% après 12 mois) et aux IP des passerelles Internet des opérateurs mobiles qui sont mutualisées pour l'ensemble de leurs clients.

Mon article est terminé, j'espère qu'il sera utile à ceux et à celles qui souhaitent quitter Feedburner et suivre par leur propre moyen l'évolution du nombre de lecteurs de leur flux de syndication. N'hésitez pas à poster un commentaire si vous avez la moindre question sur la solution proposée ou si vous avez des idées d'améliorations.

Tout le code source utilisé dans cet article a été publié sur GitHub sous le nom de FeedTracker : https://github.com/ltoinel/FeedTracker.

1. Le , 14:25 par Pa75
cbe9928b622f81c5fd00a837ccb24b73

Afin d'être certain que la requête arrive jusqu'au serveur (pour comptabiliser les hits), il faudrait remplacer la redirection 301 par une 302.

2. Le , 22:55 par Ludovic
9ab09dd3e305f924f8930e20e1a35843

Très bien vu ! La réponse 301 est généralement mise en cache par le navigateur.

Ajouter un commentaire

Le code HTML est affiché comme du texte et les adresses web sont automatiquement transformées.