4.5.3
August 10th, 2026
What's changed
- Translated the Upgrading to 4.5 section of
UPGRADE.mdfrom French to English, consistent with the rest of the document. - Fixed
support.githubURL incomposer.json— now points to the repository instead of the organisation.
4.5.2
August 9th, 2026
Maintenance
- Régénération du
package-lock.json— suppression d'une référence extraneous (../ccmanoir/vendor/statamic/cms/resources/dist-package) présente depuis le développement initial. 3 packages fantômes et leurs dépendances transitives retirés (151 lignes).
4.5.1
August 9th, 2026
- N/A Changelog not available.
4.5.0
August 8th, 2026
Breaking change (discontinuité de données)
La bibliothèque de détection d'appareil passe de jenssegers/agent (abandonnée, ne reconnaît plus les mobiles récents depuis 2020) à matomo/device-detector 6.5.1 (activement maintenue par Matomo).
Ce qui ne change pas
- Les valeurs de
device_type(tablet/mobile/desktop) sont strictement identiques. - Aucun changement de configuration, de commande ou de schéma de base de données.
Ce qui peut différer
Les libellés browser et platform peuvent être formulés différemment par la nouvelle bibliothèque autour de la date de mise à jour. Les widgets Browser usage et Platforms / OS peuvent afficher temporairement des entrées séparées pour un même navigateur/OS réel. C'est un changement assumé — voir UPGRADE.md pour les détails.
Changements internes
- Constructeur de
TrackPageVisitdésormais injectable (?DeviceDetector $deviceDetector) - Tests : réflexion supprimée, injection directe via le constructeur
- 3 paquets supprimés :
jenssegers/agent,mobiledetect/mobiledetectlib,jaybizzle/crawler-detect
4.4.8
August 7th, 2026
Correctifs audit P4
- Rate limiter ip-api atomique : remplacement du pattern non-atomique
get → test → putparCache::lock()->block()danslookupViaIpApi()— même mécanisme quetrackLookup().LockTimeoutExceptionremonte volontairement (protège un service tiers). - Permissions dossier MaxMind :
0775hardcodé →config('statamic-analytics.cache.file.permissions.directory', 0755), cohérent avec le reste de la configuration. - Throttle route consentement :
throttle:10,1ajouté surPOST /statamic-analytics/consent. - Export CSV :
->get()remplacé par->cursor()pour éviter le chargement de toute la période en mémoire. - Confirmation RGPD avant export :
window.confirm()affiché avant le téléchargement CSV (cléexport_gdpr_warningajoutée en/fr).
4.4.7
August 7th, 2026
Rebuild des assets compilés
Les fichiers dans resources/dist/ n'avaient pas été recompilés depuis le commit 6cdf6bd (v3.0.x). Le bundle JS ne reflétait pas le v-if=\"config.canManage\" introduit en v4.4.0 sur les boutons Export CSV et Reset geo stats.
Ce qui change
- Bundle JS :
statamic-analytics-HATjrHgH.js→statamic-analytics-C0DH1Uv5.js config.canManageprésent × 2 dans le nouveau bundle (confirmé par grep)- Manifest
resources/dist/build/manifest.jsonmis à jour
Ce qui ne change pas
- CSS (
statamic-analytics--r3RbQkV.css) — hash stable, contenu identique - Consent banner (
consent-banner-CJh1zk-q.js) — hash stable, contenu identique
Aucun changement de code source.
4.4.6
August 7th, 2026
Documentation
README.md
- Section «Configuration notes» (ex «Notes de configuration») — traduite en anglais avec la formulation juridique
ip_retention_daysdéjà normalisée en v4.4.3 (not recommended, and unlimited retention may be difficult to justify…). - Bloc Important
analytics:update-geoip— traduit (était resté en français). - Message de log safety net — traduit (
échec du dispatch…→queue dispatch failed, falling back to synchronous recording). - Diagramme d'architecture — ajout des deux commandes planifiées manquantes :
analytics:purge-raw-events(v4.0) etanalytics:purge-failed-jobs(v4.2), absentes du schéma malgré leur ancienneté.
UPGRADE.md
- § Upgrading to 3.0 — traduit intégralement (était 100 % en français).
- § Upgrading to 4.0 — traduit intégralement (était 100 % en français).
Aucun changement de code.
4.4.5
August 7th, 2026
Correctif cosmétique
Problème
Les permissions analytics.view et analytics.manage apparaissaient sous la rubrique «Divers» (groupe par défaut Statamic) dans l'éditeur de rôles CP, sans identification de leur origine.
Correctif
Remplacement des deux Permission::register() individuels avec ->group('analytics') par un bloc Permission::group() déclaratif :
#676E95;">// AvantPermission#89DDFF;">::#82AAFF;">register#89DDFF;">(#89DDFF;">'analytics.view#89DDFF;">'#89DDFF;">, fn #89DDFF;">($p#89DDFF;">) #89DDFF;">=> #89DDFF;">$p #89DDFF;">->#82AAFF;">label#89DDFF;">(#89DDFF;">'View analytics dashboard#89DDFF;">'#89DDFF;">) #89DDFF;">->#82AAFF;">group#89DDFF;">(#89DDFF;">'analytics#89DDFF;">'#89DDFF;">)#89DDFF;">); #676E95;">// AprèsPermission#89DDFF;">::#82AAFF;">group#89DDFF;">(#89DDFF;">'statamic-analytics#89DDFF;">'#89DDFF;">, #82AAFF;">__#89DDFF;">(#89DDFF;">'statamic-analytics::messages.permission_group#89DDFF;">'#89DDFF;">), function #89DDFF;">() #89DDFF;">{ Permission#89DDFF;">::#82AAFF;">register#89DDFF;">(#89DDFF;">'analytics.view#89DDFF;">'#89DDFF;">, fn #89DDFF;">($p#89DDFF;">) #89DDFF;">=> #89DDFF;">$p#89DDFF;">->#82AAFF;">label#89DDFF;">(#89DDFF;">'View analytics dashboard#89DDFF;">'#89DDFF;">)); Permission#89DDFF;">::#82AAFF;">register#89DDFF;">(#89DDFF;">'analytics.manage#89DDFF;">'#89DDFF;">, fn #89DDFF;">($p#89DDFF;">) #89DDFF;">=> #89DDFF;">$p#89DDFF;">->#82AAFF;">label#89DDFF;">(#89DDFF;">'Export and manage analytics data#89DDFF;">'#89DDFF;">));#89DDFF;">});
Les permissions apparaissent désormais sous «Privacy Analytics» dans l'éditeur de rôles.
Notes techniques
- Signature vérifiée contre le code source de
statamic/cmsinstallé :Permission::group(string $name, string $label, callable $permissions)— aucun écart avec la signature documentée. - Label traduit via
__('statamic-analytics::messages.permission_group'), cohérent avec le reste de l'addon. Clé ajoutée danslang/en/etlang/fr/('Privacy Analytics', nom propre identique dans les deux langues). - Aucune modification de la logique d'accès (routes, widget, middleware).
4.4.4
August 7th, 2026
Correctif de sécurité — Finding P2 de l'audit v4.4.3
Problème
Le widget CP AnalyticsOverviewWidget était affiché à tout utilisateur CP quelle que soit sa permission analytics, révélant silencieusement l'existence de la fonctionnalité à des utilisateurs non autorisés.
Correctif — défense en profondeur (deux niveaux)
1. Garde explicite dans html() — protection de référence
#89DDFF;">if #89DDFF;">(!#82AAFF;">auth#89DDFF;">()->#82AAFF;">user#89DDFF;">()?->#82AAFF;">can#89DDFF;">(#89DDFF;">'analytics.view#89DDFF;">'#89DDFF;">)) #89DDFF;">{ #89DDFF;">return #89DDFF;">''#89DDFF;">;#89DDFF;">}
Retourne une chaîne vide plutôt qu'un message d'erreur (principe de moindre privilège — l'absence silencieuse ne révèle pas l'existence de la fonctionnalité).
2. Clé can dans l'injection automatique — mécanisme natif Statamic
#89DDFF;">[#89DDFF;">'type#89DDFF;">' #89DDFF;">=> #89DDFF;">'analytics_overview#89DDFF;">'#89DDFF;">, #89DDFF;">'width#89DDFF;">' #89DDFF;">=> 50#89DDFF;">, #89DDFF;">'can#89DDFF;">' #89DDFF;">=> #89DDFF;">[#89DDFF;">'analytics.view#89DDFF;">'#89DDFF;">]]
DashboardController::getDisplayableWidgets() filtre les widgets sur can/permissions avant même d'appeler html(). Confirmé sur le code source de la version Statamic installée.
Note sur l'investigation préalable
Avant implémentation : lecture du code source de Statamic\Widgets\Widget (classe de base — aucun mécanisme d'autorisation natif) et de DashboardController::getDisplayableWidgets() (filtre can/permissions présent). Les deux niveaux de protection sont complémentaires.
Tests
3 nouveaux tests dans AnalyticsOverviewWidgetTest (81 total) :
test_widget_absent_sans_permission_analytics_viewtest_widget_visible_avec_permission_analytics_viewtest_super_admin_voit_le_widget_sans_permission_explicite
4.4.3
August 7th, 2026
Lot P3 de l'audit de sécurité/qualité
Corrections et améliorations
Protection CSV contre l'injection de formule
AnalyticsDashboardController::export() sanitise désormais chaque champ avant l'écriture CSV : toute valeur commençant par =, +, -, @, tabulation ou retour chariot est préfixée d'une apostrophe. Protection uniforme sur tous les champs (pas sélective).
Option --days pour analytics:process
Permet de rattraper des agrégats manqués si le scheduler a été interrompu plusieurs jours :
php artisan analytics:process --days=7
Le comportement par défaut (--days=2, aujourd'hui + hier) est inchangé — le scheduling automatique n'est pas affecté.
Formulations de documentation nuancées
README.md et UPGRADE.md : la mention null pour ip_retention_days est désormais décrite comme non recommandée, difficile à justifier selon les exigences applicables, sans conclusion juridique catégorique.
Tests
2 nouveaux tests (78 total) :
test_export_neutralise_les_valeurs_de_type_formuletest_option_days_recalcule_plusieurs_jours_en_arriere
4.4.2
August 7th, 2026
v4.4.2
Correctif
- Race condition dans
GeolocationService::trackLookup()(audit v4.3.0, point 18, P2)- Le bloc get→mutate→put sur la clé de statistiques journalières de géolocalisation est désormais protégé par
Cache::lock()(TTL verrou : 5 s, attente max : 2 s). - En cas de contention (verrou non acquis dans le délai), la mise à jour des stats est ignorée en best-effort et journalisée en
info— le géo-lookup lui-même n'est pas affecté. - Clé de verrou :
statamic-analytics:geo-stats-lock:Y-m-d(granularité journalière, cohérente avec la clé de stats).
- Le bloc get→mutate→put sur la clé de statistiques journalières de géolocalisation est désormais protégé par
Tests
- Ajout de deux tests dans
GeolocationServiceTest(section 9) :- Non-régression : deux lookups avec des IP distinctes →
total_lookups=2,unique_ipscontient bien 2 entrées. - Dégradation propre : verrou pré-acquis manuellement →
lookup()retourne le résultat géo attendu sans exception, les statistiques ne sont pas mises à jour.
- Non-régression : deux lookups avec des IP distinctes →
4.4.1
August 7th, 2026
v4.4.1
Tests
- Ajout de
CpPermissionsTest: 6 tests d'intégration HTTP vérifiant le middlewarecan:sur les routes CP introduites en v4.4.0.- Aucune permission → redirect (302)
analytics.view→ 200 surindex,data,geo-stats,realtime; redirect surexportetreset-statsanalytics.manage→ 200 surexportetreset-stats; redirect surindexetdata- Super-admin → 200 sur toutes les routes
- Non authentifié → redirect vers login
Aucun changement de comportement applicatif. Couverture uniquement.
4.4.0
August 7th, 2026
Permissions CP granulaires
Deux permissions Statamic permettent de contrôler l'accès au tableau de bord analytics pour les utilisateurs CP non-super-admin.
| Permission | Slug | Accès |
|---|---|---|
| View analytics dashboard | analytics.view |
Dashboard, données agrégées, géolocalisation, temps réel |
| Export and manage analytics data | analytics.manage |
Export CSV, réinitialisation des stats de géolocalisation |
Les super administrateurs contournent automatiquement ces permissions.
⚠️ Breaking change pour les utilisateurs non-super-admin
Les utilisateurs CP non-super-admin qui avaient accès aux routes analytics devront se voir attribuer explicitement analytics.view et/ou analytics.manage après la mise à jour. Voir UPGRADE.md pour la procédure.
Changements
ServiceProvider: enregistrement des deux permissions, lien de nav conditionné paranalytics.viewroutes/cp.php: deux sous-groupes middlewarecan:analytics.view/can:analytics.manageDashboard.vue: boutons Export CSV et Reset stats masqués sianalytics.manageabsent (protection réelle côté serveur)
4.3.1
August 6th, 2026
Full Changelog: https://github.com/oliweb-ch/statamic-privacy-analytics/compare/v4.3.0...v4.3.1
4.3.0
August 6th, 2026
Full Changelog: https://github.com/oliweb-ch/statamic-privacy-analytics/compare/v4.2.0...v4.3.0
4.2.0
August 6th, 2026
Full Changelog: https://github.com/oliweb-ch/statamic-privacy-analytics/compare/v4.1.0...v4.2.0
4.1.0
August 6th, 2026
What's new
Opt-in asynchronous tracking via Laravel queues, for high-traffic sites where synchronous DB writes or geolocation resolution become a measured bottleneck.
The default behaviour (synchronous, no worker needed) is strictly unchanged.
Changes
PageViewRecorderservice — geolocation lookup + DB INSERT extracted into a reusable classTrackPageViewJob—ShouldQueuejob with 3 attempts and 10/30/60 s backoffTrackPageVisitmiddleware — conditionally dispatches the job or writes synchronously based onqueue_connection- Config — two new optional keys:
ANALYTICS_QUEUE_CONNECTION/ANALYTICS_QUEUE_NAME - Tests — queue dispatch / no-dispatch assertions
- README — "Asynchronous tracking (opt-in)" section
Upgrade
No migration required. This is a purely additive change.
To enable async tracking, add to .env:
ANALYTICS_QUEUE_CONNECTION=redisANALYTICS_QUEUE_NAME=analytics
Then run a queue worker:
php artisan queue:work --queue=analytics
4.0.0
August 6th, 2026
Breaking changes
Purge définitive des événements bruts (nouveau)
analytics:purge-raw-events s'exécute quotidiennement et supprime définitivement les lignes de statamic_analytics_page_views de plus de 180 jours (configurable via ANALYTICS_RAW_RETENTION_DAYS). Contrairement à analytics:anonymize-ips qui anonymise sans supprimer, cette commande supprime les lignes.
Avant de mettre à jour sur une installation existante avec des données anciennes :
php artisan analytics:purge-raw-events --dry-run
Voir UPGRADE.md pour les options de configuration et la liste détaillée de ce qui survit vs disparaît.
Nouveautés
Agrégat _overview quotidien
analytics:process écrit désormais une ligne dimension='_overview' / dimension_value='_all' dans les agrégats pour chaque journée, préservant indéfiniment : visites totales, visiteurs uniques, pages vues uniques, visiteurs récurrents.
analytics:purge-raw-events
Nouvelle commande avec --dry-run, garde défensive sur la valeur de config, et suppression par chunks (chunkById). Planifiée quotidiennement avec withoutOverlapping().
Configuration raw_retention_days
#89DDFF;">'privacy#89DDFF;">' #89DDFF;">=> #89DDFF;">[ #89DDFF;">'ip_retention_days#89DDFF;">' #89DDFF;">=> #82AAFF;">env#89DDFF;">(#89DDFF;">'ANALYTICS_IP_RETENTION_DAYS#89DDFF;">'#89DDFF;">, 90#89DDFF;">), #89DDFF;">'raw_retention_days#89DDFF;">' #89DDFF;">=> #82AAFF;">env#89DDFF;">(#89DDFF;">'ANALYTICS_RAW_RETENTION_DAYS#89DDFF;">'#89DDFF;">, 180#89DDFF;">), #676E95;">// nouveau#89DDFF;">],
Corrections & nettoyages
- ip-api :
file_get_contentsremplacé parHttp::timeout(2)->connectTimeout(1)— timeout explicite,ConnectionExceptioncatchée séparément,$data === nullgéré proprement. - ProcessAnalytics :
whereDate('visited_at')→where >= startOfDay / < addDay()->startOfDay()pour exploiter l'index survisited_at. - Session
visited_pages: bornée à 20 entrées maximum (array_slice(-20)). AnalyticsSettingsControllersupprimé : aucune route ni vue, résidu du fork d'origine.
3.2.2
August 6th, 2026
Fix
tests/TestCase.php: import corrigé —Mohammedshuaau\EnhancedAnalytics\ServiceProvider→Oliweb\StatamicAnalytics\ServiceProvider(résidu du fork, les tests ne pouvaient pas bootstrapper)tests/ExampleTest.php: supprimé — scaffolding Laravel sans valeur (assertTrue(true))
Aucun changement fonctionnel.
3.2.1
August 6th, 2026
Fix
Correction du namespace résiduel du fork d'origine dans les fichiers de tests :
tests/ExampleTest.phptests/TestCase.phptests/TrackPageVisitSessionTest.php
Mohammedshuaau\EnhancedAnalytics\Tests → Oliweb\StatamicAnalytics\Tests
Aucun changement fonctionnel.
3.2.0
August 6th, 2026
Nouveautés
Anonymisation user_id à l'expiration de la rétention
Le champ user_id est désormais mis à NULL en même temps que ip_address et user_agent lors de l'exécution de analytics:anonymize-ips. Même seuil (ip_retention_days), aucune clé de config supplémentaire. track_authenticated_users reste actif par défaut, mais l'association utilisateur est automatiquement rompue à l'expiration — ce n'est pas un lien permanent.
Sanitisation du referrer
Le header Referer est désormais stocké sans sa query string (scheme://host/path uniquement), comme c'est déjà le cas pour page_url. Les URLs malformées ou sans host sont stockées null.
Hash SHA-256 dans les stats de géolocalisation
unique_ips dans les clés de cache de stats ne stocke plus les IPs en clair mais leur hash sha256. La déduplication reste exacte ; aucune UI ne consommait cette donnée.
resetStats() honnête en lieu et place du clearCache() no-op
GeolocationService::clearCache()était un no-op depuis v3.0.1 — renomméresetStats()avec une implémentation réelle qui vide les 32 clés de stats datées.- Route CP :
/clear-cache→/reset-stats(statamic-analytics.reset-stats) - Bouton dashboard : « Clear Geo Cache » → « Reset Statistics » / « Réinitialiser les statistiques »
- Message JSON : précise que les entrées de cache géo par IP expirent naturellement et ne peuvent pas être vidées de force sur tous les drivers.
Fichiers modifiés
src/Commands/AnonymizeIps.php · src/Middleware/TrackPageVisit.php · src/Services/GeolocationService.php · src/Http/Controllers/AnalyticsDashboardController.php · src/Http/Controllers/AnalyticsSettingsController.php · routes/cp.php · resources/js/components/Dashboard.vue · resources/lang/en/messages.php · resources/lang/fr/messages.php · README.md
3.1.3
August 6th, 2026
Correctif P0 — session()->invalidate() dans le middleware de tracking
Problème
Depuis la mise en place du tracking, session()->invalidate() était appelé à la première visite trackée d'un visiteur. Cette méthode vide intégralement la session Laravel — panier, authentification, état de formulaire, toute donnée tierce — pas uniquement les clés propres à l'addon. Tout site hôte utilisant la session pour autre chose que l'analytics était donc exposé à une perte silencieuse de données à la première page vue.
Correctif
Suppression du bloc invalidate() / regenerate() et de la sauvegarde manuelle du consentement qui le compensait. Le middleware pose désormais uniquement ses propres clés de session (analytics_session_started, visitor_id, visited_pages, etc.) sans jamais toucher aux données existantes.
Changements
src/Middleware/TrackPageVisit.php— suppression deinvalidate(),regenerate()et de la restauration deanalytics_consent/analytics_settingstests/TrackPageVisitSessionTest.php— test de non-régressiontest_tracking_does_not_destroy_existing_sessionREADME.md— section Privacy & tracking : garantie explicite de préservation de la session applicative
Mise à jour recommandée
Cette version est un correctif de sécurité fonctionnelle. La mise à jour est recommandée pour tous les sites utilisant la session Laravel (panier, auth, formulaires multi-étapes, etc.).
3.1.2
August 6th, 2026
Correctif
Compatibilité multi-driver dans getHeatmapData()
Le widget heatmap utilisait strftime() (syntaxe SQLite uniquement), ce qui provoquait une erreur silencieuse sur MySQL et MariaDB.
getHeatmapData() détecte désormais le driver actif via DB::getDriverName() et sélectionne les expressions SQL correspondantes :
| Driver | Heure | Jour |
|---|---|---|
| SQLite | strftime('%H', visited_at) |
strftime('%w', visited_at) + 1 |
| MySQL / MariaDB | HOUR(visited_at) |
DAYOFWEEK(visited_at) |
Les deux expressions retournent le même encodage de jour (1=Dim … 7=Sam), le remapping interne vers 0=Lun … 6=Dim reste inchangé.
Requirements mis à jour
SQLite, MySQL et MariaDB sont désormais officiellement supportés.
Ce qui ne change pas
Aucune migration, aucun changement de configuration.
3.1.1
August 5th, 2026
Correctif
Filtre Content-Type dans isTrackableResponse()
Le filtre HTTP 200 introduit en v3.1.0 ne suffisait pas à lui seul : les assets statiques servis en 200 par des addons tiers (fichiers .js, .wasm, etc. — ex. vendor/statamic-cap/*) étaient comptabilisés comme des pages vues.
isTrackableResponse() vérifie désormais en plus que le Content-Type de la réponse commence par text/html. Les réponses JSON, JavaScript, WebAssembly, CSS et autres types non-HTML sont silencieusement ignorées.
Ce qui ne change pas
- Aucune migration, aucun changement de configuration
shouldTrack()et le bloc de tracking : inchangésStrétait déjà importé — aucun ajout d'import
3.1.0
August 5th, 2026
Nouveauté
Middleware après — filtrage par statut HTTP
Le middleware TrackPageVisit est converti en middleware après : $next($request) est désormais appelé en premier, et l'insertion en base n'a lieu que si la réponse retourne exactement HTTP 200.
Avant : toutes les requêtes correspondant aux critères de shouldTrack() étaient enregistrées, y compris celles aboutissant en 404 — scans automatisés testant des chemins WordPress/PHP (wp-admin/install.php, phpmyadmin, etc.), sondes de pénétration, robots d'indexation mal configurés.
Après : seules les pages effectivement servies (200) sont comptabilisées. Les 404 sont silencieusement ignorées, sans liste d'exclusion manuelle à maintenir.
Ce qui ne change pas
shouldTrack()et tous ses filtres (consent, exclude_paths, exclude_ips, exclude_bots, track_authenticated_users) — inchangés, appliqués cumulativement- Le bloc de tracking (session, visitor_id, géolocalisation, insertion DB) — strictement identique
- Aucune migration, aucun changement de configuration
Mise à jour sans action requise
Déployer le code suffit. Aucune publication de config ni migration.
3.0.2
August 5th, 2026
Correctifs
Bug Carbon 3.x — diffIn*() absolu explicite
Carbon 3.x a changé le comportement par défaut de diffIn*() : $absolute vaut désormais false (au lieu de true en 2.x), provoquant des valeurs négatives dans les calculs de durée de session.
AnalyticsDashboardController
getTopPages()— temps moyens par page retournaient des valeurs négativesgetUserFlow()— pages engagées calculées incorrectementcalculateAverageTimeOnSite()— rendu explicite par cohérence$periodLength(diffInDays) — rendu explicite par cohérence
CacheManager
cleanupFiles()— bug silencieux : la conditiondiffInSecondsretournait une valeur négative, donc les fichiers de cache expirés n'étaient jamais supprimés depuis le passage à Carbon 3.x
Dashboard.vue
formatDuration()— filet défensif : une valeur< 0affiche désormais0:00au lieu d'un résultat absurde
Mise à jour des assets
Rebuild Vite inclus.
3.0.1
August 5th, 2026
Correctif — Fuite mémoire dans GeolocationService
Problème
trackLookup() utilisait une clé de cache globale unique avec un TTL glissant de 30 jours. Le tableau unique_ips à l'intérieur croissait indéfiniment tant qu'il y avait du trafic.
Correctif
trackLookup: clé journalièregeolocation_stats_YYYY-MM-DDavec TTL fixe de 32 jours — chaque entrée expire naturellement,unique_ipsest borné à une journée de trafic.getStats(int $days = 30): agrège les N dernières clés journalières au lieu de lire une clé globale. Signature rétrocompatible (valeur par défaut30).clearCache: simplifié — les clés expirent d'elles-mêmes via leur TTL, aucun nettoyage manuel nécessaire.
Aucun changement de comportement pour les appelants existants.
3.0.0
August 5th, 2026
Breaking change — Politique de rétention IP par défaut
Les adresses IP et user-agents des pages vues de plus de 90 jours sont désormais anonymisés (mis à NULL) automatiquement par une commande planifiée quotidienne. Les statistiques de fréquentation (visites, visiteurs uniques) et les données de géolocalisation déjà résolues ne sont pas affectées.
Migration requise
php artisan migrate
Nouveautés
- Nouvelle section
privacy.ip_retention_daysdans la config (défaut : 90 jours, viaANALYTICS_IP_RETENTION_DAYS) - Nouvelle commande
analytics:anonymize-ipsavec option--dry-run - Planification quotidienne automatique via le scheduler Laravel
Options
Ajuster la durée de rétention :
ANALYTICS_IP_RETENTION_DAYS=30
Désactiver l'anonymisation automatique (non recommandé) :
ANALYTICS_IP_RETENTION_DAYS=null
⚠️ Le mot
nulldoit être écrit littéralement. Une valeur vide (ANALYTICS_IP_RETENTION_DAYS=) serait interprétée comme une chaîne vide et provoquerait une anonymisation immédiate de la quasi-totalité des données.
Voir UPGRADE.md pour le guide de migration complet.
2.0.1
November 29th, -0001
- N/A Changelog not available.
2.0.0
August 4th, 2026
⚠ Breaking change
The default geolocation provider has changed from ip-api to maxmind.
If you never set ANALYTICS_GEO_PROVIDER in your .env, your installation was
using ip-api. After upgrading, it will silently switch to maxmind, which
requires a free MaxMind account and credentials.
Migration options — see UPGRADE.md for full details:
- Keep using
ip-api: addANALYTICS_GEO_PROVIDER=ip-apito your.env - Set up MaxMind: add
MAXMIND_ACCOUNT_ID+MAXMIND_LICENSE_KEY, then runphp artisan analytics:update-geoip - Disable geolocation entirely:
ANALYTICS_GEO_PROVIDER=disabled
What's new
analytics:update-geoip command rewritten
- No more system calls —
curlviasystem()/exec()replaced by Laravel'sHttpfacade (Guzzle) - SHA-256 integrity check after download via MaxMind's
?suffix=tar.gz.sha256endpoint - Atomic
.mmdbwrite — staging copy on the same filesystem + POSIXrename(), eliminating any partial-read window for concurrent requests; explicit fallbackcopy()with warning if cross-device - Return value checks on every
copy(),rename(), and fallbackcopy()— cleanFAILUREreturned at each step - Collision-safe temp filenames via
uniqid()instead oftime() PharData::extractTo()wrapped intry/catch \PharException|\Exceptionwith guaranteed cleanup- Checksum URL derived from
$this->url— no more independent string to keep in sync - File permissions read from
config('statamic-analytics.cache.file.permissions.file', 0644) - Network errors caught via
ConnectionExceptionwith clear error messages
Control Panel warning banner
When maxmind is the active provider but credentials are missing, a warning banner
is displayed in the analytics dashboard with a link to the setup procedure and a
mention of the disabled alternative.
Geographic widgets hidden when disabled
When provider = disabled, the Top countries and Top cities widgets are
removed from the dashboard entirely — no empty widget, no placeholder.
Throttled "database missing" log
The Log::warning that fired on every request when the .mmdb file was not found
is now capped to once per hour via Cache::remember.
Bug fixes
rename()cross-device failure: fallback tocopy()+unlink()withwarn()(noterror()) and return value checkcountryChart: guarded withif (countryChartEl.value)on init and&& countryChartinupdateStateto prevent a crash when the canvas element is absent due tov-if
Documentation
UPGRADE.mdadded with full migration guide- README: providers table updated,
.envexample with all three options commented, note on the CP warning banner and widget hiding behaviour
1.3.3
November 29th, -0001
- N/A Changelog not available.
1.3.2
November 29th, -0001
- N/A Changelog not available.
1.3.1
November 29th, -0001
- N/A Changelog not available.
1.3.0
November 29th, -0001
- N/A Changelog not available.
1.2.8
November 29th, -0001
- N/A Changelog not available.
1.2.7
July 29th, 2026
- New 'analytics_overview' widget displaying stats for the last 7 days (today's visits, page views, unique visitors)
- Blade view using native Statamic CP classes (no additional build step required)
- Auto-injected into the CP dashboard if not already manually configured
1.2.6
June 16th, 2026
- N/A Changelog not available.
1.2.5
June 16th, 2026
- N/A Changelog not available.
1.2.4
May 27th, 2026
- N/A Changelog not available.
1.2.3
May 27th, 2026
- N/A Changelog not available.
1.2.2
May 27th, 2026
correction consent banner
1.2.1
May 27th, 2026
correction name consent banner
1.2.0
May 26th, 2026
- N/A Changelog not available.
1.1.0
March 19th, 2026
traduction
1.0.18
June 21st, 2025
- N/A Changelog not available.
1.0.17
June 21st, 2025
- N/A Changelog not available.
1.0.16
June 21st, 2025
- N/A Changelog not available.
1.0.15
June 21st, 2025
- N/A Changelog not available.
1.0.14
June 21st, 2025
- N/A Changelog not available.
1.0.13
June 21st, 2025
- N/A Changelog not available.
1.0.12
March 5th, 2025
- N/A Changelog not available.
1.0.11
March 5th, 2025
- N/A Changelog not available.
1.0.10
March 5th, 2025
- N/A Changelog not available.
1.0.9
January 15th, 2025
- N/A Changelog not available.
1.0.8
January 15th, 2025
- N/A Changelog not available.
1.0.7
January 14th, 2025
- N/A Changelog not available.
1.0.6
January 14th, 2025
- N/A Changelog not available.
1.0.5
January 12th, 2025
- N/A Changelog not available.
1.0.4
January 12th, 2025
- N/A Changelog not available.
1.0.3
January 12th, 2025
- N/A Changelog not available.
1.0.2
January 12th, 2025
- N/A Changelog not available.
1.0.1
January 12th, 2025
- N/A Changelog not available.
1.0.0
May 26th, 2026
- N/A Changelog not available.
1.0.0
March 19th, 2026
1ère release