# CHANGELOG — Module Analytics

## [1.1.0] — 2026-05-13 — Fix GTM stub bypass + auto-migration force_ga4

### Corrigé
- `analytics.js` — `ensureGtag()` : le check `typeof window.gtag === 'function'` était satisfait par le stub GTM sans que le vrai `gtag.js` soit chargé. Remplacé par un check sur la présence physique du script (`[data-nxt-gtag]` marker ou `[src*="gtag/js?id=GA4_ID"]`). Voir [ADR-005](../../../docs/decisions/ADR-005-analytics-force-ga4-auto-migration.md).
- `class-analytics.php` — Mode par défaut changé de `'auto'` à `'force_ga4'` dans `DEFAULTS`.

### Ajouté
- `class-analytics.php` — Migration runtime silencieuse dans `get_options()` : si `mode === 'auto'` ET `ga4_id` non vide → runtime en `force_ga4` sans écriture en DB. Résout les 60+ sites existants sans intervention manuelle.

---

## [1.0.0] — 2026-05-05

### Ajouté — Module initial

#### Service centralisé `window.nxtAnalytics`
- API publique :
  - `nxtAnalytics.track(event, payload)` — push event (préfixe automatique)
  - `nxtAnalytics.isReady()` — vrai si consentement OK et services prêts
  - `nxtAnalytics.isModuleTracked(slug)` — utilisé par les autres modules pour conditionner leur tracking
- Push **dataLayer** (GTM-first) **+** push `gtag('event')` si gtag direct détecté.
- Auto-injection de `page_url` et `page_title` dans chaque payload.

#### Modes d'injection
- `auto` (par défaut) — n'injecte rien, push dataLayer + gtag si dispo.
- `force_ga4` — injecte dynamiquement `gtag.js` avec l'ID GA4 configuré (utile sur sites sans GTM).
- `disabled` — aucun script servi côté front, `window.nxtAnalytics` indéfini.

#### Auto-détection CMP RGPD
Détection par présence du global, file d'attente jusqu'au consentement :
- **Cookiebot** — via `window.Cookiebot.consent.statistics` + listeners `CookiebotOnAccept` / `CookiebotOnDecline`.
- **CookieYes** — via `window.getCkyConsent().categories.analytics` + events `cookieyes_consent_update` / `cookieyes_consent_change`.
- **Axeptio** — via cookie `axeptio_authorized_vendors` (recherche `google_analytics` / `google_tag`) + callback queue `_axcb` (events `cookies:complete`, `consent:saved`).
- Filet de sécurité : poll automatique à 1s / 3s / 8s pour rattraper toute CMP loadée tardivement.

État retourné par `detectCmpState()` :
- `no_cmp` → push direct (pas de CMP donc pas de check applicable)
- `granted` → push direct
- `pending` → ajout en queue, flush quand le consentement est donné
- `denied` → events ignorés (queue vidée)

#### Page admin (strict admin)
- Apparence → Nexxis Toolkit → carte « Analytics » → Réglages.
- Verrou `nxt_user_is_module_admin()` (helper toolkit ajouté à la racine) — refuse les Editors même s'ils ont `manage_options` par accident.
- Sections : Mode d'injection, ID GA4, Convention naming (préfixe d'events), Modules à tracker (cases à cocher), Métadonnées additionnelles (paires `key=value`), Mode debug.

#### Convention naming events
- Préfixe configurable, défaut `nxt_` (idempotent : `track('nxt_foo')` n'ajoute pas un second préfixe).
- Sanitization serveur : `[a-z0-9_]` uniquement, force le `_` final.

#### Paramètres standardisés (toujours dans le payload)
- `cta_type`, `cta_label`, `cta_position`, `cta_module`
- `page_url`, `page_title` (auto-injectés)
- Métadonnées additionnelles (textarea admin) — fusionnées dans **chaque** event

#### Mode debug
- `console.log('[nxtAnalytics]', event, payload)` à chaque PUSH, QUEUE, SKIP ou FLUSH.
- Aucun impact UX visible.

#### Intégrations livrées en PHASE 1
- **floating-toolbar** v1.4.0 — clics CTA + ouverture toolbar/bottom sheet.

### Sécurité
- ID GA4 validé strictement (regex `^G-[A-Z0-9]{4,}$`) — refus en mode `force_ga4` si vide ou invalide (revient sur `auto`).
- Page admin et `handle_save_options` gardés par `nxt_user_is_module_admin()` (strict admin).
- Aucune donnée PII serveur — tout le tracking se fait côté navigateur de l'utilisateur.

### À venir (PHASE 2)
- Intégration `nav-mobile` — ouverture/fermeture du drawer mobile.
- Tests de couverture CMP réelle sur `wp.mon-site-nexxis.fr` avec et sans Cookiebot.
- Helper `track('cta_click', {...})` documenté dans `docs/DEVELOPER.md`.
