Fournisseurs : capacités et limites vérifiées
Matrice établie par essai sur les versions épinglées, pas d'après la documentation commerciale. Date des vérifications : 25/10/2026.
| Rybbit | Umami | Matomo | |
|---|---|---|---|
| Version essayée | ghcr.io/rybbit-io/rybbit-backend:latest | v2.19.0 | 5.3.2 |
| Navigateur | oui | oui | oui |
| Serveur (HTTP) | oui | oui | oui |
| Mobile natif | non | oui | oui |
| Vues de page | oui | oui | oui |
| Événements personnalisés | oui | oui | oui |
identify | oui | non | oui (uid) |
| Enregistrement de session | oui | non | extension payante |
| Entonnoirs | oui | oui | plugin |
| Authentification d'ingestion | clé d'API (serveur) | aucune | jeton (serveur) |
Contrats d'ingestion
| Rybbit | Umami | Matomo | |
|---|---|---|---|
| Endpoint | POST /api/track | POST /api/send | POST /matomo.php |
| Corps | JSON | JSON | formulaire URL-encodé |
| En-têtes | Authorization: Bearer, Content-Type | Content-Type, User-Agent | Content-Type |
| Champs d'événement | site_id, type, event_name, pathname, properties | website, name, data, url | idsite, rec=1, apiv=1, e_c, e_a |
Pièges constatés à l'essai
Détection de robots : les deux répondent « succès » en jetant l'événement
C'est le piège principal du POC. Umami et Rybbit filtrent les robots d'après le User-Agent,
et répondent tout de même en succès.
- Umami : sans User-Agent de navigateur crédible, la requête renvoie
200et rien n'est stocké. Un User-Agent contenant+http— convention classique des robots — suffit à déclencher le filtre. Constaté : aucune ligne danswebsite_event. - Rybbit : la requête renvoie
{"success":true}et l'événement part dans la tablebot_eventsau lieu deevents. Le journal du backend l'indique (botDetectionTotals: {ua_pattern: 1}). Constaté :events = 0,bot_events = 2.
Le même filtre frappe un navigateur réel piloté : le User-Agent par défaut de Chromium en mode
sans interface contient HeadlessChrome, et Umami répond alors 200 avec le corps littéral
{"beep":"boop"} sans rien stocker (constaté le 26/10/2026). Un test de bout en bout qui ne
remplace pas ce User-Agent mesure le filtre antirobot, pas la chaîne d'envoi de l'application.
smoke-app.ts remplace donc HeadlessChrome par Chrome dans le contexte Playwright. Les visiteurs
réels ne sont pas concernés.
Conséquence pour le code : les deux adaptateurs exigent un userAgent côté serveur et refusent
de s'initialiser sans lui. Vérifier un code HTTP ne prouve rien ; c'est pourquoi le test de fumée
interroge les données.
Matomo
core:installn'existe pas en Matomo 5 : l'installation passe par l'installeur web. Le scriptprovision-matomo.mjsdéroule le formulaire étape par étape.- Détecter l'installation par la présence d'un bouton de connexion donne un faux positif : l'installeur en affiche un. La détection porte sur le titre de la page.
e_vn'accepte qu'une valeur numérique ; les autres propriétés passent en dimension.- Un jeton d'API s'obtient sans jeton préalable via
UsersManager.createAppSpecificTokenAuth, authentifié par mot de passe. Live.getLastVisitsDetailslit les journaux bruts : la vérification n'attend pas l'archivage, qui est différé.
Umami
/api/sendn'exige aucune authentification : l'endpoint doit être protégé par le proxy (limitation de débit), sinon n'importe qui peut injecter des événements.- L'API de lecture exige un jeton d'administration (
/api/auth/login). - Les noms d'événements se lisent par
metrics?type=event; les valeurs de propriétés parevent-data/values. Vérifier le seul nom ne prouve pas que la charge utile est arrivée. - Pas d'
identify: les sessions sont dérivées d'une empreinte serveur.
Rybbit
propertiesest une chaîne JSON de 2048 caractères maximum, pas un objet. L'adaptateur sérialise et retire les clés les plus longues jusqu'à tenir dans la limite.- Seuls les chaînes et les nombres sont acceptés comme valeurs.
event_nameest limité à 256 caractères.- L'API d'administration passe par better-auth : cookie de session et en-tête
Origin, sans quoi elle répondMISSING_OR_NULL_ORIGIN. - Dépendances : ClickHouse, PostgreSQL et Redis. C'est le fournisseur le plus lourd.
- La création de site est
POST /api/organizations/{organizationId}/sites— chemin absent de la documentation publique, trouvé dansopenapi.json. GET /api/sites/{id}/events/countrenvoie un tableau de tranches horaires ([{ time, pageview_count, custom_event_count, event_count, … }]), pas un total. Liredatacomme un nombre donne zéro en permanence, sans erreur. Les vues de page se comptent parpageview_count, pas parevent_count.
Limite de conception connue
Les files d'attente sont indexées par nom de fournisseur : une seule instance par type de fournisseur est gérée. Deux instances Matomo simultanées se télescoperaient. Ce n'est pas un besoin identifié ; le lever demanderait une clé composite.
Ce qui n'est pas couvert
screen(): refusé par les trois adaptateurs, faute de SDK natif dans ce POC.identify(): implémenté dans l'interface pour la portabilité, mais refusé par configuration dans ce dépôt (ADR 006).- Enregistrement de session : jamais activé, quelle que soit la capacité du fournisseur.