# Dashboard Visite — Spec

**Date :** 2026-04-28  
**Scope :** Tracking des visites de la page publique `/` avec dashboard analytics dans l'interface admin.

---

## Contexte

ContractFlow dispose d'une page publique scrollable (landing page clients) accessible sur `/`, et d'une interface admin privée derrière authentification. L'objectif est de tracker les visites de la page publique et d'afficher les statistiques dans un dashboard admin dédié `/visits`.

---

## Données collectées

### Table `page_visits`

| Colonne        | Type             | Description                                      |
|----------------|------------------|--------------------------------------------------|
| `id`           | bigint (PK)      |                                                  |
| `visited_at`   | timestamp        | Horodatage de la visite                          |
| `ip_hash`      | string(64)       | SHA-256 de l'IP — jamais l'IP brute              |
| `browser`      | string           | Chrome, Firefox, Safari, Edge…                   |
| `device_type`  | string           | `desktop` / `mobile` / `tablet`                  |
| `os`           | string           | Windows, macOS, iOS, Android, Linux…             |
| `country`      | string(2)\|null  | Code ISO pays (`FR`, `US`…)                      |
| `country_name` | string\|null     | Nom complet (`France`, `États-Unis`…)            |
| `referrer`     | string\|null     | URL de provenance                                |
| `language`     | string\|null     | Header Accept-Language (`fr-FR`, `en-US`…)       |
| `is_bot`       | boolean          | `true` si robot/crawler détecté                  |
| `bot_name`     | string\|null     | Nom du bot (`Googlebot`, `Bingbot`, `curl`…)     |
| `timestamps`   | created_at only  |                                                  |

### Règles de collecte

- **1 enregistrement par session/jour** par `ip_hash` — anti-duplication via cache Laravel (TTL 24h par IP hash).
- **Aucun cookie** posé côté client.
- **Bots trackés** (pas ignorés) dans la colonne `is_bot` / `bot_name` pour avoir le ratio bots/humains.
- **RGPD :** aucune donnée personnelle stockée (IP hashée, pas de nom, pas d'email).

---

## Packages

| Package | Rôle |
|---|---|
| `jenssegers/agent` | Parsing User-Agent → browser, device, OS, robot |
| `stevebauman/location` | Géolocalisation IP → pays via MaxMind GeoLite2 (local, offline) |

### Setup MaxMind GeoLite2

1. Créer un compte gratuit sur [maxmind.com](https://www.maxmind.com)
2. Télécharger `GeoLite2-City.mmdb`
3. Placer dans `storage/app/geoip/GeoLite2-City.mmdb`
4. Configurer le driver dans `config/location.php`

---

## Architecture

### Middleware `TrackPageVisit`

- **Enregistré sur :** `GET /` uniquement
- **Logique :**
  1. Parser le User-Agent avec `jenssegers/agent`
  2. Détecter si bot → remplir `is_bot` et `bot_name`
  3. Hasher l'IP : `hash('sha256', $request->ip())`
  4. Vérifier le cache : si `visits.{ip_hash}.{today}` existe → skip
  5. Géolocaliser l'IP avec `stevebauman/location`
  6. Créer un enregistrement `PageVisit`
  7. Mettre en cache la clé (TTL 24h)

### Model `PageVisit`

- `$fillable` : toutes les colonnes
- Scope `human()` : `where('is_bot', false)`
- Scope `bot()` : `where('is_bot', true)`
- Scope `period(int $days)` : filtre sur les N derniers jours

### Controller `VisitDashboardController`

Invokable, derrière `auth`. Calcule :

**Humains :**
- Visites aujourd'hui, cette semaine, ce mois
- Visiteurs uniques (count distinct `ip_hash`, 30 derniers jours)
- Visites par jour sur 30 jours (pour Chart.js)
- Répartition navigateurs, appareils, OS, pays (top 10)
- Top 10 référents

**Bots :**
- Total bots (30 jours)
- Ratio bots vs humains
- Activité bots par jour (30 jours)
- Top bots par nom

---

## Interface admin

### Route

```
GET /visits → VisitDashboardController@__invoke → visits.index
```
Middleware : `auth`, `verified`.

### Vue `visits/index.blade.php`

Deux onglets Alpine.js (`x-data="{ tab: 'humans' }"`) :

**Onglet "Visiteurs"**
- 4 KPI cards : aujourd'hui / semaine / mois / uniques
- Graphique ligne : visites/jour sur 30 jours
- 3 graphiques donut : Navigateurs / Appareils / OS
- Barres horizontales : Top 10 pays
- Tableau : Top référents

**Onglet "Bots"**
- 2 KPI cards : total bots / ratio bots %
- Graphique ligne : activité bots/jour sur 30 jours
- Tableau : top bots (nom, count, dernier passage)

**Librairie graphiques :** Chart.js via CDN (pas de changement au pipeline Vite).

---

## Navigation

Ajout dans la sidebar (`app.blade.php`) d'un lien "Statistiques" avec icône graphe, entre "Tableau de bord" et "Devis". Actif sur `request()->routeIs('visits.*')`.

---

## Fichiers impactés

| Fichier | Action |
|---|---|
| `database/migrations/..._create_page_visits_table.php` | Créer |
| `app/Models/PageVisit.php` | Créer |
| `app/Http/Middleware/TrackPageVisit.php` | Créer |
| `app/Http/Controllers/VisitDashboardController.php` | Créer |
| `resources/views/visits/index.blade.php` | Créer |
| `bootstrap/app.php` | Modifier — enregistrement middleware sur `/` |
| `routes/web.php` | Modifier — route `/visits` |
| `resources/views/components/layouts/app.blade.php` | Modifier — lien sidebar |

---

## Ce qui est hors scope

- Heatmaps / scroll depth (nécessite JS + consentement)
- Session recording
- Alertes (ex: spike de trafic)
- Export CSV des données
- Rétention configurable des données
