Intelligence Artificielle

Tracker les agents IA et crawlers ChatGPT, Claude, Perplexity sur son site avec Matomo

2026-05-06 · Pierre

En 2026, une part non négligeable du trafic d’un site web ne vient plus d’un humain devant un navigateur, mais d’agents IA et de crawlers d’entraînement. Le problème : ces visiteurs sont quasi invisibles dans Matomo par défaut. Le script JavaScript de tracking ne s’exécute pas chez eux, et les crawlers d’entraînement sont filtrés comme bots génériques. Résultat : vos stats Matomo sous-estiment massivement la réalité de l’exposition de votre contenu à l’écosystème IA.

Ce guide explique comment on a résolu le problème sur datacampus.fr, avec un retour d’expérience complet : les pièges, les fausses pistes (la doc qui circule sur le web est partiellement obsolète), et la configuration finale qui marche.

Sommaire

1. Deux familles de bots IA à distinguer absolument

Premier réflexe en lisant la liste des user-agents IA : vouloir tout balancer dans un même bucket. Mauvaise idée. Il y a deux catégories très différentes, qui imposent un traitement différent.

Famille Exemples d’UA Déclenché par Fréquence
Chatbot users (humain via IA) ChatGPT-User, Claude-User, Perplexity-User, MistralAI-User, Gemini-Deep-Research, Google-NotebookLM Un humain pose une question à une IA, qui consulte votre site en direct pour répondre Sporadique, suit le rythme des requêtes humaines
AI crawlers (entraînement / indexation) GPTBot, ClaudeBot, CCBot, PerplexityBot, Google-Extended, Applebot-Extended, Bytespider, Meta-ExternalAgent... Robot autonome qui aspire le web pour entraîner ou alimenter un modèle Continu, par vagues, parfois agressif

Les deux populations méritent d’être trackées, mais pas dans le même rapport. Un chatbot user, c’est un signal d’engagement utilisateur (votre contenu est cité en réponse à une question réelle). Un AI crawler, c’est un signal d’exposition au modèle (votre contenu est avalé pour entraînement futur). Mélanger les deux, c’est se priver d’informations stratégiques.

2. Le plugin natif Matomo BotTracking

Bonne nouvelle : depuis Matomo 5.8 (sorti début 2026), un plugin natif BotTracking est livré avec le cœur. Il génère un rapport AI Chatbots Overview qui agrège les hits des chatbot users, dans une table SQL dédiée (matomo_log_bot_request) qui ne pollue pas vos stats humaines.

Mais attention : ce plugin a deux limites importantes.

Limite 1 : 6 user-agents hardcodés, et c’est tout

Le plugin reconnaît exactement 6 patterns, listés en dur dans plugins/BotTracking/BotDetector.php :

'ChatGPT-User'         => BOT_TYPE_AI_CHATBOT,
'MistralAI-User'       => BOT_TYPE_AI_CHATBOT,
'Gemini-Deep-Research' => BOT_TYPE_AI_CHATBOT,
'Claude-User'          => BOT_TYPE_AI_CHATBOT,
'Perplexity-User'      => BOT_TYPE_AI_CHATBOT,
'Google-NotebookLM'    => BOT_TYPE_AI_CHATBOT,

Pas de GPTBot, pas de ClaudeBot, pas de CCBot. Le plugin est strictement limité aux chatbot users, pas aux crawlers d’entraînement. Pour ces derniers, il faut une solution maison (qu’on verra plus loin).

Limite 2 : les chatbot users ne lisent pas le JavaScript

Même en activant le plugin, vous ne verrez rien dans le rapport. Pourquoi ? Parce que les agents IA récupèrent vos pages en HTTP simple, sans exécuter le JavaScript. Le script Matomo ne tourne donc jamais chez eux. Il faut tracker côté serveur, en envoyant un hit HTTP au tracker Matomo depuis votre code PHP.

Le paramètre clé que personne ne documente correctement : recMode=2

C’est là qu’on a perdu une heure. Les articles qu’on trouve en cherchant "Matomo bot tracking" mentionnent souvent le paramètre bots=1. Ce paramètre existe, mais il ne déclenche pas le plugin BotTracking. Le bon paramètre, documenté dans la référence officielle de l’API HTTP Tracking, est recMode=2 :

# Test rapide depuis un autre serveur
curl "https://matomo.example.com/matomo.php?\
idsite=1&rec=1&url=https://votresite.com/&\
ua=ChatGPT-User/1.0&recMode=2&\
token_auth=VOTRE_TOKEN&cip=20.171.207.1"

Vérification directe en SQL :

SELECT bot_name, COUNT(*) FROM matomo_log_bot_request
WHERE DATE(server_time) = CURDATE()
GROUP BY bot_name;

Si rien n’apparaît alors que vous êtes sûr d’avoir envoyé le hit, lisez la section "pièges classiques" plus bas. Spoiler : l’exclusion d’IP globale dans Matomo bloque souvent les tests.

3. Le tracker serveur en PHP, version fire-and-forget

L’objectif : au chargement de chaque page, détecter si l’UA correspond à un bot IA, et si oui envoyer un hit Matomo. Sans ralentir la réponse HTTP. La recette : register_shutdown_function + fastcgi_finish_request + cURL avec timeout court.

// includes/bot-tracker.php (extrait)
$ua = $_SERVER['HTTP_USER_AGENT'] ?? '';
if ($ua === '') return;

// 6 chatbot users (alimentent le plugin natif sur idsite=1)
$chatbot_user_patterns = [
    'ChatGPT-User'         => 'openai',
    'Claude-User'          => 'anthropic',
    'Perplexity-User'      => 'perplexity',
    'MistralAI-User'       => 'mistral',
    'Gemini-Deep-Research' => 'google',
    'Google-NotebookLM'    => 'google',
];

// AI crawlers (envoyés vers idsite=2 avec dimensions)
$ai_crawler_patterns = [
    'GPTBot'             => 'openai',
    'ClaudeBot'          => 'anthropic',
    'CCBot'              => 'commoncrawl',
    'PerplexityBot'      => 'perplexity',
    'Google-Extended'    => 'google',
    'Applebot-Extended'  => 'apple',
    'Bytespider'         => 'bytedance',
    'Meta-ExternalAgent' => 'meta',
    // ... 20 patterns supplémentaires
];

// Détection (chatbot d'abord, puis crawler, exclusif)
foreach ($chatbot_user_patterns as $pattern => $provider) {
    if (stripos($ua, $pattern) !== false) {
        $detected_bot = $pattern;
        $detected_mode = 'chatbot_user';
        break;
    }
}

// Envoi différé après la réponse HTTP
register_shutdown_function(function () use (...) {
    if (function_exists('fastcgi_finish_request')) {
        fastcgi_finish_request();
    }

    $params = [
        'rec'        => 1,
        'url'        => $url,
        'ua'         => $ua,
        'cip'        => $ip,
        'token_auth' => MATOMO_BOTS_TOKEN,
    ];
    if ($detected_mode === 'chatbot_user') {
        $params['idsite']  = 1;
        $params['recMode'] = 2;
    } else {
        $params['idsite']     = 2;
        $params['bots']       = 1;
        $params['dimension1'] = $detected_bot;
        $params['dimension2'] = $detected_provider;
        $params['dimension3'] = 'ai-crawler';
    }

    $ch = curl_init('https://matomo.example.com/matomo.php');
    curl_setopt_array($ch, [
        CURLOPT_POST              => true,
        CURLOPT_POSTFIELDS        => http_build_query($params),
        CURLOPT_CONNECTTIMEOUT_MS => 500,
        CURLOPT_TIMEOUT_MS        => 1000,
    ]);
    curl_exec($ch);
    curl_close($ch);
});

Trois points clés :

  • fastcgi_finish_request() renvoie la réponse HTTP au client avant que la fonction shutdown ne s’exécute. Le bot IA ne subit pas la latence du tracking.
  • Timeouts courts (500 ms connect, 1 s total). Si Matomo est en panne, votre site reste rapide.
  • Les deux familles sont mutuellement exclusives. Un UA matche soit l’une soit l’autre, jamais les deux. Le break après détection garantit qu’on ne double-compte pas.

Inclure ce fichier au tout début de votre header.php (ou équivalent) suffit. Pas besoin de modifier chaque page.

4. Pourquoi deux sites Matomo séparés

Notre choix architectural : deux idsite distincts.

idsite=1 — Site principal
  • Visiteurs humains (JavaScript classique)
  • + 6 chatbot users (server-side, recMode=2)
  • Rapport "AI Chatbots Overview" disponible
  • Stats humaines pas polluées par les bots
idsite=2 — Crawlers
  • AI crawlers (~28 patterns : GPTBot, ClaudeBot...)
  • Search crawlers (Googlebot, Bingbot...)
  • Custom dimensions : bot_name, bot_provider, bot_category
  • Filtrage simple par dimension dans Matomo

Pourquoi ne pas tout mettre sur idsite=1 ? Parce que les crawlers d’entraînement (autonomes, agressifs) génèrent un volume tel qu’ils écrasent les stats humaines dans tous les rapports géographiques, navigateurs, OS, technos. Mieux vaut une séparation nette.

Créer les custom dimensions sur idsite=2

# Via API (3 dimensions au scope action)
curl -X POST "https://matomo.example.com/" \
  -d "module=API&method=CustomDimensions.configureNewCustomDimension" \
  -d "idSite=2&name=Bot%20Name&scope=action&active=1" \
  -d "token_auth=$TOKEN"
# Répéter pour Bot Provider et Bot Category

5. Import quotidien des logs Apache

Le tracker serveur capture les bots qui visitent en temps réel. Mais si on l’a mis en place tardivement, ou si on veut un filet de sécurité, on peut compléter avec un import quotidien des logs Apache via import_logs.py (livré avec Matomo).

#!/bin/bash
# /usr/local/bin/matomo-import-bots.sh
TOKEN=$(cat /etc/matomo/import-token)
LOG_FILE='/var/www/votresite/log/access.log.1'
FILTER='GPTBot|OAI-SearchBot|ClaudeBot|anthropic-ai|Claude-Web|\
Claude-SearchBot|PerplexityBot|Google-Extended|Applebot-Extended|\
Meta-ExternalAgent|Meta-ExternalFetcher|Bytespider|Amazonbot|YouBot|\
DuckAssistBot|cohere-ai|CCBot|DeepSeekBot|Diffbot|ExaBot|\
FirecrawlAgent|PanguBot|AI2Bot|Timpibot|Webzio-Extended|Omgilibot|\
iaskspider|ChatGLM-Spider'

grep -E "$FILTER" "$LOG_FILE" | python3 import_logs.py \
  --url=https://matomo.example.com --idsite=2 --token-auth=$TOKEN \
  --recorders=2 --enable-bots --log-format-name=ncsa_extended -

Important : ne pas inclure les chatbot users (ChatGPT-User, Claude-User...) dans le filtre. Ils sont déjà trackés en temps réel par bot-tracker.php vers idsite=1. Les ajouter ici créerait un double comptage.

Synchronisation avec logrotate

Sur Debian/Ubuntu récents, c’est systemd-logrotate.timer qui rotate les logs Apache quotidiennement à 00:00. Avec l’option delaycompress dans la conf logrotate, access.log.1 reste non compressé pendant 24h, ce qui permet au script grep de fonctionner sans zgrep. Cron à 03:15 laisse 3h15 de marge après rotation, largement safe.

# /etc/cron.d/matomo-import-bots
SHELL=/bin/bash
PATH=/usr/local/bin:/usr/bin:/bin
15 3 * * * root /usr/local/bin/matomo-import-bots.sh \
              >> /var/log/matomo-import-bots.log 2>&1

6. Les pièges qui font perdre une après-midi

Piège 1 : l’exclusion d’IP globale

Vous testez depuis votre serveur, vous voyez des HTTP 204 sur les requêtes vers matomo.php, mais rien n’arrive dans la base. C’est probablement parce que l’IP de votre serveur est exclue dans Settings > Privacy > Excluded IPs. Solution : utiliser le paramètre cip= avec une IP qui n’est pas exclue (ex : une plage Azure OpenAI), avec token_auth=.

Piège 2 : bots=1 ne déclenche pas le plugin BotTracking

On l’a vu en section 2. bots=1 dit juste à Matomo "ne filtre pas ce hit comme bot générique". recMode=2 est ce qui déclenche réellement le plugin BotTracking et alimente la table matomo_log_bot_request.

Piège 3 : les hits arrivent en SQL mais pas dans l’UI

Matomo agrège les rapports via core:archive. Si vous testez quelques hits manuellement, ils n’apparaîtront dans le rapport "AI Chatbots Overview" qu’après un nouvel archivage. Pour forcer :

cd /var/www/matomo && php console core:invalidate-report-data \
  --sites=1 --dates=2026-04-25 --periods=day
php console core:archive --force-idsites=1

Piège 4 : oublier que les chatbot users sont déjà trackés en temps réel

Si vous avez configuré bot-tracker.php ET que votre filtre d’import des logs inclut ChatGPT-User, vous comptez deux fois ces visites. Premier réflexe quand un chiffre semble étrange : vérifier que le filtre regex de l’import ne contient aucun des 6 UA chatbot users.

Piège 5 : les listes de UA évoluent vite

Anthropic a sorti Claude-SearchBot en 2025, Meta a ajouté Meta-ExternalFetcher, DeepSeek est monté en puissance, FirecrawlAgent et ExaBot sont arrivés. Garder un œil sur le dépôt communautaire ai-robots-txt/ai.robots.txt et sur les rapports Cloudflare Radar évite de rater les nouveaux entrants.

Résultat : ce qu’on voit sur datacampus.fr

Après déploiement, en regardant une journée classique d’avril 2026 :

  • idsite=1 : 15 visites humaines + 30 hits ChatGPT-User dans la table BotTracking. Le rapport "AI Chatbots Overview" est alimenté en temps réel.
  • idsite=2 : 50 visites bots, 139 hits, dont OAI-SearchBot (66), ClaudeBot (37), Meta-ExternalAgent (36) sur la journée. Custom dimensions filtrables instantanément.

Visibilité complète sur deux populations qui étaient quasi invisibles avant. Côté performance, le tracker serveur ajoute zéro latence perceptible (envoi en shutdown function, après la réponse HTTP au client).

Pour aller plus loin

Une fois que les données remontent, plein d’analyses deviennent possibles : quelles pages sont les plus crawlées par GPTBot vs ClaudeBot ? Quels mots-clés déclenchent le plus de hits chatbot users ? Quel ratio entre exposition entraînement et engagement réel ? Combien de fois votre contenu est-il cité en réponse à une vraie question utilisateur ? Ce sont les nouvelles métriques SEO de l’ère post-Google.

Si vous n’avez pas envie de tout configurer vous-même — héberger Matomo, gérer les mises à jour, le plugin BotTracking, les custom dimensions, l’import des logs — sachez que Datacampus propose Matomo en infogérance complète, avec cette configuration AI tracking préparamétrée. Données hébergées en France, sur notre datacenter du Futuroscope, en immersion cooling.

Hébergement souverain, éco-responsable et infogéré

Serveurs en France, énergie renouvelable, support humain. Découvrez ce que Datacampus peut faire pour vous.

Découvrir nos solutions Nous contacter

Articles sur le même sujet

← Retour au blog