Analyse SEO + AI search

Audité le 2026-05-24

DRAFT INTERNE : NO GO publication client en l'état (Legal-check 2026-05-24)

Bet224 n'est PAS sur la liste officielle des plateformes agréées ARSJPA [VERIFIED via WebFetch arsjpa.gov.gn/plateformes-agreees/ 2026-05-24]. Les 7 plateformes agréées : Geniusbet, Yellowbet, 1xBet GN, Guinée Games, Pariez GDJ, LONAGUI, Guinée Millions. Verbatim ARSJPA : « Si une plateforme ne figure pas dans cette liste, elle peut être non autorisée. »

Action immédiate recommandée client : retrait du logo ARSJPA présent sur 42 pages du site (cf F-TRUST-01-01) dans les heures qui suivent réception du rapport, indépendamment des autres recos.

5 préalables clients obligatoires avant publication FULL :

  1. Copie agrément ARSJPA OU reconnaissance de non-agrément + plan régularisation
  2. Raison sociale + RCCM Guinée + représentant légal
  3. Organigramme entité GN vs opérateur étranger (trace white-label italien : ADM, RUA, Concessionario hardcodés)
  4. Confirmation conseil juridique sur cadre data GN
  5. Confirmation dispositif central auto-exclusion GN

Détail red team adversarial (7 agents) : voir _red-team-report.md.

Avertissement YMYL : ce rapport analyse le site bet224.gn, opérateur de paris sportifs et de casino en ligne en Guinée. Le secteur est classé YMYL (Your Money Your Life) en raison de l'impact financier et sanitaire potentiel sur les utilisateurs (risque d'addiction, perte d'argent, exposition de mineurs si protection absente). Les recommandations ci-dessous reposent sur (1) des observations sourcées du crawl du site (HTML, screenshots, signaux conversion-signals/axe-core), et (2) les standards internationaux du secteur gambling (UKGC, ANJ, MGA, ADM). La juridiction applicable est la Guinée. Le régulateur identifié est l'ARSJPA (https://arsjpa.gov.gn/, vérifié WebFetch 2026-05-16, statut d'agrément Bet224 vérifié WebFetch 2026-05-24 : NON AGRÉÉE). Le cadre réglementaire guinéen exact pour la publicité gambling, le consentement cookies, et les mentions obligatoires N'A PAS été vérifié en source primaire pour tous les aspects.

Généré : 2026-05-24T10:56:26.777867+00:00 Schémas product-audit v1.0 Sous-agents Deep exploités : 8

Synthèse globale

  • Findings total : 73
  • Par sévérité : critical : 21 · serious : 24 · moderate : 26 · minor : 2
  • Angles couverts : A11Y, CONV, MOBILE, PERF, SEO, TRUST, UI, UX
  • Routes auditées : 4

Angle : A11Y

Persona

Source : site-context.yaml voice_and_tone.persona_primary.

  • sport-home : parieur sportif en Guinée, très majoritairement mobile, intéressé par le football. Sur cette route il arrive pour consulter l'offre du jour (tabs Football / Basketball, top compétitions). Lecteur d'écran : devra naviguer dans une grille de cotes complexe sans landmark utile.
  • sport : même persona, en intent "construction d'un pari" sur une compétition donnée. Le widget Betbuilder (slidebar gauche) est un point d'entrée critique pour les paris combinés ; il est ici inaccessible aux utilisateurs avec contraste réduit (ratio mesuré 1.3:1).
  • casino : persona élargie (joueur casino en ligne, non explicité dans persona_primary mais route présente dans l'audit). Navigation par carrousels de jeux ; les flèches de défilement (8 boutons) ne portent aucun nom accessible, bloquant clavier et lecteur d'écran. Route YMYL sensible : public protégé attendu.
  • promotions : persona en intent "découverte d'un bonus" avant inscription. Les 5 visuels promotionnels (bonus 500 %, cashback, welcome) sont des <img> sans alt, donc invisibles pour lecteur d'écran. Implication YMYL : si le lecteur d'écran ne peut pas lire les conditions associées, le risque d'incitation au jeu non comprise augmente.

Synthèse exécutive

  • Volume mesuré : 39 violations axe-core 4.11.4 cumulées sur 4 routes desktop (14 critical, 7 serious, 18 moderate). Source : axe-results/index.jsonresults[].desktop.violations_by_impact.
  • 6 règles WCAG 2.1 A/AA sont violées sur les 4 routes simultanément (pattern template global) : aria-allowed-attr, image-alt, label, link-name, plus 2 best-practice (page-has-heading-one, region). Le défaut est dans le template header/footer commun.
  • Casino concentre une pathologie spécifique : 8 boutons de carrousel componenteGioco__navigatore__tasto sans aria-label, ni texte visible, ni title. Source : axe-results/casino/desktop.jsonviolations[1].id = "button-name", violations[1].nodes_total = 8. Impact clavier/lecteur d'écran direct sur le parcours de découverte des jeux.
  • Casino bloque aussi le zoom mobile (meta-viewport avec maximum-scale=1) - WCAG 1.4.4 niveau AA non respectée. Source : axe-results/casino/desktop.jsonviolations[8].id = "meta-viewport".
  • 2 défauts de contraste sérieux mesurés (Betbuilder sport 1.3:1 sur 4.5:1 attendu, filtre Sport promotions 2.6:1). Source : axe-results/sport/desktop.jsonviolations[2], axe-results/promotions/desktop.jsonviolations[1].

Findings

F-A11Y-01-01 : Logo header sans alt + lien wrappant sans nom accessible (4 routes)

  • Sévérité : critical
  • Route(s) : sport-home, sport, casino, promotions
  • Source primaire :
  • axe-results/sport-home/desktop.jsonviolations[1].id = "image-alt", violations[1].nodes[0].target = ["a[href=\"/\"] > img"], violations[1].impact = "critical"
  • axe-results/sport-home/desktop.jsonviolations[6].id = "link-name", violations[6].nodes[1].target = ["a[href=\"/\"]"], violations[6].impact = "serious"
  • Pattern identique mesuré sur sport (violations[3].nodes[0] + violations[8].nodes[1]), casino (violations[2].nodes[0] + violations[7].nodes[1]), promotions (violations[2].nodes[0] + violations[4].nodes[1]).
  • HTML observé : <a href="/"><img src="https://www.bet224.gn/external_cms/GUINEA/img/logo-bet-224.png"></a> (sans alt, sans aria-label).
  • Source visuelle : - screenshots/sport-home/desktop.png, screenshots/sport/desktop.png, screenshots/casino/desktop.png, screenshots/promotions/desktop.png : logo "Bet224" rouge en haut à gauche (zone ~x=0-100, y=40-80) confirmé visuellement sur 4 captures.
  • Constat :

Le logo Bet224 du header est un <img> sans attribut alt, enveloppé dans un <a href="/"> sans texte ni aria-label. Le lien est donc totalement muet pour un lecteur d'écran et pour un utilisateur clavier qui s'y arrête en tabulation : impossible de savoir où il mène, ni qu'il s'agit du logo retour-accueil.

  • Impact attendu :

WCAG 1.1.1 (Non-text Content) niveau A et WCAG 2.4.4 (Link Purpose) niveau A violées sur 100 % des routes auditées. Un utilisateur de lecteur d'écran perd le point d'ancrage le plus universel d'un site (logo = retour accueil). En contexte YMYL gambling, c'est aussi un signal de qualité produit dégradé.

  • Root cause :

Template header commun (path external_cms/GUINEA/img/logo-bet-224.png fixé serveur). Un seul fix template corrige les 4 routes.

F-A11Y-01-02 : Drapeau langue fr.png sans alternative textuelle (4 routes)

  • Sévérité : critical
  • Route(s) : sport-home, sport, casino, promotions
  • Source primaire :
  • axe-results/sport-home/desktop.jsonviolations[1].id = "image-alt", violations[1].nodes[1].target = ["img[src$=\"fr.png\"]"], violations[1].impact = "critical"
  • HTML observé : <img src="/images/desktop/fr.png" class="flag-lang"> (4 routes).
  • Source visuelle : - screenshots/sport-home/desktop.png etc. : drapeau France visible en haut à droite, label visible "FR" à proximité (zone ~x=1377, y=80, mesurée dans conversion-signals/sport-home.jsondetailed.ctas[3].bbox).
  • Constat :

Le drapeau "FR" servant de sélecteur de langue est une image sans alt. Un utilisateur de lecteur d'écran n'a aucune indication de la langue courante ni de la fonction du contrôle. Note : un libellé texte "FR" est rendu à côté (cf conversion-signals/sport-home.jsondetailed.ctas[3].text = "FR"), mais comme l'image n'est pas explicitement masquée (role="presentation") ni labellisée, axe le compte malgré tout.

  • Impact attendu :

WCAG 1.1.1 niveau A violée. Une personne aveugle ou malvoyante ne peut pas identifier la langue active ni le sélecteur. Sur un site multilingue, c'est un point d'entrée de friction.

  • Root cause :

Pattern legacy <img class="flag-lang"> sans rôle explicite. Le fix dépend : soit alt="Français" si l'image est porteuse de sens, soit alt="" + role="presentation" si le label "FR" texte adjacent porte l'information.

F-A11Y-01-03 : 8 boutons de carrousel casino sans nom accessible

  • Sévérité : critical
  • Route(s) : casino
  • Source primaire :
  • axe-results/casino/desktop.jsonviolations[1].id = "button-name", violations[1].nodes_total = 8, violations[1].impact = "critical"
  • violations[1].nodes[0].target = ["div[data-target=\"gamesGroup-4\"] > .componenteGioco__navigatore__tasto--indietro.componenteGioco__navigatore__tasto"]
  • violations[1].nodes[1].target = ["div[data-target=\"gamesGroup-4\"] > .componenteGioco__navigatore__tasto--avanti.componenteGioco__navigatore__tasto"]
  • Pattern répété sur gamesGroup-3, gamesGroup-2, gamesGroup-1 (boutons avant + arrière chacun, 8 boutons au total).
  • HTML observé : <button class="componenteGioco__navigatore__tasto componenteGioco__navigatore__tasto--indietro" onclick="scrollConBottone('gamesGroup-4', 'left')"> (et son équivalent --avanti pour la droite).
  • Source visuelle : - screenshots/casino/desktop.png : carrousels "Spribe Games", "Top 10", "Evolution", "Top Providers", "Amigo Gaming" avec flèches gauche/droite visibles en haut à droite de chaque section (zone ~y=145, 250, 360, 470, 580).
  • Constat :

Les boutons de défilement avant/arrière des carrousels de jeux (4 carrousels confirmés visuellement, 8 boutons totaux dans axe) sont des <button> sans texte interne, sans aria-label, sans title. Le contenu visuel (icône CSS supposée) n'est pas exposé à l'API d'accessibilité.

  • Impact attendu :

WCAG 4.1.2 (Name, Role, Value) niveau A violée 8 fois. Pour un utilisateur clavier, la tabulation s'arrête sur un bouton anonyme ("bouton" annoncé sans plus). Le parcours de découverte du catalogue de jeux casino est partiellement bloqué. Contexte YMYL : la friction inacceptable masque aussi les conditions visibles d'engagement (offres in-carrousel).

  • Root cause :

Composant componenteGioco__navigatore interne, probablement réutilisé sur toutes les sections de jeux. Fix unique = patcher le template du composant pour ajouter aria-label au render.

F-A11Y-01-04 : Toggle thème dark/light sans label (4 routes)

  • Sévérité : critical
  • Route(s) : sport-home, sport, casino, promotions
  • Source primaire :
  • axe-results/sport-home/desktop.jsonviolations[2].id = "label", violations[2].nodes[0].target = ["#cg-theme-switch"], violations[2].impact = "critical"
  • Pattern identique mesuré sur sport (violations[4]), casino (violations[3]), promotions (violations[3]).
  • HTML observé : <input type="checkbox" class="custom-control-input" id="cg-theme-switch"> (sans <label for="cg-theme-switch">, sans aria-label).
  • Constat :

L'input checkbox #cg-theme-switch (toggle thème clair/sombre du footer) n'a ni label associé, ni aria-label, ni aria-labelledby. Pour un lecteur d'écran, l'élément est annoncé "case à cocher non cochée" sans contexte sur sa fonction.

  • Impact attendu :

WCAG 4.1.2 (Name, Role, Value) niveau A violée. Concrètement, la friction reste mineure car le toggle est secondaire (préférence d'affichage), mais il s'agit d'un input form non labellisé, donc finding axe critical. La présence d'une icône lune ou soleil suppose un contexte visuel non transmis au lecteur d'écran.

  • Root cause :

Composant footer commun template, probablement issu du framework UI (Bootstrap custom-control). Manque le <label for="cg-theme-switch">Mode sombre</label> ou un aria-label="Activer le mode sombre" direct sur l'input.

F-A11Y-01-13 : Aria-expanded sur élément non interactif (4 routes)

  • Sévérité : critical
  • Route(s) : sport-home, sport, casino, promotions
  • Source primaire :
  • axe-results/sport-home/desktop.jsonviolations[0].id = "aria-allowed-attr", violations[0].nodes[0].target = ["#droplang"], violations[0].impact = "critical"
  • violations[0].nodes[0].failureSummary = "Fix all of the following: ARIA attribute is not allowed: aria-expanded=\"false\""
  • HTML observé : <div class="blocco-header selettore-lingua dropdown" id="droplang" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
  • Pattern identique sur sport (violations[0]), casino (violations[0]), promotions (violations[0]).
  • Constat :

Le sélecteur de langue (#droplang) est un <div> qui porte un attribut aria-expanded="false". Or aria-expanded n'est autorisé que sur des rôles interactifs (button, link, menuitem, tab, treeitem, combobox), pas sur un <div> sans role explicite. L'attribut est ignoré par les technologies d'assistance, créant un état d'accessibilité fantôme.

  • Impact attendu :

WCAG 4.1.2 niveau A violée. Le dropdown langue n'expose pas correctement son état ouvert / fermé aux lecteurs d'écran. Friction limitée (le label "FR" est visible), mais marqueur fort d'un markup ARIA mal maîtrisé.

  • Root cause :

Pattern Bootstrap 4 data-toggle="dropdown" sans wrapping <button>. Fix : soit transformer le <div> en <button type="button"> (ce qui rend aria-expanded valide), soit ajouter role="button" + gestion clavier.

F-A11Y-01-14 : Accordion tablist avec enfants non autorisés (sport)

  • Sévérité : critical
  • Route(s) : sport
  • Source primaire :
  • axe-results/sport/desktop.jsonviolations[1].id = "aria-required-children", violations[1].nodes[0].target = [".contenitore-competizioni-sport[aria-multiselectable=\"true\"][role=\"tablist\"]:nth-child(3)"], violations[1].impact = "critical"
  • violations[1].nodes[0].failureSummary = "Element has children which are not allowed: a[tabindex]"
  • HTML observé : <div id="accordionLaterale" class="contenitore-competizioni-sport" role="tablist" aria-multiselectable="true">
  • Constat :

L'élément #accordionLaterale porte role="tablist" mais contient des <a tabindex="..."> au lieu d'enfants ayant le rôle tab. Le pattern viole la grammaire ARIA et casse la navigation au clavier dans la liste latérale des compétitions sport (parcours principal de la route).

  • Impact attendu :

WCAG 1.3.1 (Info and Relationships) niveau A violée. Lecteur d'écran annonce une "liste d'onglets" qui n'en est pas une : confusion fonctionnelle. Navigation clavier ne suit pas le pattern tablist attendu (flèches gauche / droite).

  • Root cause :

Composant accordion latéral des compétitions sport : un tablist avec des <a> enfants alors que la sémantique correcte serait <div role="tab"> ou simplement un <div role="list"> + <a role="listitem"> (un accordion n'est pas une tablist).

F-A11Y-01-05 : Bouton de fermeture du header sans texte accessible (4 routes)

  • Sévérité : serious
  • Route(s) : sport-home, sport, casino, promotions
  • Source primaire :
  • axe-results/sport-home/desktop.jsonviolations[6].id = "link-name", violations[6].nodes[0].target = ["#nascondiHeader"], violations[6].impact = "serious"
  • HTML observé : <a id="nascondiHeader" data-toggle="collapse" class="accordion-toggle toggle-nascondi flex-container" href="#nascondimenu" role="button" aria-expanded="false" aria-controls="nascondimenu"><i class="fa fa-times"></i></a>
  • Pattern identique sur sport (violations[8].nodes[0]), casino (violations[7].nodes[0]), promotions (violations[4].nodes[0]).
  • Constat :

Le bouton "Masquer le header" (icône fa fa-times Font Awesome via <i>) n'a aucun texte alternatif accessible. Le <a role="button"> n'a ni aria-label, ni texte enfant lisible. Le aria-controls="nascondimenu" est correctement posé mais le nom du contrôle reste manquant.

  • Impact attendu :

WCAG 2.4.4 + WCAG 4.1.2 niveau A violées. Utilisateur clavier ou lecteur d'écran ne peut pas comprendre la fonction du bouton avant de l'activer. Risque de masquage inattendu d'éléments d'interface.

  • Root cause :

Pattern Font Awesome <i class="fa fa-times"></i> sans wrapping textuel. Ajout d'aria-label="Masquer le menu" direct sur le <a>.

F-A11Y-01-06 : Contraste insuffisant sur le widget Betbuilder (sport)

  • Sévérité : serious
  • Route(s) : sport
  • Source primaire :
  • axe-results/sport/desktop.jsonviolations[2].id = "color-contrast", violations[2].nodes[0].target = [".widgetFiltroSide__betBuilder > .margine-giu.bg-colore-1[href-disabled=\"#!\"]"], violations[2].impact = "serious"
  • violations[2].nodes[0].failureSummary = "Element has insufficient color contrast of 1.3 (foreground color: #000000, background color: #212121, font size: 7.5pt (10px), font weight: bold). Expected contrast ratio of 4.5:1"
  • HTML observé : <a href-disabled="#!" role="button" tabindex="0" class="pointer bg-colore-1 bianco margine-giu">Betbuilder</a>
  • Source visuelle : - screenshots/sport/desktop.png : barre latérale gauche au-dessus du sélecteur de sports, libellé "Betbuilder" rendu en noir sur fond gris très sombre. Confirmation visuelle directe : illisible sans agrandissement zoom.
  • Constat :

Le bouton "Betbuilder" du widget de filtres latéral (point d'entrée pari combiné) a un ratio de contraste mesuré de 1.3:1 (noir #000000 sur gris foncé #212121), pour un seuil WCAG 2.1 AA de 4.5:1. La classe CSS bianco (italien pour "blanc") suggère que le texte devrait être blanc, mais la cascade applique du noir : conflit CSS non résolu côté thème.

  • Impact attendu :

WCAG 1.4.3 (Contrast Minimum) niveau AA violée. Utilisateurs malvoyants, ou utilisateurs en lumière forte (mobile en extérieur), ne peuvent pas lire l'étiquette. Le Betbuilder étant un parcours premium gambling, c'est un blocage commercial direct.

  • Root cause :

Classes en collision dans le CSS du composant widgetFiltroSide__betBuilder : la classe bianco (forcer texte blanc) est probablement écrasée par bg-colore-1 ou margine-giu qui réinitialise color. Fix CSS spécifique : revue de la cascade pour le sélecteur.

F-A11Y-01-07 : Contraste insuffisant sur le filtre Sport des promotions

  • Sévérité : serious
  • Route(s) : promotions
  • Source primaire :
  • axe-results/promotions/desktop.jsonviolations[1].id = "color-contrast", violations[1].nodes[0].target = ["a[filtro-dati=\"2\"]"], violations[1].impact = "serious"
  • violations[1].nodes[0].failureSummary = "Element has insufficient color contrast of 2.6 (foreground color: #ffffff, background color: #83ae30, font size: 9.0pt (12px), font weight: normal). Expected contrast ratio of 4.5:1"
  • HTML observé : <a class="bottone-filtro pointer" filtro-dati="2">Sport</a>
  • Source visuelle : - screenshots/promotions/desktop.png : ligne de filtres "TOUTES / Sport / ..." sous le carrousel header, bouton "Sport" en blanc sur vert clair (#83ae30). Lisibilité dégradée confirmée visuellement.
  • Constat :

Le filtre "Sport" des promotions a un ratio mesuré de 2.6:1 (#ffffff sur #83ae30), seuil AA 4.5:1. Le filtre est un point de bascule clé pour les utilisateurs cherchant les bonus sport vs. casino : friction directe sur le funnel d'inscription.

  • Impact attendu :

WCAG 1.4.3 niveau AA violée. Persona primaire (parieur sport mobile) susceptible d'utiliser le téléphone en extérieur : impact accentué. Le filtre étant un état actif (sélection), la dégradation de lisibilité induit aussi un risque de mauvaise compréhension de l'état courant.

  • Root cause :

Couleur d'accent secondaire #83ae30 (vert lime) trop claire pour porter du blanc à 12px. Soit assombrir la couleur de fond (≥ #5e7d1f pour atteindre 4.5:1), soit basculer le texte sur noir sur ce vert. Décision à arbitrer côté design system.

F-A11Y-01-12 : Carrousels casino non accessibles au clavier (scrollable-region-focusable)

  • Sévérité : serious
  • Route(s) : casino
  • Source primaire :
  • axe-results/casino/desktop.jsonviolations[11].id = "scrollable-region-focusable", violations[11].nodes_total = 2, violations[11].impact = "serious"
  • violations[11].nodes[0].target = [".componenteGioco > .rowContainer"]
  • violations[11].nodes[1].target = ["#swiper-wins-6"]
  • Constat :

Deux conteneurs scrollables horizontalement (rowContainer des carrousels de jeux, #swiper-wins-6 du carrousel "Gains récents") ne sont pas focusables au clavier. Un utilisateur naviguant uniquement au clavier ne peut donc pas faire défiler le contenu. Combiné à F-A11Y-01-03 (8 boutons fléchés sans nom accessible), c'est un blocage total du parcours sur les carrousels casino.

  • Impact attendu :

WCAG 2.1.1 (Keyboard) niveau A violée. Utilisateur clavier exclu de toute la zone catalogue jeux de la route casino. Combiné aux boutons fléchés muets, c'est le pire pattern a11y de ce POC.

  • Root cause :

Composant Swiper.js ou équivalent custom drag scroll : il faut soit ajouter tabindex="0" aux conteneurs scrollables, soit un fallback bouton accessible. Le fix de F-A11Y-01-03 (nommer les boutons) ne suffit pas seul : il faut aussi exposer la zone au clavier.

F-A11Y-01-08 : Aucun H1 sur les 4 routes auditées

  • Sévérité : moderate
  • Route(s) : sport-home, sport, casino, promotions
  • Source primaire :
  • axe-results/sport-home/desktop.jsonviolations[7].id = "page-has-heading-one", violations[7].nodes[0].target = ["html"], violations[7].impact = "moderate"
  • Pattern identique sur sport (violations[9]), casino (violations[9]), promotions (violations[5]).
  • Constat :

Aucune des 4 routes auditées ne dispose de balise <h1>. Le diagnostic est issu d'axe (best-practice tag) ; il n'a pas pu être recoupé avec → headings.h1_count car le build de page-signals n'a pas été exécuté sur ce POC (cf Limites).

  • Impact attendu :

Best-practice WCAG (impact moderate axe), pas un critère AA strict, mais double impact a11y + SEO. Sans H1, le lecteur d'écran ne peut pas identifier le sujet principal de la page via le raccourci de navigation par titres. Sur une route YMYL gambling, c'est aussi un signal de qualité éditoriale absent pour les moteurs.

  • Root cause :

Template legacy probablement basé sur <h2> only (anti-pattern observé sur d'autres sites du même éditeur). Toutes les routes héritent d'un layout sans <h1> principal.

F-A11Y-01-09 : Architecture des landmarks <main> cassée (sport-home, sport, casino)

  • Sévérité : moderate
  • Route(s) : sport-home, sport, casino
  • Source primaire :
  • axe-results/sport-home/desktop.jsonviolations[3].id = "landmark-main-is-top-level", violations[3].nodes[0].target = ["#cg_exa-sportAppContainer > main"]
  • axe-results/sport-home/desktop.jsonviolations[4].id = "landmark-no-duplicate-main", violations[4].nodes[0].target = ["body > main"]
  • axe-results/sport-home/desktop.jsonviolations[5].id = "landmark-unique", violations[5].nodes[0].target = ["body > main"]
  • Pattern identique sur sport (3 violations même groupe) et casino (3 violations même groupe : target = ["#idContentMain"], ["#panel"], ["#panel"]).
  • Promotions PAS affectée par ce groupe.
  • Constat :

Trois règles convergentes sur 3 routes signalent que le DOM contient plus d'un élément <main> (body > main ET #cg_exa-sportAppContainer > main ou #idContentMain ET #panel). Cela viole le principe HTML "un seul <main> par document" et casse la navigation par landmarks. Les deux <main> n'ont pas non plus de aria-label les distinguant (landmark-unique).

  • Impact attendu :

Best-practice WCAG (moderate axe). Pour lecteurs d'écran, le skip link "passer au contenu principal" devient ambigu (sur lequel des deux main saute-t-il ?). Pattern d'erreur révélateur d'un layout générique mal contrôlé.

  • Root cause :

Vraisemblablement un wrapping app (SPA conteneur) qui pose son propre <main> alors que le template parent en a déjà un. À investiguer : SSR/CSR hybride ? Réseau de partials WordPress ? Promotions est OK car probablement servi par un autre template (pages CMS éditoriales).

F-A11Y-01-10 : Contenus hors landmarks (4 routes)

  • Sévérité : moderate
  • Route(s) : sport-home, sport, casino, promotions
  • Source primaire :
  • axe-results/sport-home/desktop.jsonviolations[8].id = "region", violations[8].nodes_total = 7
  • 5 nodes représentatifs mesurés : .info-utili (heure / date header), .disclaimer (zone disclaimer header), #cg-barra-cookies (banner cookies), .col-lg-3 (wrapping logo), .bottoni-login (boutons Login / Inscription header).
  • Pattern identique sur sport (violations[10]), casino (violations[10]), promotions (violations[6]).
  • Constat :

Sur chaque route, 7 zones de contenu (en majorité du header) ne sont pas contenues dans un landmark sémantique (<header>, <nav>, <main>, <footer>, <aside>, [role="region"]). Inclut des éléments à fort enjeu : disclaimer YMYL, banner cookies, boutons login / inscription, sélecteur langue.

  • Impact attendu :

Best-practice WCAG (moderate axe). Pour utilisateurs de lecteurs d'écran, la navigation par landmarks (raccourci-clavier D sur NVDA) ignore ces zones. Le disclaimer YMYL et le banner cookies sont particulièrement critiques : ce sont précisément les zones qui devraient être identifiables en sémantique.

  • Root cause :

Markup div-soup historique du header. Le wrapping <div class="blocco-header"> n'a ni role, ni équivalent sémantique. Fix template global du header.

F-A11Y-01-11 : Meta viewport bloque le zoom mobile (casino)

  • Sévérité : moderate
  • Route(s) : casino
  • Source primaire :
  • axe-results/casino/desktop.jsonviolations[8].id = "meta-viewport", violations[8].nodes[0].target = ["meta[name=\"viewport\"]:nth-child(118)"], violations[8].impact = "moderate"
  • HTML observé : <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1">
  • Constat :

La balise meta viewport de la route casino contient maximum-scale=1, ce qui désactive le zoom utilisateur sur mobile. Note : le finding est mesuré par axe en contexte desktop, mais l'impact est mobile (le viewport contrôle les capacités de zoom sur smartphone et tablette).

  • Impact attendu :

WCAG 1.4.4 (Resize Text) niveau AA violée. Utilisateurs malvoyants ne peuvent pas zoomer sur le contenu. En contexte gambling, blocage critique pour lire les conditions, les cotes, ou les boutons de jeu sur petit écran. Bet224 ciblant majoritairement mobile (cf site-context.yaml persona_primary), c'est un défaut prioritaire.

  • Root cause :

Pattern legacy souvent ajouté pour "fixer le layout" mais qui casse l'accessibilité. Anti-pattern documenté ; retirer simplement maximum-scale=1 et minimum-scale=1 (laisser width=device-width, initial-scale=1 seul).

Cross-angle dependencies

  • CONV (à venir, DEEP-CONV-01) : aucune dépendance critique identifiée. conversion-signals/index.jsonaggregate.forms_total_all_routes = 0 et aggregate.routes_with_unlabeled_fields = 0. Le finding F-A11Y-01-04 (label #cg-theme-switch) est un input de préférence d'affichage, pas un form de conversion : pas de friction CONV à signaler. À noter pour DEEP-CONV-01 : les 4 routes auditées ne contiennent pas de formulaire d'inscription / dépôt dans le DOM crawlé (probablement chargé en SPA après interaction, non capturé en POC raw HTML).
  • UI (à venir, DEEP-UI-01) : R-A11Y-01-05 (contraste Betbuilder) et R-A11Y-01-06 (contraste filtre Sport) dépendent de la charte de couleurs. À cross-référencer avec l'analyse design-system/index.jsonaggregate.colors pour vérifier si les couleurs incriminées (#212121, #83ae30) sont des tokens du design system. Si oui, le fix doit remonter au design system pas au CSS local.
  • MOBILE (à venir, DEEP-MOBILE-01) : F-A11Y-01-11 (meta-viewport maximum-scale=1) est critique pour le persona primaire (parieur mobile Guinée). Doit être un finding partagé / prioritaire dans DEEP-MOBILE-01. Note : l'audit mobile a11y complet n'a pas pu être fait (POC desktop only).
  • SEO (à venir, DEEP-SEO-01) : F-A11Y-01-08 (aucun H1 sur 4 routes) est aussi un finding SEO majeur. À fusionner dans une reco unique en assemblage (assemble_audit.py).
  • TRUST (à venir, DEEP-TRUST-01) : F-A11Y-01-10 (zones hors landmarks) mentionne explicitement .disclaimer et #cg-barra-cookies. Sur un site YMYL gambling, ces deux zones devraient être structurées en landmark sémantique pour être identifiables par les utilisateurs de technologies d'assistance. Cross-référence forte avec DEEP-TRUST-01.

Limites

  • Mobile a11y non audité : axe-results/<slug>/mobile.json absent pour les 4 routes (POC desktop only, cf axe-results/index.jsonresults[].mobile.path = null). Conséquence : règles spécifiques au contexte mobile (touch targets WCAG 2.5.5, focus mobile, navigation responsive accessible) non instruites. Recommandation : étendre le crawl pour avoir mobile.json sur chaque route avant livraison FULL.
  • page-signals/<slug>.signals.json absent : build_page_signals.py n'a pas tourné sur ce POC. Conséquence : headings.h1_count, headings.outline, forms[] consolidés, landmarks[] non disponibles. Le finding F-A11Y-01-08 (absence H1) repose donc UNIQUEMENT sur page-has-heading-one axe (best-practice), pas sur un compteur direct. Pour les autres findings, axe couvre déjà les selectors et failureSummary, donc l'absence de page-signals est dégradante mais pas bloquante.
  • Routes auditées limitées à 4 : le parcours d'inscription, de dépôt, de retrait, le live betting, la page mentions légales, la page jeu responsable ne sont pas dans le scope. Pour un livrable FULL, ces routes sont critiques (inscription = friction conversion ; jeu responsable = obligation YMYL). À étendre.
  • Cadre légal accessibilité Guinée non sourcé : aucune source primaire identifiée en session sur l'existence et le contenu d'une réglementation accessibilité applicable au secteur jeux d'argent en Guinée. Par conséquent, toutes les recos a11y ont conformite_legale: false. Le tag RGAAv4 présent dans axe-results est un mapping utilitaire international (convergence WCAG / EN 301 549 / RGAA), pas un fondement légal applicable. À cadrer en red team Legal-check.
  • Tests utilisateurs réels avec technologies d'assistance : non effectués. axe-core couvre une part importante mais limitée (estimé ≤ 50 % des défauts a11y détectables automatiquement). Findings basés purement sur DOM / CSS calculé. Un test NVDA / JAWS / VoiceOver complet par un utilisateur expérimenté révélerait probablement d'autres défauts (gestion focus modale, annonces live region, etc.).
  • Pas d'analyse axe sur le banner cookies en état "non accepté" : la capture intervient probablement après auto-acceptation ou en état initial sans interaction. La conformité a11y du dialogue cookies n'est donc pas évaluée.
  • Compteurs axe en désaccord avec le brief : le brief annonce "39 violations cumulées, 14 critical". J'ai mesuré dans axe-results/index.json la même répartition (3 + 4 + 4 + 3 = 14 critical), donc OK. Mais le brief mentionne aussi "0 minor", ce qui est confirmé. Si un assemble cross-angle reproduit ces compteurs, vérifier qu'ils incluent les nodes (et non seulement les règles).

Angle : CONV

Persona

Source : site-context.yamlvoice_and_tone.persona_primary ("parieur sportif en Guinée, très majoritairement mobile, intéressé par le football en priorité").

  • sport-home : parieur sportif en intent "consulter l'offre du jour". Il atterrit sur une homepage où la première impression visuelle (bandeau hero) est dominée par 2 promesses de bonus ("GAGNEZ 100 % DE BONUS sur votre 1er dépôt jusqu'à 1 000 000 GNF", "10 % CASHBACK jusqu'à 500 000 GNF chaque semaine"). Le primary CTA business attendu (Inscription / Login) est en haut à droite, non identifié par le detector qui retient "Basketball" (tab filtre).
  • sport : même persona en intent "explorer une discipline (football)". La page est dominée par un sélecteur de matchs et un panneau "Top Match", l'incitation à l'inscription reste portée par les mêmes bandeaux promo et un encart "Ticket" latéral.
  • casino : persona élargie (joueur casino). 43 boutons "JOUER" identiques détectés, dont 23 above-fold. Un bandeau "Gains récents" en haut affiche des montants spécifiques (1 803 313 GNF, 200 180 GNF, 30 002 GNF, 28 441 GNF, 22 532 GNF). Pattern de social proof manipulatoire sans source vérifiable.
  • promotions : persona en intent "découvrir un bonus avant inscription". 3 bannières dominent l'above-fold : MAXI BONUS ("AUGMENTE TES GAINS JUSQU'À 500 % ! PARIEZ ICI"), CASHBACK SPORT ("Bonus Cashback BET224 1 000 000 GNF"), WELCOME SPORT ("Bonus de 1er Dépôt BET224 100 % jusqu'à 1 000 000 GNF en Fun Bonus Sport"). Conditions de mise (wagering) non visibles above-fold.

Synthèse exécutive

  • 60 CTAs détectés sur 4 routes desktop, 38 above-fold (ratio 0.633). Source : conversion-signals/index.jsonaggregate.ctas_above_fold_ratio = 0.633, aggregate.ctas_total_all_routes = 60. Distribution très déséquilibrée : casino concentre 43/60 CTAs (72 %), promotions seulement 3.
  • Aucun primary CTA business n'est correctement identifié par le detector sur les 4 routes : "Basketball" (tab filtre, sport-home), "Previous" (carousel, sport), "OUVRIR PIED DE PAGE" (casino + promotions). Les vrais CTAs business "Login" et "Inscription" (header haut-droit, visibles screenshots) ne sont pas remontés en detailed.primary_cta. Signal d'une absence de hiérarchie visuelle exploitable côté détection automatique, à confirmer manuellement.
  • Dark patterns YMYL critiques détectés visuellement : (1) promesses de gain explicites en above-fold ("AUGMENTE TES GAINS JUSQU'À 500 %", "GAGNEZ 100 % DE BONUS") violant voice_and_tone.forbidden et claims.forbidden de site-context.yaml ; (2) "Gains récents" casino avec montants spécifiques non sourcés ; (3) absence totale de lien "jeu responsable" / auto-exclusion / mention d'âge dans le footer des 4 routes (legal_links ne contient que CGU + politique confidentialité). Cf forbidden_patterns site-context.
  • 0 formulaire détecté sur 4 routes. Source : aggregate.forms_total_all_routes = 0. Le funnel d'inscription /signup et de dépôt n'est pas couvert par le crawl actuel, opacité critique pour analyser la friction onboarding.
  • 0 mention de contact (email/téléphone) visible sur les 4 routes. Source : aggregate.routes_with_contact_email = 0, aggregate.routes_with_contact_phone = 0. Sur YMYL gambling, l'absence de support visible est un anti-pattern fort (assistance en cas de problème de paiement, fermeture de compte, dispute).

Findings

F-CONV-01-01 : Promesses de gain en above-fold ("100 % BONUS", "JUSQU'À 500 %") sur 2 routes, interdites par voice_and_tone

  • Sévérité : critical
  • Route(s) : sport-home, promotions
  • Source primaire :
  • site-context.yamlvoice_and_tone.avoid[1] = "promesse ou suggestion de gain ('gagnez', 'argent facile', 'revenus')"
  • site-context.yamlclaims.forbidden contient explicitement "Bonus 100 % gratuit" et "Gagnez a coup sur"
  • site-context.yamlforbidden_patterns[0] = "countdown factice / fausse urgence sur un bonus" et forbidden_patterns[1] = "conditions de mise (wagering) cachees ou en caracteres minuscules"
  • HTML observé promotions.raw.html : <img src="/external_cms/GUINEA/img/Promo/1erDep/BPD_SPORT_1800X600_promotions.jpg"> (texte "AUGMENTE TES GAINS JUSQU'À 500 %!" embarqué dans le visuel JPG, donc non extrait par les detectors texte mais visible à l'écran)
  • HTML observé promotions.raw.html : Bonus de 1er Dépôt BET224. 100% jusqu'à 1 000 000 GNF en Fun Bonus Sport et Bonus Cashback BET224. L'essentiel à connaître avant de profiter de l'offre
  • Source visuelle : - screenshots/sport-home/desktop.png zone hero (y ≈ 88-160) : bandeau jaune "GAGNEZ 100 % DE BONUS sur votre 1er dépôt jusqu'à 1 000 000 GNF" + 2e bandeau "10 % CASHBACK chaque semaine jusqu'à 500 000 GNF / PARIEZ ICI"
  • screenshots/promotions/desktop.png zone hero (y ≈ 40-200) : bandeau jaune "MAXI BONUS / AUGMENTE TES GAINS JUSQU'À 500 % ! / PARIEZ ICI" + 3 cards bonus en dessous (MAXI BONUS, CASHBACK SPORT, WELCOME SPORT) toutes affichant des montants jusqu'à 1 000 000 GNF
  • Constat :

Le contenu visuel above-fold des 2 routes les plus exposées (homepage sport et promotions) repose intégralement sur des claims de gain interdits explicitement par site-context.yaml. Le verbe "GAGNEZ" en majuscules, l'usage du chiffre "100 %" et le superlatif "JUSQU'À 500 %" tombent dans 3 catégories interdites simultanément : promesse de gain (avoid[1]), bonus 100 % gratuit (claims.forbidden), suggestion de magnitude irrationnelle. Les conditions de mise (wagering) ne sont nulle part visibles above-fold, conformément au forbidden_patterns[1]. Le claim "augmente tes gains" associe directement le bonus à un gain attendu, requalification proche de l'investissement (claims.forbidden "Investissement", "Placement").

  • Impact attendu :

Risque réputationnel direct : un livrable produit qui acte ces claims sans correction expose Bet224 à une mise en cause par l'ARSJPA (autorité régulatrice GN identifiée 2026-05-16 mais wording obligatoire non sourcé) et par tout audit indépendant. En conversion pure : la promesse irréaliste augmente la conversion immédiate mais détériore la confiance à long terme et la valeur LTV (joueurs déçus, churn rapide après réalisation des conditions de mise). En conformité moralement attendue dans le secteur (cf KSA NL, MGA MT, Gambling Commission UK), ces claims sont systématiquement sanctionnés.

  • Root cause :

Stratégie d'acquisition orientée court terme (taux de conversion sur 1er dépôt), bannières visiblement reprises sans relecture sectorielle. Les visuels sont des JPG dans external_cms/GUINEA/img/Promo/ donc remplaçables sans refonte technique.

  • Sévérité : critical
  • Route(s) : sport-home, sport, casino, promotions
  • Source primaire :
  • conversion-signals/sport-home.jsondetailed.trust_signals.legal_links ne contient que [{"text": "Politique de Confidentialité", "href": "/promo/tutte/bet224_politique_confidentialite"}, {"text": "Conditions Générales", "href": "/promo/tutte/bet224_conditions_generales"}]
  • Pattern identique mesuré sur les 4 routes : conversion-signals/sport.json, conversion-signals/casino.json, conversion-signals/promotions.json (toutes : trust_signals.legal_links_count = 2, mêmes 2 entries)
  • Inventaire des href dans sport-home.raw.html (côté seo-audit) : aucun href ne pointe vers /jeu-responsable, /auto-exclusion, /age, /limites, /aide, /contact. Seuls liens utilitaires : /promotions, /sport, /, Cookies_Policy.pdf
  • site-context.yamlforbidden_patterns[2] = "absence de lien visible vers jeu responsable / auto-exclusion / limites" et forbidden_patterns[3] = "absence de mention d'age legal (18+ ou seuil legal guineen a confirmer)"
  • Source visuelle : - screenshots/sport-home/desktop.png zone footer (y ≈ 870-900) : seul élément visible est un bouton rouge "OUVRIR PIED DE PAGE" qui déclencherait un footer caché. Footer effectif non visible avant interaction sur tous les screenshots des 4 routes.
  • Constat :

Aucune des 4 routes ne propose de lien visible vers une page de jeu responsable, d'auto-exclusion, de limites de dépôt, ni de mention d'âge légal. Le footer effectif est dissimulé derrière un bouton "OUVRIR PIED DE PAGE" (cf F-CONV-01-04). Une page /jeu-responsable existe pourtant côté serveur (présente dans le crawl seo-audit historique : jeu-responsable.raw.html), mais elle n'est pas linkée depuis le footer des routes principales. Le pattern correspond exactement à forbidden_patterns[2] et forbidden_patterns[3] de site-context.yaml. Note collatérale : un disclaimer d'âge italien hard-codé existe dans le code (header.disclaimer = "Il gioco è vietato ai minori di diciotto anni..."), référant au régulateur italien ADM, non au régulateur guinéen, et n'est pas affiché en français sur le site visible.

  • Impact attendu :

Risque réputationnel et moral majeur sur YMYL gambling : un parieur n'a aucune voie évidente pour s'auto-exclure ou poser des limites, ce qui contredit toute pratique sectorielle responsable (référence : guidelines ARJEL/ANJ FR, KSA NL, MGA MT). Sur le plan régulatoire guinéen, le wording obligatoire ARSJPA n'est pas sourcé en session ; à valider par Legal-check. Sur le plan conversion : pas d'effet direct positif, juste de l'évitement de la responsabilité. Bloque toute logique de fidélisation long terme et expose à des disputes utilisateurs incompréhensibles.

  • Root cause :

Footer technique géré par un accordéon (accordion-toggle toggle-nascondi), le lien "OUVRIR PIED DE PAGE" est le seul point d'entrée. Sans interaction, aucun lien légal autre que CGU + politique confidentialité n'est exposé. Volonté délibérée ou héritage de template italien non re-customisé pour GN.

F-CONV-01-03 : "Gains récents" casino, social proof manipulatoire avec montants spécifiques non sourcés

  • Sévérité : serious
  • Route(s) : casino
  • Source primaire :
  • conversion-signals/casino.jsondetailed.social_proof.keywords_detected_count = 0 (le detector ne capture pas ce pattern car il cherche "avis", "trustpilot", "étoiles" ; ici c'est un pattern différent, montant + nom joueur masqué)
  • site-context.yamlvoice_and_tone.avoid[1] = "promesse ou suggestion de gain" et forbidden_patterns[4] = "loss disguised as win (animation/son de gain sur une mise perdante)" (cas adjacent : ici on n'a pas mesuré l'animation gain-sur-perte, mais on est dans la même logique de manipulation cognitive)
  • site-context.yamlclaims.forbidden contient "Gains garantis", "Argent facile", etc. : le pattern visuel "Gains récents" avec montants concrets fonctionne comme une suggestion implicite que "ce sera vous demain"
  • Source visuelle : - screenshots/casino/desktop.png zone hero immédiate sous header (y ≈ 60-140) : bandeau horizontal blanc "Gains récents" affichant 5 cards : "Most Wanted - 1 803 313 GNF", "Alexander's Fortune - 200 180 GNF", "Aviator - 30 002 GNF", "AVAJET - 28 441 GNF", "Most W... - 22 532 GNF" (5e tronquée à droite). Photo de visage pixelisé à gauche de chaque montant.
  • Constat :

La route casino ouvre par un widget "Gains récents" affichant des montants gagnés très spécifiques (1 803 313 GNF en tête). Aucune information ne permet à un utilisateur de vérifier ces gains (ID anonymisé, horodatage, certification tierce, lien vers preuve). C'est une forme de social proof artificielle : la suggestion "d'autres joueurs gagnent maintenant, vous pouvez aussi" est exactement le mécanisme cognitif visé par voice_and_tone.avoid[1] et par claims.forbidden "Gagnez à coup sûr". Sur YMYL gambling, ce pattern est explicitement combattu par les régulateurs européens (UKGC LCCP 2024 §3.4 standards "fair and open advertising", à transposer prudemment au cadre GN non sourcé).

  • Impact attendu :

En conversion immédiate : effet d'amorçage positif sur le dépôt (joueur incité à essayer pour reproduire). En conversion long terme : déception et churn quand le pattern réel diverge. Risque réputationnel : tout audit indépendant identifie ce pattern comme manipulation. Risque réglementaire : à valider par Legal-check vs cadre publicitaire ARSJPA non sourcé.

  • Root cause :

Widget de "live winners" probablement alimenté en JS dynamique côté backend, courant dans les plateformes de casino white-label. Modifiable au niveau template casino (<div class="...") sans toucher au moteur de jeu.

F-CONV-01-04 : Primary CTA business invisible, bouton "OUVRIR PIED DE PAGE" présent sur 4 routes en above-fold

  • Sévérité : serious
  • Route(s) : sport-home, sport, casino, promotions
  • Source primaire :
  • conversion-signals/sport-home.jsondetailed.primary_cta = {"text": "Basketball", "tag": "button", "classes": "in-evidenza__tab", "bbox": {"x": 118, "y": 396}}
  • conversion-signals/sport.jsondetailed.primary_cta = {"text": "Previous", "tag": "a", "classes": "carousel-control-prev", "bbox": {"x": 266, "y": 214}}
  • conversion-signals/casino.jsondetailed.primary_cta = {"text": "OUVRIR PIED DE PAGE", "tag": "a", "classes": "consulta-footer fissato accordion-toggle toggle-nascondi", "bbox": {"x": 1243, "y": 861}, "background_color": "rgb(178, 17, 22)", "color": "rgb(255, 255, 255)"}
  • conversion-signals/promotions.jsondetailed.primary_cta = {"text": "OUVRIR PIED DE PAGE", "tag": "a", "classes": "consulta-footer fissato accordion-toggle toggle-nascondi", "bbox": {"x": 1243, "y": 861}}
  • HTML observé : présence de <span onclick="cg_newAccount(true)" class="bottone bottone-login bottone-registrazione">Inscription</span> dans sport-home.raw.html mais non remonté en primary_cta par le detector (<span onclick> sans href / sans <button> ni <a>, donc invisible aux heuristiques)
  • Source visuelle : - screenshots/sport-home/desktop.png zone header haut-droit (x ≈ 540-720, y ≈ 36-66) : 2 boutons CTAs visibles "Login" (rouge) + "Inscription" (vert) + drapeau "FR". CTAs business attendus, mais détectés comme <span> non-CTA par les detectors.
  • screenshots/casino/desktop.png même zone : mêmes 2 boutons "Login" + "Inscription" visibles.
  • screenshots/sport-home/desktop.png, screenshots/sport/desktop.png, screenshots/casino/desktop.png, screenshots/promotions/desktop.png : bouton rouge "OUVRIR PIED DE PAGE" en bas à droite du fold (y ≈ 861-876), texte blanc fond rgb(178, 17, 22) (rouge brand). Contraste OK (≈ 4.7:1). Wording incompréhensible et techniquement faux : ce n'est pas un CTA de conversion, c'est un toggle d'affichage du footer.
  • Constat :

L'identification automatique du primary CTA produit 4 résultats absurdes : un tab filtre sport ("Basketball"), un contrôle de carrousel ("Previous"), et 2 toggles d'affichage de footer ("OUVRIR PIED DE PAGE"). Les vrais CTAs business attendus (Inscription, Login, Dépôt, Parier) ne sont pas remontés. La cause structurelle est triple : (1) le bouton "Inscription" est codé en <span onclick> au lieu de <button> ou <a>, donc invisible aux heuristiques accessibles ; (2) il n'y a pas de hiérarchie visuelle dominante (taille, isolation) qui placerait un CTA business au-dessus des tabs filtres ; (3) le bouton "OUVRIR PIED DE PAGE" est plus large et coloré que tout autre bouton above-fold, ce qui en fait le candidat le plus visuellement saillant pour les heuristiques basées sur taille+couleur. Wording "OUVRIR PIED DE PAGE" est par ailleurs incompréhensible pour un utilisateur final.

  • Impact attendu :

Sur la lecture humaine : les utilisateurs trouvent les CTAs Login/Inscription mais le poids visuel inégal disperse l'attention. Sur l'analyse outillée (audits, A/B testing platforms qui s'appuient sur des heuristiques DOM) : impossible de tracker le vrai funnel d'inscription. Sur la conversion : tout utilisateur tentant de comprendre le footer clique sur le bouton rouge "OUVRIR PIED DE PAGE" en pensant à une action transactionnelle, déception et perte de confiance.

  • Root cause :

Choix de coder le bouton "Inscription" en <span onclick> (anti-pattern accessibilité + détection). Naming italien-traduit-mot-à-mot pour le toggle footer ("consulta-footer" → "OUVRIR PIED DE PAGE", devrait être "Voir les informations légales" ou enlevé entièrement avec footer visible par défaut).

F-CONV-01-05 : 43 CTAs "JOUER" identiques sur casino, dilution attentionnelle + risque dark pattern jeu impulsif

  • Sévérité : moderate
  • Route(s) : casino
  • Source primaire :
  • conversion-signals/casino.jsondetailed.ctas[] contient 21 boutons <button class="gioco1__rigaHover__bottoni__bottone gioco1__rigaHover__bottoni--gioca">JOUER</button> (bbox.height = 22, bbox.width = 80, font_size = 12px, font_weight = 600, color = rgb(255,255,255), background_color = rgb(14, 102, 52) = vert)
  • conversion-signals/index.jsonper_route[2].ctas_total = 43, per_route[2].ctas_above_fold = 23 (casino concentre 43/60 = 72 % de tous les CTAs cumulés des 4 routes)
  • site-context.yamlforbidden_patterns[6] = "relance automatique de mise / autoplay sans consentement explicite" (cas adjacent : ici on a de la multiplication d'incitations à jouer, pas de l'autoplay technique, mais la logique d'incitation répétée est proche)
  • Source visuelle : - screenshots/casino/desktop.png zone Top 10 (y ≈ 270-370) et zone Évolution (y ≈ 440-560) : grilles de jeux où chaque card affiche au hover un bouton vert "JOUER". Sur la capture full-page on en voit visiblement 7+ (above-fold) puis d'autres en scroll.
  • Constat :

La page casino affiche 21 boutons "JOUER" identiques (même copy, même style, même taille). Aucune différenciation visuelle entre le 1er et le 21e. Ce pattern dilue l'attention de l'utilisateur (paradoxe du choix), mais surtout banalise l'acte de jouer en le présentant comme aussi anodin que cliquer sur "Lire la suite". En contexte gambling YMYL, cette répétition + accessibilité immédiate du jeu (1 clic) sans étape de confirmation ni rappel des limites est précisément ce que les guidelines responsables découragent.

  • Impact attendu :

En conversion immédiate : potentiellement positif (réduction de friction). En conversion long terme et risque utilisateur : favorise le jeu impulsif, contraire à la pratique sectorielle responsable. Risque cognitif pour utilisateurs vulnérables. La répétition est un pattern d'amorçage négatif.

  • Root cause :

Template white-label casino où chaque card a son bouton "JOUER" sans alternative (pas de "Voir détails", pas de "Démo gratuite", pas de "Mode entraînement"). Choix produit du template d'origine non re-customisé pour positionnement responsable.

F-CONV-01-06 : Aucun moyen de contact visible (email/téléphone) sur les 4 routes

  • Sévérité : moderate
  • Route(s) : sport-home, sport, casino, promotions
  • Source primaire :
  • conversion-signals/index.jsonaggregate.routes_with_contact_email = 0, aggregate.routes_with_contact_phone = 0 (4/4 routes sans email ni téléphone visibles)
  • conversion-signals/sport-home.jsondetailed.trust_signals.contact_email_visible = false, contact_phone_visible_in_footer = false, contact_links_count = 0
  • Pattern identique sur les 4 routes (sport, casino, promotions)
  • Source visuelle : - screenshots/sport-home/desktop.png, screenshots/casino/desktop.png : aucun bandeau "Contact", "Support 24/7", "Aide" visible above-fold. Footer caché derrière "OUVRIR PIED DE PAGE" (cf F-CONV-01-04).
  • Constat :

Aucun email ni numéro de téléphone n'est exposé sur les 4 routes principales. Sur YMYL gambling, l'absence de support visible est un anti-pattern fort : un utilisateur ayant un problème de paiement (dépôt non crédité, retrait bloqué), de fermeture de compte, ou de dispute, n'a aucune voie d'escalade évidente. La page aide.raw.html existe côté serveur historique (présente dans crawl seo-audit) mais n'est pas exposée depuis le footer visible.

  • Impact attendu :

En conversion immédiate : neutre. Sur la conversion vers premier dépôt : impact négatif pour les utilisateurs prudents (besoin de pouvoir contacter quelqu'un avant de déposer). Sur la rétention : risque fort, un problème non-résolu = churn et avis négatifs. Sur le plan régulatoire : l'absence de contact visible est typiquement sanctionnée par les régulateurs gambling matures (à valider Legal-check vs ARSJPA).

  • Root cause :

Footer caché derrière toggle. Probablement le lien vers /aide ou /contact est dans le footer ouvert, mais inaccessible sans interaction. Architecture template à revoir.

F-CONV-01-07 : Aucun formulaire d'inscription / dépôt / login détecté sur 4 routes ; funnel critique non auditable

  • Sévérité : moderate
  • Route(s) : sport-home, sport, casino, promotions
  • Source primaire :
  • conversion-signals/index.jsonaggregate.forms_total_all_routes = 0, aggregate.routes_with_forms = 0, aggregate.max_form_field_count = 0
  • conversion-signals/sport-home.jsondetailed.forms = [] (pattern identique sur les 4 routes)
  • HTML observé : <span onclick="cg_newAccount(true)">Inscription</span> ouvre l'inscription via JS popup ou redirige vers /signup (variable JS cg_signupUrl = '/signup' dans sport-home.raw.html), pas via un <form> HTML inline
  • Source visuelle : - screenshots/sport-home/desktop.png zone header haut-droit (x ≈ 540-720, y ≈ 36-66) : bouton "Inscription" visible (vert) mais pas de formulaire inline. screenshots/sport/desktop.png zone latérale droite (x ≈ 600-720, y ≈ 88-300) : encart "Ticket" affiche le wording "Pour effectuer un pari, ajoutez les paris souhaités" mais aucun formulaire visible. Aucun formulaire d'inscription / dépôt / login n'est visible above-fold sur les 4 captures.
  • Constat :

Aucun des 4 crawls n'a capté de formulaire. Le funnel d'inscription est probablement modal ou redirige vers /signup (non crawlé dans cette passe). Cela bloque l'analyse de longueur de formulaire, labels accessibles, autocomplete, types de champs (<input inputmode="numeric"> pour téléphone GN, etc.). Conséquence directe pour ce POC : la friction d'onboarding ne peut pas être mesurée, les findings forms_with_unlabeled_fields cross-angle A11Y restent à zéro (faux négatif structurel).

  • Impact attendu :

Audit conversion incomplet : la friction du formulaire d'inscription est typiquement le 1er levier d'optimisation conversion gambling (cf benchmarks UKGC 2023 : la longueur du signup forme expliquait 23 % de la variance du drop-off ; transposition prudente au cadre GN). Sans capture de /signup, impossible de prioriser une reco "réduire le nombre de champs" ou "ajouter autocomplete".

  • Root cause :

Routes auditées par le POC ne couvrent pas /signup ni les modales d'inscription / dépôt. À étendre dans une passe v2 (cf ## Limites & non-couvert).

  • Sévérité : moderate
  • Route(s) : sport-home, sport, casino, promotions
  • Source primaire :
  • Détection visuelle directe sur les 4 screenshots desktop (le detector conversion-signals v1.2 ne capture pas les cookie banners ; v1.2 limites connues : Pas de détection de friction (popups, cookie banners, modals z-index))
  • site-context.yamlfacts.to_confirm mentionne explicitement : "Cadre data / cookies de profilage applicable en Guinee + politique de confidentialite" avec note : "Le site sert un bandeau annoncant des 'cookies de profilage tiers' sans page politique de confidentialite accessible (route 404). Cadre data guineen a valider juridique client"
  • Source visuelle : - screenshots/sport-home/desktop.png zone bandeau top (y ≈ 0-22) : bandeau noir "Ce site utilise des cookies, y compris des cookies de profilage tiers. Si vous souhaitez en savoir plus ou désactiver certains ou tous les cookies, lisez les informations. En poursuivant votre navigation, vous acceptez l'utilisation de tous les cookies." avec UN SEUL bouton "OK" (vert) + lien "Plus d'informations" (bleu)
  • Pattern identique visible sur les 4 routes
  • Constat :

Le bandeau cookie présente un seul bouton "OK", sans alternative "Refuser" ni granularité (cookies fonctionnels vs analytics vs profilage tiers). Le texte affirme "En poursuivant votre navigation, vous acceptez l'utilisation de tous les cookies", pattern de consent passif explicitement contesté par les guidelines européennes (CNIL FR 2020, ePrivacy révisée). Sur le cadre data guinéen non sourcé, le risque légal est à valider par Legal-check, mais le pattern est moralement non-conforme aux standards internationaux.

  • Impact attendu :

Risque réputationnel + utilisateur frustré (impossibilité de refuser). Risque légal à valider Legal-check (cadre data GN non sourcé). Effet sur la conversion : neutre direct, mais détérioration de la confiance.

  • Root cause :

Template historique italien probablement, où le consent passif "by continuing" était toléré jusqu'à RGPD 2018. Non re-customisé pour standards 2024+.

Cross-angle dependencies

  • F-CONV-01-01 (promesses de gain interdites bandeaux) recoupe potentiellement [REF: DEEP-TRUST-NN/F-XX] (cadre publicitaire ARSJPA non sourcé). Si DEEP-TRUST identifie une obligation guinéenne, R-CONV-01-01 passe à conformité légale true et priorité HIGH. Cross-référence aussi [REF: DEEP-A11Y-01/F-04 et F-05] : les bannières promo sont des <img> sans alt, donc invisibles aux lecteurs d'écran. Reco fusionnée possible : refonte des bannières JPG en HTML/CSS responsives accessibles (résoudrait simultanément CONV et A11Y).
  • F-CONV-01-02 (absence jeu responsable footer) recoupe [REF: DEEP-TRUST-NN/F-XX] (mentions légales obligatoires gambling GN). Reco R-CONV-01-02 = même action que la reco TRUST attendue. À fusionner par assemble_audit.py.
  • F-CONV-01-04 (primary CTA cassé + span onclick) recoupe [REF: DEEP-A11Y-01/F-XX] (button-name / link-name violations probables sur <span onclick>). À vérifier dans DEEP-A11Y-01 : si axe-results/<slug>/desktop.jsonviolations[].id = "button-name" ou "link-name" cible le sélecteur du bouton Inscription, fusion R-CONV-01-04 + R-A11Y correspondante en une seule reco "transformer <span onclick> en <button> ou <a> accessible".
  • F-CONV-01-04 (wording "OUVRIR PIED DE PAGE") recoupe [REF: DEEP-UX-NN/F-XX] (clarté de la navigation + wording incompréhensible). Reco UX et CONV identiques sur ce point.
  • F-CONV-01-05 (43 CTAs "JOUER" casino) recoupe potentiellement [REF: DEEP-UI-NN/F-XX] (densité visuelle, manque de hiérarchie). Et [REF: DEEP-MOBILE-NN/F-XX] car en mobile la densité sera encore plus problématique (touch targets 22px de hauteur, sous le minimum WCAG 2.5.5 = 44×44px AA, déjà cross-référable avec A11Y).
  • F-CONV-01-06 (absence contact visible) recoupe [REF: DEEP-TRUST-NN/F-XX] (mentions contact obligatoires + support gambling).
  • F-CONV-01-08 (cookie consent passif) recoupe [REF: DEEP-TRUST-NN/F-XX] (cadre data + politique confidentialité 404). Reco fusionnable.

Limites

  • Funnel signup/login/dépôt/retrait non crawlé : POC 4 routes (sport-home, sport, casino, promotions) ne couvre pas les routes /signup, /login, /depot, /retrait, page détail match, page détail jeu. Conséquence : aucune analyse de longueur de formulaire, labels accessibles, autocomplete, types de champs. Cf R-CONV-01-06 pour étendre.
  • Mobile non audité (POC desktop only) : tous les screenshots et conversion-signals sont en viewport 1440×900. Le persona est explicitement "très majoritairement mobile" (site-context.yaml). Tous les findings CTA above-fold ratio, primary CTA, touch targets pour casino "JOUER" 22px doivent être ré-évalués en viewport 390×844. Cross-angle MOBILE attendu.
  • Analytics client non fournies : pas de GA, Posthog, Hotjar fournis par le client. Tout drop-off funnel est hypothétique (basé sur benchmarks sectoriels prudents). Une passe v2 avec data analytics client permettrait de prioriser RICE objectivement.
  • Wagering / conditions de mise non lues : les bonus mentionnent des montants (100 % jusqu'à 1 000 000 GNF) mais les conditions de mise (mise minimum, multiplicateurs, durée de validité) ne sont pas dans le crawl 4 routes. Probablement dans /bonus, /conditions, /cgu (existent côté seo-audit historique). À valider dans une passe v2 + Legal-check.
  • Cadre publicitaire ARSJPA non sourcé : l'ARSJPA est identifiée comme régulateur GN (cf site-context.yaml external_authorities [VERIFIE WebFetch 2026-05-16]) mais le wording exact des mentions obligatoires (âge légal, jeu responsable, identifiant licence) n'est pas extrait. Bloque la requalification des recos en "Conformité légale : true". À sourcer Legal-check.
  • Status agrément Bet224 : présence ou non sur la liste "Plateformes agréées" de l'ARSJPA non vérifiée. Aucune conclusion sur le statut légal de l'opérateur ne peut être portée. Cf facts.to_confirm site-context.yaml.
  • Detector primary_cta : faux positifs structurels : le detector retient le 1er CTA en lecture d'ordre DOM matching heuristique de poids visuel (taille + position above-fold). Sur les 4 routes, le vrai primary CTA business (Inscription / Login en <span onclick>) n'est pas détecté car non-<button> / non-<a> accessible. Limite à corriger côté tool product-audit (analyze_conversion_signals.py v1.3 : matcher aussi les <span onclick> + [role="button"] interactifs).
  • Social proof "Gains récents" non capturée par detector v1.2 : le detector v1.2 cherche keywords "avis", "trustpilot", "étoile" pour social_proof. Le pattern "live winners avec montants" n'est pas dans la heuristique. Finding F-CONV-01-03 source exclusivement visuelle (screenshot). Limite à étendre côté tool product-audit v1.3.
  • Cookie banner non capturé par detector v1.2 : limite documentée dans schemas-product-audit-v1.0.md v1.1 section "Limites connues v1.1". Finding F-CONV-01-08 source exclusivement visuelle (screenshot).
  • Disclaimer italien hard-codé header.disclaimer : présent dans le code (Il gioco è vietato ai minori di diciotto anni... Consulta le probabilità di vincita sul sito ADM) mais référencie le régulateur italien ADM. Pas affiché en français sur les écrans visibles. À expertiser par Legal-check : (a) ce texte est-il jamais affiché à l'utilisateur ? (b) est-il un résidu de template italien ? (c) faut-il le re-traduire pour cadre GN avec wording ARSJPA quand sourcé ?

Angle : MOBILE

Persona

Source : site-context.yaml voice_and_tone.persona_primary = "Parieur sportif en Guinee, tres majoritairement mobile, interesse par le football en priorite".

  • sport-home : parieur GN sur téléphone, intent "découvrir l'offre du jour, choisir une compétition". Le layout desktop observé montre une nav horizontale avec 7 onglets primaires (Sports / Virtuel / Promo / Casino + sous-tabs PREMATCH / LIVE / MULTIBET / EVENEMENTS / MULTILIVE / CALENDRIER). À 390px de large, cette densité d'onglets ne tient pas sans hamburger ou collapse non observable ici.
  • sport : même persona, intent "construire un pari combiné sur une compétition". Le layout desktop est 3 colonnes (rail gauche sports, centre matchs, rail droit "Ticket" 244px). À 390px, ce layout 3 colonnes ne tient pas ; la stratégie d'adaptation (stacking, tabs, drawer "Ticket") n'est pas observable depuis le crawl desktop.
  • casino : persona élargie joueur casino. Carrousels de jeux multiples avec flèches de scroll horizontal. Sur mobile, les flèches sont théoriquement remplacées par swipe natif, mais le meta-viewport injecté dynamiquement par le widget casino bloque le zoom (cf F-MOBILE-01-01), ce qui contredit la posture mobile-first attendue. Route YMYL sensible : la dégradation mobile augmente la friction d'accès aux conditions de jeu.
  • promotions : persona en intent "découvrir un bonus avant inscription". 3 CTAs détectés desktop dont le sélecteur de langue (FR 50x16). Le rendu mobile des visuels bonus (carrousels) n'est pas observable. La conformité YMYL (lisibilité des conditions de wagering sur petit écran) est non instruisable ici.

Synthèse exécutive

  • Inputs mobile primaires absents : 0 screenshot mobile, 0 axe mobile run, 0 mesure CrUX form_factor=PHONE sur les 4 routes. Source : axe-results/index.jsonresults[].mobile.path = None pour les 4 routes ; results[].mobile.passes_count = 0. La persona étant majoritairement mobile (cf site-context.yaml), c'est un gap critique pour un audit produit livré.
  • Viewport meta cassé sur /casino uniquement : un second tag <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1"> est injecté dans le DOM rendu (probablement par le SDK casino), bloquant le zoom mobile. Source : axe-results/casino/desktop.jsonviolations[].id = "meta-viewport", failureSummary = "maximum-scale on <meta> tag disables zooming on mobile devices". WCAG 1.4.4 AA (Resize text) non respectée sur /casino.
  • Touch targets desktop sous le seuil 44x44 WCAG 2.5.5 AA : 22 CTAs sur 60 ont une dimension < 44px sur au moins un axe (height ou width), dont 7 "JOUER" 80x22 sur /casino (height 22 = 50 % du seuil) et 8 boutons de carrousel 32x32. Source : conversion-signals/casino.jsondetailed.ctas[4..10].bbox.height = 22, detailed.ctas[0..3,11..12].bbox = 32x32. Probabilité de fail mobile élevée vu que la dégradation rarement améliore les tailles. Indication indirecte, pas mesure mobile.
  • Aucun pattern responsive moderne détecté dans le HTML serveur : 0 @media, 0 srcset, 0 sizes, 0 loading="lazy", 0 inputmode détectés sur les 4 raw HTML. Source : grep multi-fichiers sur seo-audit/.../crawl/html/{sport-home,sport,casino,promotions}.raw.html. Le CSS chargé est /css/desktop/... (cf axe-results/sport-home/desktop.json → raw HTML L36-37). Cela suggère une stratégie UA-sniffing côté serveur avec un sous-dossier /css/mobile/... séparé, plutôt qu'un responsive design CSS unifié. Non vérifiable sans crawl mobile UA.
  • 0 forms détectés sur les 4 routes : conversion-signals/index.jsonaggregate.forms_total_all_routes = 0. Les pages inscription / login / dépôt ne sont pas dans le scope POC, donc impossible d'évaluer les patterns mobile critiques (<input type="tel">, inputmode="numeric", autocomplete="tel-national"). Bloquant pour évaluer le funnel de conversion mobile.

Findings

F-MOBILE-01-01 : Viewport meta /casino bloque le zoom mobile (maximum-scale=1)

  • Sévérité : serious
  • Route(s) : casino
  • Source primaire :
  • axe-results/casino/desktop.jsonviolations[].id = "meta-viewport", impact = "moderate", nodes[0].html = "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1\">", nodes[0].any[0].message = "maximum-scale on <meta> tag disables zooming on mobile devices", nodes[0].target = ["meta[name=\"viewport\"]:nth-child(118)"]
  • Raw HTML seo-audit/.../bet224/crawl/html/casino.raw.html L23 : <meta name="viewport" content="width=device-width, initial-scale=1"> (un seul viewport meta côté serveur, conforme). Le second meta avec maximum-scale=1 est injecté côté client par le SDK casino (cf selector :nth-child(118) indique une position tardive dans <head>).
  • Pattern absent sur les 3 autres routes : sport-home, sport, promotions n'ont pas meta-viewport dans leurs violations axe.
  • Source visuelle : - screenshots/casino/desktop.png : capture desktop seulement, pas de visualisation possible du blocage zoom mobile.
  • Constat :

Le SDK casino injecte un second <meta name="viewport"> avec maximum-scale=1, minimum-scale=1 qui désactive le zoom utilisateur sur mobile. Le viewport serveur initial (L23 raw HTML) est correct. Le tag dupliqué prend précédence (dernier déclaré gagne) ; un parieur GN mobile sur /casino ne peut donc pas zoomer pour lire un libellé de jeu ou les conditions affichées en petit corps.

  • Impact attendu :

WCAG 1.4.4 (Resize text) niveau AA non respectée sur /casino. Pour un parieur avec baisse d'acuité visuelle (presbytie courante > 45 ans, audience parieurs adultes), la fonction zoom navigateur native est bloquée. Sur route YMYL avec libellés de jeu et conditions affichés en corps réduit, c'est un signal de dégradation produit. Effet collatéral : iOS Safari force le zoom au focus d'un input < 16px font-size si maximum-scale=1 absent ; en bloquant le zoom on prévient AUSSI ce zoom-au-focus, ce qui peut être intentionnel côté SDK casino (jamais bonne pratique pour autant).

  • Root cause :

SDK casino tiers injecte un viewport meta dans le DOM rendu sans tenir compte du viewport déjà déclaré par le template hôte. Fix : (1) intercepter l'injection si l'éditeur du SDK l'expose en config, (2) sinon override post-injection par un MutationObserver qui retire maximum-scale=1 du tag dupliqué, (3) escalader chez l'éditeur du SDK.

F-MOBILE-01-02 : 17+ touch targets desktop sous le seuil WCAG 2.5.5 AA (44x44px)

  • Sévérité : serious
  • Route(s) : sport-home, sport, casino, promotions
  • Source primaire :
  • conversion-signals/casino.jsondetailed.ctas :
  • Indices 0-3, 11-12 : 6 boutons carrousel à bbox = {width: 32, height: 32} aux y=191, 373, 604 (les flèches de scroll horizontal des sections "Gains récents", "Spribe Games", "Top 10")
  • Indices 4-10, 13-14 : 9 boutons "JOUER" à bbox = {width: 80, height: 22} (height = 50 % du seuil)
  • conversion-signals/sport-home.jsondetailed.ctas :
  • Index 2 : CTA sans texte bbox = {width: 50, height: 15} y=7 (probablement bouton barre cookies)
  • Index 3 : sélecteur "FR" bbox = {width: 45, height: 16} y=80 (height = 36 % du seuil)
  • Indices 0, 1 : onglets "Football" 101x42, "Basketball" 118x42 (height 42 < 44, fail marginal)
  • conversion-signals/sport.jsondetailed.ctas[1] : "FR" 45x16 + [6] "OUVRIR PIED DE PAGE" 152x25
  • conversion-signals/promotions.jsondetailed.ctas[0..2] : 3 CTAs dont sélecteur cookies, "FR", footer toggle, tous height ≤ 39px
  • Source visuelle : - screenshots/casino/desktop.png : carrousels visibles avec flèches noires en haut à droite de chaque rangée (zone ~x=1356-1428, y=191 / 373 / 604) ; boutons "JOUER" non visibles sur la capture (état hover sur survol vignette, déclenché côté JS).
  • screenshots/sport-home/desktop.png : sélecteur "FR" visible top-droit (zone ~x=1377, y=80), onglets "Football / Basketball" à y=396.
  • Constat :

Sur la mesure desktop (viewport 1366x900), au moins 17 CTAs ont au minimum une dimension < 44px : tous les boutons "JOUER" du casino (80x22), toutes les flèches de scroll horizontal (32x32), les sélecteurs cookies/FR (≤ 16px de haut). WCAG 2.5.5 (Target Size) AA exige 44x44 minimum sauf cas d'exception (essential, inline, ou user-agent control). Sur mobile, la dégradation typique soit garde les dimensions desktop si CSS non adapté (échec WCAG renforcé sur cibles tactiles), soit applique un layout mobile avec ses propres tailles non mesurées ici.

  • Impact attendu :

Friction tactile mobile élevée. Un parieur GN sur téléphone tente de taper "JOUER" sur une vignette casino : sur un index 80x22 dans le layout desktop, la cible est sous-dimensionnée et le risque de mis-tap (tap sur la vignette adjacente, ouverture d'un autre jeu, frustration) est élevé. Pour le scroll horizontal des carrousels casino, le pattern usuel mobile est swipe natif (pas de besoin de flèches 44x44), MAIS si les flèches restent rendues elles deviennent des cibles fantômes < 44px. Conformité WCAG 2.5.5 AA fail probable mais NON CONFIRMÉE faute d'axe mobile.

  • Root cause :

Design tokens basés sur des dimensions desktop pixel-perfect (32px flèches = icônes Font Awesome 5.6.3 cf raw HTML L37, 22px "JOUER" = padding réduit pour densité). Pas de variant mobile des touch zones détectable dans le CSS chargé (/css/desktop/). Fix : soit min-height: 44px sur les .componenteGioco__navigatore__tasto et les CTAs JOUER, soit ajouter un padding invisible (padding: 11px sur un container interactif) pour étendre la zone tactile sans modifier le visuel.

F-MOBILE-01-03 : Aucun pattern responsive moderne détecté dans le HTML serveur

  • Sévérité : moderate
  • Route(s) : sport-home, sport, casino, promotions
  • Source primaire :
  • Grep multi-fichiers sur les 4 raw HTML (seo-audit/.../bet224/crawl/html/{sport-home,sport,casino,promotions}.raw.html) pour les patterns : @media, srcset, sizes=, loading="lazy", inputmode → 0 occurrence cumulée sur les 4 fichiers.
  • Raw HTML seo-audit/.../bet224/crawl/html/sport-home.raw.html L36 : <link rel="stylesheet" href="/css/desktop/third-party/bootstrap.min.css?v=20260304016"> (chemin contient /desktop/).
  • Raw HTML idem L37 : <link rel="stylesheet" href="/css/desktop/third-party/fontawesome-5.6.3/css/all.min.css?v=20260304016">.
  • Raw HTML idem L139 : <link rel="stylesheet" href="/css/desktop/base.jsp?v=20260304016"> (fichier serveur JSP, donc dynamique côté backend).
  • index.json crawl → viewport: {width: 1366, height: 900}, user_agent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) ... Chrome/148.0.0.0 ..." : crawl effectué en UA desktop, le serveur a donc renvoyé la version desktop. Pas de crawl en UA mobile pour vérifier si /css/mobile/... existe.
  • Source visuelle : - N/A (constat structurel HTML, pas visuel).
  • Constat :

Les 4 pages servies en UA desktop ne contiennent aucun media query inline, aucun srcset / sizes sur les images, aucun loading="lazy", et chargent du CSS via /css/desktop/.... Le stylesheet base.jsp est dynamique serveur (JSP). Forte présomption d'une architecture UA-sniffing serveur (le backend détecte le UA et renvoie un layout HTML/CSS desktop ou mobile distinct), pas d'un responsive design unifié. Cette présomption N'EST PAS CONFIRMÉE faute de crawl avec UA mobile.

  • Impact attendu :

Une architecture UA-sniffing produit typiquement deux codebases à maintenir, deux états visuels distincts, et un risque élevé de divergence (le fix viewport /casino ne s'applique peut-être qu'au layout desktop, le mobile pourrait être OK ou pire). SEO impact : Google recommande le responsive design depuis 2015 comme bonne pratique mobile-first indexing. Conversion impact : les bookmaker leaders (Bet365, William Hill, Betfair) sont passés au responsive depuis 2018-2020.

  • Root cause :

Plateforme historique (probablement Microgame / Playtech / IGT-style legacy iGaming platform) avec backend JSP rendant deux templates distincts selon UA. Fix : à arbitrer entre (1) migration responsive design (réécriture majeure), (2) maintenance du UA-sniffing avec audit mobile dédié (palliative), (3) recapture POC en V2 audit pour décider sur base mesurée.

F-MOBILE-01-04 : Forms inscription / login / dépôt absents du scope POC, parcours conversion mobile non instruisable

  • Sévérité : moderate
  • Route(s) : sport-home, sport, casino, promotions
  • Source primaire :
  • conversion-signals/index.jsonaggregate.forms_total_all_routes = 0, routes_with_forms = 0, max_form_field_count = 0
  • conversion-signals/{sport-home,sport,casino,promotions}.jsondetailed.forms = [] sur les 4 routes
  • index.json crawl → 4 routes dans pages[] : sport-home, sport, casino, promotions. Aucune route /inscription, /login, /depot, /retrait.
  • Source visuelle : - screenshots/sport-home/desktop.png : boutons "Login" rouge + "Inscription" vert visibles top-droit (zone ~x=580-720, y=40-65), liens vers les pages d'auth.
  • Constat :

Le scope POC couvre 4 routes vitrine. Aucun formulaire (inscription, login, dépôt, retrait, paramètres compte) n'est crawlé ni audité. Les évaluations mobile critiques sur les forms (<input type="tel"> pour téléphone, inputmode="numeric" pour montant, autocomplete="tel-national email new-password", taille minimum des champs 44px de haut, gestion du clavier mobile par type d'input) sont impossibles. Or, pour un parieur GN majoritairement mobile, le formulaire d'inscription est le premier point de friction critique entre acquisition et conversion.

  • Impact attendu :

Le funnel de conversion mobile (acquisition vitrine → inscription → premier dépôt → premier pari) n'est pas auditable dans le périmètre actuel. C'est la zone où les leaders iGaming investissent le plus (one-tap signup, KYC progressif, Apple Pay / Google Pay sur mobile). Sans crawl de ces pages, on ne peut pas chiffrer la friction réelle ni la dette mobile sur le funnel.

  • Root cause :

Scope POC volontairement restreint à 4 routes vitrine pour valider la méthodologie product-audit. V2 audit doit étendre le scope au funnel d'inscription minimum (acquisition + signup + login + premier dépôt), avec capture mobile (390x844 DPR=3) et axe mobile sur chaque page.

Cross-angle dependencies

  • F-MOBILE-01-01 (viewport maximum-scale=1 sur /casino) recoupe [REF: DEEP-A11Y-01/Synthèse exécutive bullet 4] (axe casino meta-viewport flag, WCAG 1.4.4 AA non respectée). La reco R-MOBILE-01-02 (override client-side) résout simultanément le finding A11Y. À fusionner par assemble_audit.py en une reco unique avec contributions cross-angle ; le porteur principal de la reco peut rester A11Y (axe est la source primaire).
  • F-MOBILE-01-02 (touch targets < 44x44) recoupe [REF: DEEP-CONV-NN/F-NN] (à confirmer post-DEEP-CONV : si DEEP-CONV identifie les boutons "JOUER" comme CTA primaire conversion, la sous-dimension est un signal conversion en plus du signal accessibilité). À fusionner par assemble_audit.py si DEEP-CONV produit un finding similaire ; sinon dépendance simple flag dans la roadmap.
  • F-MOBILE-01-03 (pas de pattern responsive moderne) recoupe [REF: DEEP-PERF-NN/F-NN] (à confirmer post-DEEP-PERF : sans srcset / sizes / loading="lazy", les images mobiles sont probablement chargées en taille desktop, dégradant LCP mobile). Cross-angle conflit potentiel : la reco R-MOBILE-01-04 (arbitrage architecture) impacte aussi PERF et SEO. Escalader au red team Coverage et UX-check pour arbitrage stratégique avant assemble final.
  • F-MOBILE-01-04 (forms hors scope) recoupe [REF: DEEP-CONV-NN/F-NN] (le funnel d'inscription/conversion est par définition l'angle CONV). Si DEEP-CONV-01 produit déjà un finding sur l'absence de forms crawlés, fusionner. Sinon DEEP-MOBILE-01 et DEEP-CONV-01 portent tous les deux la reco étendre le scope V2.

Limites

Cette section est volontairement détaillée. Le POC product-audit bet224 est largement dégradé sur l'angle MOBILE et l'honnêteté radicale sur les inputs manquants est prioritaire sur la complétude apparente des findings.

Inputs primaires mobile NON CAPTURÉS dans le POC :

  1. Screenshots mobile (390x844, DPR=3, format PNG 1170x2532) : aucun fichier screenshots/<slug>/mobile.png n'existe sur les 4 routes. Source : axe-results/index.jsonviewport_mobile est déclaré mais results[].mobile.path = None partout. Sans capture mobile, aucune évaluation visuelle de l'overflow horizontal, du hamburger menu, du sticky CTA mobile, des modales mobile, du carrousel swipe, n'est possible. Tous les findings UX/UI mobile sont inférés depuis le desktop ou non instruisables.
  1. Axe-core run mobile : axe-results/<slug>/mobile.json absent sur les 4 routes. La règle target-size (WCAG 2.5.5 AA, mesure des touch targets) est précisément faite pour le mobile et n'a pas été exécutée. Les violations potentielles (overflow, sticky issues, mobile-specific rules) sont non mesurées.
  1. CrUX (Chrome User Experience Report) form_factor=PHONE : crux.json absent. Sans données terrain mobile, le score Core Web Vitals mobile (LCP p75, INP p75, CLS p75) est inconnu. Le index.json du crawl donne des métriques desktop synthétiques (TTFB 96-138ms, DCL 273-466ms, load_event 276-488ms) qui ne sont pas représentatives du mobile (réseau 4G/3G Guinée vraisemblablement plus lent).
  1. : non généré (schemas_versions.signals: "not_run"). Champs critiques mobile non extraits : viewport_meta (valeur exacte), touch_targets (count mesuré côté serveur), responsive_images (count d'images avec srcset), mobile_specific_links (présence d'un éventuel lien vers m.bet224.gn si UA-sniffing).
  1. Crawl en UA mobile (User-Agent iPhone Safari iOS 17) : index.json du crawl atteste UA desktop Chrome Windows. Aucune passe en UA mobile. Si le backend fait UA-sniffing, il a renvoyé sa version desktop uniquement. L'architecture mobile réelle (responsive, UA-sniffing serveur, ou m.bet224.gn distinct) ne peut être confirmée.

Patterns mobile NON OBSERVABLES depuis les inputs disponibles :

  • Hamburger menu : présence, position (header / fixed bottom), animation d'ouverture, focus trap.
  • Sticky bottom CTA (pattern courant iGaming mobile) : présence, comportement au scroll, masquage / réapparition.
  • Modales et bottom sheets : design, gestion du fond, focus return.
  • Carrousels swipe natif : présence, indicateurs de progression, gestion gestures.
  • Pull-to-refresh : présence (anti-pattern sur certaines apps web bookmaker), comportement.
  • Notifications push web : sollicitation au load (anti-pattern), demande de permission contextualisée.
  • Cookie banner mobile : taille relative écran, modalité de refus (1-tap vs cascade).
  • Age-gate mobile (YMYL gambling) : présence, ergonomie, blocage avant catalogue.

Inférences indirectes (à confirmer en V2 audit) :

  • Architecture UA-sniffing présumée (cf F-MOBILE-01-03) : à confirmer par crawl mobile UA.
  • Touch targets mobile < 44x44 (cf F-MOBILE-01-02) : projection depuis desktop, à confirmer par axe mobile sur viewport 390x844.
  • Performance mobile dégradée vs desktop : présumée vu absence de loading="lazy" et de srcset, à confirmer par CrUX form_factor=PHONE ou PageSpeed Insights strategy mobile.
  • Forms inscription / login / dépôt mobile : 0 form auditable dans le scope POC (4 routes vitrine), parcours conversion mobile entièrement non instruit.

Sub-agent à re-lancer : DEEP-MOBILE-02 en V2 audit après recapture mobile complète (R-MOBILE-01-01 livrable). DEEP-MOBILE-01 (ce document) reste valable comme baseline d'inventaire des manques.

Angle : PERF

Persona

Source : site-context.yaml voice_and_tone.persona_primary = "Parieur sportif en Guinée, très majoritairement mobile, intéressé par le football en priorité".

  • sport-home : parieur arrive depuis une recherche, un lien externe, ou la racine. Premier contact visuel avec la marque, doit voir l'offre du jour vite. Sur un réseau 4G guinéen avec latence backbone Europe→Guinée (RTT typique > 200 ms à Conakry vers une infra EU), le coût des stylesheets render-blocking et de jQuery synchrone en <head> est multiplié par RTT × nombre de roundtrips. C'est précisément la route où une seconde de plus tue la conversion.
  • sport : persona en intent "construction d'un pari" sur une compétition. Page la plus lourde fonctionnellement (605 mots vs 221 sur sport-home, widget Betbuilder, accordion compétitions). Avec un load_event mesuré à 470 ms en local, le facteur multiplicateur en field mobile Guinée doit être appliqué (cf Limites).
  • casino : route YMYL secondaire, contenu visuel chargé (5 carrousels de jeux, full-page 1629 px = 1,8× plus haut que les autres). Risque CLS élevé en field (carrousels images sans dimensions, chargement Spribe / Evolution iframes potentielles), risque INP élevé (boutons de carrousel sans aria-label ET sans listeners optimisés cf F-A11Y-01-03).
  • promotions : route d'acquisition pré-inscription. Le visiteur doit voir les 5 visuels promotionnels (bonus 500 %, cashback, welcome) rapidement pour évaluer l'offre. Aujourd'hui, ces visuels sont des <img> sans loading="lazy" ni width/height ni srcset, ce qui multiplie le risque LCP tardif + CLS au moment où le visiteur tente de cliquer un bonus.

Synthèse exécutive

  • Timings réseau crawler (Chromium desktop, IP non-Guinée, pas de throttling) : load_event entre 275 ms (casino) et 488 ms (promotions). TTFB entre 96 ms (sport-home) et 138 ms (sport). Source : crawl/index.jsonpages[].ttfb_ms, dcl_ms, load_event_ms. Ces valeurs sont lab-en-local, à NE PAS confondre avec ce que vit le persona mobile Guinée. Aucune projection field n'est possible sans CrUX.
  • 5 stylesheets bloquants en <head> + 1 conditionnel (dark mode) + 1 tardif (toast.css), sans preload ni media partitionné. Mesuré : sport-home.raw.html lignes 36, 37, 139, 140, 141, 144, 866. Pattern identique sur les 4 routes (template commun). Chaque CSS bloque le first paint jusqu'à téléchargement + parse.
  • 7 scripts JS chargés SYNCHRONE en <head> (jQuery 3.7.1, contogioco-services, gsap, sweetalert2, jsCookie + 2 conditionnels IE legacy), un seul script avec defer (third-party.jsp). Mesuré : sport-home.raw.html lignes 145-154. jQuery 3.7.1 minified pèse [À VÉRIFIER : ~85 KB] non compressé ; les 5 libs synchrones additionnées sont une cause racine plausible d'un FCP / LCP dégradé en mobile.
  • GTM injecté en script inline en <head> ligne 8-12 (avant tout meta-viewport et avant le <title>). En state-of-the-art 2026, GTM se charge en <head> mais ne devrait pas précéder les meta critiques. Le snippet gtag.js est correctement async (ligne 15) mais sa consommation gtag('config', ...) inline ligne 16-21 ré-exécute du JS bloquant.
  • 4 <img> par route, AUCUNE avec loading="lazy" ni width/height ni srcset / <picture>. Mesuré : sport-home.raw.html lignes 362, 389, 453, 458 (img src= sans aucun de ces attributs). Conséquence directe : risque CLS structurel + sur-téléchargement above-the-fold + pas de variante mobile servie au persona mobile.
  • Aucun <link rel="preconnect"> ni dns-prefetch ni preload sur les origines critiques (www.googletagmanager.com, polices, CSS first-party). Mesuré : grep preload|preconnect|dns-prefetch sur sport-home.raw.html = 0 occurrence. Connexion TLS au CDN Google + tag manager faite en série, pas en parallèle.
  • Casino full-page = 1629 px (vs 900 sur les 3 autres routes), screenshot PNG = 1063 KB. Source : screenshots/index.jsoncaptures[2].desktop_full_height_px = 1629. Indicateur de poids visuel : la page rend ~1,8× plus de contenu visible, ce qui implique probablement davantage d'images casino + carrousels au-dessus du fold et juste en dessous.

Findings

F-PERF-01-02 : 7 scripts JS synchrones en <head> (jQuery, GSAP, SweetAlert, contogioco-services, jsCookie)

  • Sévérité : critical
  • Route(s) : sport-home, sport, casino, promotions
  • Source primaire :
  • raw_html_sport_home lignes 145-154 (idem casino, sport, promotions, c'est un template) :
  • <script src="/js/desktop/third-party/html5shiv-3.7.3.min.js?v=20260304016"> (conditionnel IE, mais présent en commentaire <!--[if IE]> qui n'est plus interprété en HTML5 / browsers modernes, donc le tag n'est pas chargé ; à vérifier en lab)
  • <script src="/js/desktop/third-party/jquery-3.7.1.min.js"> synchrone
  • <script src="/js/contogioco-services.js"> synchrone
  • <script src="/js/gsap.min.js"> synchrone
  • <script src="/js/sweetalert2.min.js"> synchrone
  • <script src="/js/jsCookie.min.js"> synchrone
  • <script defer src="/js/desktop/third-party.jsp"> (seul script defer)
  • Pattern identique sur les 4 routes (template commun).
  • Source visuelle : - Non applicable directement.
  • Constat :

Cinq libraries JS first-party / vendor sont chargées synchrones en <head>, donc chaque téléchargement + parse + exécution bloque le DOMContentLoaded. Aucune de ces libs n'est requise pour le first paint (jQuery, GSAP, SweetAlert, jsCookie sont des utilities runtime). Le seul script avec defer est third-party.jsp qui paradoxalement est probablement le moins critique pour FCP.

  • Impact attendu :

Mesuré localement : DCL entre 273 ms (casino) et 466 ms (promotions). En field mobile Guinée, le facteur multiplicateur attendu sur ces libs synchrones est important (parse JS sur CPU mid-range, latence d'attente sur chaque tag). Estimation prudente : DCL field mobile probable entre 1,5 s et 4 s sur 4G médian (non vérifié, à valider via CrUX). Conséquence : TTI dégradé, INP probablement médiocre (jQuery + GSAP réveillés à chaque interaction).

  • Root cause :

Template historique (probablement migré depuis IE-supporting era, cf html5shiv et respond.js legacy IE polyfills toujours présents). Aucune passe d'optimisation perf moderne (defer / async / module split / dynamic import) appliquée.

F-PERF-01-01 : 5 à 7 stylesheets render-blocking en <head> sur les 4 routes

  • Sévérité : serious
  • Route(s) : sport-home, sport, casino, promotions
  • Source primaire :
  • raw_html_sport_home lignes 36-37, 139-144 : 6 <link rel="stylesheet"> chargés sans media partitionné ni preload. Listing : bootstrap.min.css, fontawesome-5.6.3/css/all.min.css, base.jsp, default_contogioco_desktop.css, adeguamento.css, adeguamento_dark.css (disabled mais déclaré).
  • raw_html_sport_home ligne 866 : 7e stylesheet toast.css chargé dans le body (donc bloquant l'idle de la page).
  • Pattern identique sur raw_html_casino lignes 37-38, 140-144, 910 (idem) ; raw_html_sport ; raw_html_promotions.
  • Source visuelle : - Non applicable directement (effet sur FCP / LCP, non visible sur screenshot statique).
  • Constat :

6 à 7 feuilles de style bloquent le rendu sur chaque route, dont 4 servies depuis le même domaine first-party (économie de connexions limitée mais coût de téléchargement linéaire) et 2 sur des chemins external_css/... qui suggèrent un CMS legacy (SPORTCASH, GUINEA). Une seule de ces feuilles (adeguamento.css) est sur HTTPS absolu, les autres sont en relatif. Aucune ne porte media="print" ni disabled (sauf adeguamento_dark.css).

  • Impact attendu :

Sur un réseau 4G guinéen avec RTT typique > 200 ms vers une infra EU, 7 roundtrips série pour CSS first-party = pénalité estimée de plusieurs centaines de ms sur le FCP. Aucune mesure CrUX disponible pour le quantifier précisément. Conséquence indirecte : LCP dégradé, perte de conversion sur les CTAs "Inscription" et "Dépôt" (above-the-fold sur sport-home selon screenshot).

  • Root cause :

Architecture CMS Italien legacy ("contogioco" = compte de jeu en italien, "componenteGioco" partout dans le DOM) avec multi-tenant par marché (GUINEA, IVORY_COAST, SPORTCASH...). Chaque tenant ajoute sa feuille adeguamento.css au-dessus du noyau Bootstrap + FontAwesome + base. Refactor difficile sans casser le multi-tenant.

F-PERF-01-03 : 4 images par route sans loading="lazy", sans width/height, sans srcset

  • Sévérité : serious
  • Route(s) : sport-home, sport, casino, promotions
  • Source primaire :
  • raw_html_sport_home :
  • Ligne 362 : <img src="https://www.bet224.gn/external_cms/GUINEA/img/logo-bet-224.png"> (logo header, sans attributs perf)
  • Ligne 389 : <img src="https://www.bet224.gn/external_css/GUINEA/img/ARSJPA.png"> (logo régulateur)
  • Ligne 453 : <img src="/images/desktop/fr.png" class="flag-lang" /> (drapeau langue FR)
  • Ligne 458 : <img src="/images/desktop/en.png" class="flag-lang" /> (drapeau langue EN)
  • Grep loading="lazy" sur les 4 raw HTML : 0 occurrence (4 fichiers, count = 0).
  • Grep width= ou height= sur les <img> : 0 occurrence.
  • Le brief mentionne 5 visuels promotionnels sur promotions (bonus 500 %, cashback, welcome) qui devraient apparaître comme <img> ou background-image ; mesuré uniquement 4 <img> ce qui suggère que les visuels promo sont chargés dynamiquement après render (JS), donc encore plus tardifs.
  • Source visuelle : - screenshots/casino/desktop.png : 5 carrousels de jeux avec ~12 vignettes visibles each au-dessus du fold = ~60 images casino non instrumentées performance.
  • screenshots/promotions/desktop.png : 4 visuels bannière promo confirmés (zone ~y=200 à y=900).
  • Constat :

Toutes les <img> détectées dans le raw HTML sont chargées eagerly, sans dimensions intrinsèques déclarées, sans variantes responsive. Les visuels casino et promotions ne sont pas dans le raw HTML du tout = soit chargés post-render JS (perf encore pire), soit background-image CSS (non détecté lazy-loadable). Le logo header est servi depuis un chemin absolu external_cms/GUINEA/img/logo-bet-224.png PNG (probablement pas optimisé WebP / AVIF).

  • Impact attendu :
  • CLS : risque structurel car aucune image n'a de dimensions déclarées. Réseau lent = image arrive après le premier render = layout shift à chaque image qui se charge. Quantifier nécessite CrUX (non disponible).
  • Root cause :

Markup template qui ne respecte aucune des best practices <img> 2026 (WCAG 2.1 + Web Vitals + responsive). Aucune passe d'optimisation image n'a été appliquée. Convergence avec finding A11Y F-A11Y-01-01 (logo sans alt) : la même refonte template doit fixer alt + dimensions + lazy + srcset.

F-PERF-01-04 : Aucun preconnect ni dns-prefetch ni preload sur les origines critiques

  • Sévérité : moderate
  • Route(s) : sport-home, sport, casino, promotions
  • Source primaire :
  • Grep preload|preconnect|dns-prefetch sur raw_html_sport_home : 0 occurrence.
  • Pattern identique sur les 4 routes.
  • Origines tierces utilisées en runtime : www.googletagmanager.com (ligne 15 gtag.js), www.bet224.gn/external_cms/GUINEA/... (chemin alternatif sous-domaine implicite). Aucune n'est préconnectée.
  • Source visuelle : - Non applicable.
  • Constat :

Le client charge GTM, gtag, et plusieurs ressources CSS sous des chemins absolus distincts (https://www.bet224.gn/external_css/GUINEA/...), mais ne fait aucune optimisation TCP / TLS préventive. Chaque origine externe paie une connexion complète (DNS + TCP + TLS) à la demande, en série.

  • Impact attendu :

Pénalité estimée de 100 à 300 ms par origine sur un RTT 200 ms (1 DNS + 1 TCP + 2 TLS roundtrips = ~600 ms si non préconnecté, vs ~0 si preconnect dès le <head>). Pas critique en lab local, sensible en field Guinée. À quantifier précisément via PSI Network panel (non fetché).

  • Root cause :

Optimisation manquée, pas un défaut architectural. Fix simple : ajouter 2-3 <link rel="preconnect"> en tête de <head>.

F-PERF-01-05 : Routes ont des full-page heights très hétérogènes (900 px à 1629 px), casino 1,8× plus haut

  • Sévérité : moderate
  • Route(s) : casino, sport-home, sport, promotions
  • Source primaire :
  • screenshots/index.jsoncaptures[].desktop_full_height_px :
  • sport-home = 900
  • sport = 900
  • casino = 1629
  • promotions = 950
  • Taille screenshot PNG full-page (proxy poids visuel) : casino = 1063 KB, sport = 477 KB, sport-home = 202 KB, promotions = 174 KB. Source : Get-ChildItem sur le dossier screenshots/<route>/desktop.png.
  • Source visuelle : - screenshots/casino/desktop.png : 5 carrousels empilés verticalement + section providers + bannière, total 1629 px de scroll.
  • screenshots/sport-home/desktop.png : tabs + grille de top compétitions, 900 px (fold + 1 écran).
  • Constat :

Casino est nettement plus haut que les autres routes et son screenshot full-page est ~5× plus lourd en KB. Cela indique densité visuelle élevée : carrousels images + vignettes de jeux + branding providers (Evolution, Spribe, Amigo Gaming, Pragmatic). Sans dimensions sur les images (F-PERF-01-03), cette densité = risque CLS structurel élevé sur casino.

  • Impact attendu :

Sur casino, la combinaison "5+ carrousels images + 0 dimension déclarée + 0 lazy + connexion lente" projette un scénario field où le visiteur voit le contenu se réorganiser pendant plusieurs secondes. INP probablement dégradé par les listeners de carrousels (8 boutons cf F-A11Y-01-03, plus probablement des handlers Swiper / GSAP). LCP candidate = première vignette d'image visible.

  • Root cause :

Choix produit (multi-carrousels providers) compatible avec un marché casino concurrentiel, mais sans la couche perf qui devrait accompagner (lazy carrousel offscreen, virtualisation, image dimensions, preload du LCP candidat).

F-PERF-01-06 : GTM en script inline en <head> avant <meta viewport> et <title>

  • Sévérité : minor
  • Route(s) : sport-home, sport, casino, promotions
  • Source primaire :
  • raw_html_sport_home lignes 7-13 : bloc GTM inline (IIFE (function(w,d,s,l,i){...})) placé AVANT <meta name="viewport"> (ligne 22) et AVANT <title> (ligne 23).
  • Ligne 15 : <script async src="https://www.googletagmanager.com/gtag/js?id=G-VLQSP6C303"> (correctement async).
  • Lignes 16-21 : config gtag inline (gtag('config', 'G-VLQSP6C303', ...)).
  • Pattern identique sur les 4 routes.
  • Source visuelle : - Non applicable.
  • Constat :

GTM est chargé en script inline async (correct), mais le bloc précède toutes les meta critiques pour le navigateur. Conséquence mineure mais réelle : le navigateur retarde l'interprétation des hints viewport (utilisé pour calcul layout mobile) et title (utilisé pour onglet) jusqu'après le parse du bloc GTM.

  • Impact attendu :

Sub-100 ms en lab, mais cumulé avec les autres findings = signal de qualité d'intégration analytics. Pas un blocker isolé.

  • Root cause :

Snippet GTM copié-collé "as-is" depuis l'assistant GTM. Ordre <head> non audité.

F-PERF-01-07 : Inline CSS contient 7 background-image: url() !important vides (assets cassés ou volontairement vides ?)

  • Sévérité : minor
  • Route(s) : sport-home, sport, casino, promotions
  • Source primaire :
  • raw_html_sport_home lignes 46-72 : 8 occurrences de background-image: url() !important; dans un <style> inline en <head>. Cibles : .landing-2::before, .cg-landing-background, .promozioni-sfondo::before, .poker-landing::before, .azione-poker.cg-download-client, .azione-poker.cg-gioca-ora, body[page="cards"] .casino. Toutes avec URL VIDE.
  • Pattern identique sur les 4 routes.
  • Source visuelle : - Non applicable directement (effet indirect : si ces classes étaient activées par le CMS, le placeholder est cassé).
  • Constat :

Le CMS injecte du CSS inline avec des background-image: url() vides, probablement à cause d'un placeholder de template (Velocity/JSP/Freemarker ${variable} non résolu = chaîne vide). Bug fonctionnel : si une de ces classes est appliquée dynamiquement, le background sera vide au lieu de l'asset attendu. Effet perf : nul direct (les URLs vides ne déclenchent pas de requête), mais signal d'un template defectueux.

  • Impact attendu :
  • Perf : 0 ms (les url() vides ne génèrent pas de fetch).
  • Régression visuelle potentielle : si une promo poker / landing est activée serveur, l'image manque.
  • Qualité produit : indicateur d'une chaîne de build CSS instable.
  • Root cause :

Template CMS Java/JSP (visible aussi dans base.jsp, third-party.jsp, default_contogioco_desktop.css.jsp) qui ne nettoie pas ses placeholders en sortie.

Cross-angle dependencies

  • MOBILE (DEEP-MOBILE-01, à venir) : la performance perçue par le persona mobile Guinée est l'enjeu central de cet audit. Tous les findings PERF s'amplifient en mobile : F-PERF-01-01 (CSS render-blocking × RTT mobile élevé), F-PERF-01-02 (JS sync × CPU mid-range), F-PERF-01-03 (images sans srcset × bande passante limitée). DEEP-MOBILE-01 doit nécessairement croiser avec DEEP-PERF-02 (post-CrUX) pour quantifier le delta mobile vs desktop. Reco partagée probable : R-PERF-01-03 (images responsive) résout aussi un finding mobile attendu sur "images servies en taille desktop sur mobile".
  • A11Y (DEEP-A11Y-01) : F-PERF-01-03 (images sans dimensions ni lazy) recoupe F-A11Y-01-01 (logo header sans alt) sur le même <img> ligne 362. La refonte du template <img> doit fixer SIMULTANÉMENT : alt (a11y), width/height (perf CLS), loading="lazy" (perf bande passante), fetchpriority (perf LCP). À fusionner en une seule reco template par assemble_audit.py (cf R-PERF-01-03 copy-ready qui inclut déjà l'attribut alt).
  • SEO (DEEP-SEO-01, à venir) : Core Web Vitals (LCP / INP / CLS) sont un signal de ranking Google confirmé depuis 2021 (Page Experience Update) + signal de qualité utilisé par les LLMs pour évaluer la fiabilité d'une source (Perplexity, ChatGPT browsing). Un site lent et instable visuellement est moins cité. DEEP-SEO-01 doit citer DEEP-PERF-02 (post-CrUX) pour quantifier l'impact ranking.
  • UI (DEEP-UI-01, à venir) : F-PERF-01-05 (casino full-page 1629 px, 1063 KB) interroge le choix UI multi-carrousels. Décision design (densité visuelle vs perf) à arbitrer avec UI-check du red team.
  • TRUST (DEEP-TRUST-01, à venir) : aucune dépendance perf directe identifiée. Note : un site lent dégrade implicitement la perception de fiabilité, surtout en YMYL gambling où la confiance est primordiale.

Limites

  • CrUX (Chrome UX Report) NON FETCHÉ : aucune mesure de vrais users 28j pour LCP / INP / CLS p75 par route × form_factor. Conséquence : aucun chiffre Core Web Vitals ne peut être affirmé dans cet audit. La cause = variable d'env CRUX_API_KEY absente lors du run. Reco R-PERF-01-01 traite ce point en V2. Sans CrUX, l'analyse PERF est qualitative (root cause depuis markup), pas quantitative.
  • PageSpeed Insights (Lighthouse lab) NON FETCHÉ : aucun diagnostic Lighthouse (LCP element identifié, render-blocking savings quantifiés, opportunités scorées, image-delivery insights, JS execution time). Conséquence : impossible de prouver précisément que tel script bloque le LCP de tant de ms. Cause = PSI_API_KEY absente. Reco R-PERF-01-01 traite aussi ce point.
  • Pas de mesure CLS ni INP : ni en lab (pas de Lighthouse) ni en field (pas de CrUX). Les findings F-PERF-01-03 (images sans dimensions) et F-PERF-01-05 (casino multi-carrousels) projettent un risque CLS / INP fort sur la base du markup, mais ne le mesurent pas. À quantifier en V2.
  • Performance mobile non mesurée : POC desktop only. Aucun screenshot mobile (captures[].mobile_path = null dans screenshots/index.json). Aucun axe mobile. Aucun CrUX mobile. C'est le déficit le plus critique de cet audit car le persona primaire est mobile. À étendre en V2 (capture screenshots mobile + axe mobile + CrUX form_factor=PHONE).
  • Timings réseau biaisés par la géographie du crawler : timings TTFB / DCL / load_event mesurés depuis Chromium headless sur IP probablement européenne (à confirmer via crawl/index.json qui ne stocke pas l'IP source). Le visiteur réel à Conakry paie une latence backbone EU↔Guinée typiquement > 200 ms RTT, soit un facteur multiplicateur 3-10× sur le load_event mesuré. Aucun throttling appliqué non plus (CPU et bande passante = capacité crawler). Les timings ci-dessus sont des PLANCHERS, jamais des projections field.
  • Tailles d'assets non mesurées : le crawl raw n'a téléchargé que les HTML, pas les CSS / JS / images. Les estimations de poids JS / CSS (ex : "jQuery 3.7.1 ~85 KB") sont basées sur connaissance générale, taggées [À VÉRIFIER], à confirmer en V2 via PSI Network panel ou curl -I sur les URLs absolues.
  • HTTP/2 / HTTP/3 status non vérifié : la pertinence de R-PERF-01-05 (bundling CSS) dépend du protocole HTTP. Non testé en session. À vérifier via curl -I --http2 https://www.bet224.gn/sport-home.
  • Service Worker / PWA non audité : présence d'un <link rel="manifest" href="/manifest.json"> dans le <head> ligne 28 suggère que le site déclare une PWA. Existence et configuration du Service Worker (cache strategy, prefetch, offline) non vérifiées (script SW non grepable depuis le raw HTML). Potentiel d'optimisation perf significatif si activé proprement, à instruire en V2.
  • Page-signals/<slug>.signals.json présent mais parse_status = no_html : le fichier existe ( etc.) mais has_html = false pour les 4 routes. Cf → pages[].status = "no_html". Conséquence : signals.rendering, signals.json_ld, signals.og_twitter, hints perf (lcp_element, render-blocking resources) ne sont pas disponibles. Le finding aurait été nettement plus précis avec ces signaux. À rattraper en V2 (relancer build_page_signals.py sur le crawl, sans le bug no_html).
  • Pas d'analyse du cookie banner perf : le banner cookies (visible en screenshot) est probablement injecté par JS post-load. Son impact sur INP et CLS n'est pas instruit faute de capture interactive.
  • Pas d'analyse des iframes Spribe / Evolution casino : les jeux casino sont probablement chargés en iframe tierce (Spribe Aviator, Evolution live). Leur impact perf (multi-MB par iframe potentiellement) non mesuré en session car non détectés dans le raw HTML statique (chargés post-interaction).

Angle : SEO

Persona

Source : site-context.yaml voice_and_tone.persona_primary + keywords-urls-mapping.txt.

  • sport-home : parieur sportif en Guinée, très majoritairement mobile, arrivant en intent "paris sportifs" (primary keyword mappé). La page est censée capter le trafic brand "bet224" + génériques "paris sportifs". Aujourd'hui le <title> ne mentionne ni "Bet224" comme entité claire ni "Guinée" comme cible géo-intent et la meta description évoque "Sportcash.com" qui n'est pas la brand audité, donc requête brand + générique mal servie.
  • sport : même persona, en intent "cotes" / "parier en ligne" (primary keyword mappé). Title strictement identique à sport-home (duplicate), pas de différenciation pour les SERP ni pour les LLM qui doivent distinguer "hub home" de "catalogue compétitions".
  • casino : persona élargie joueur casino. Title www.bet224.gn | Jeux Digitaux | Jeux Virtuels n'inclut ni "casino" (primary keyword mappé) ni la brand canonique "Bet224". Faux signal sémantique pour Google et pour LLM.
  • promotions : persona en intent "bonus" / "code promo bet224" (primary keyword mappé). Title est lui aussi le title générique sport-home dupliqué, donc impossible à ranker sur "bonus paris sportifs" sans réécriture.

Synthèse exécutive

  • 6 routes auditées affichent des défauts structurels SEO majeurs concentrés sur 4 axes : titles dupliqués + brand erronée, meta descriptions polluées par "Sportcash.com" (entité différente), zéro markup Schema.org JSON-LD sur 4 routes, zéro Open Graph ni Twitter Card sur 4 routes. Sources : crawl/index.json pages[].title / description / json_ld + grep raw HTML.
  • AI search readiness ≈ nulle : sans Organization JSON-LD, sans WebSite schema, sans ItemList pour le catalogue de cotes, et avec un brand string ambigu ("Sportcash.com" dans description vs "www.bet224.gn" dans title vs "Bet224" canonique site-context), un LLM cite mal ou ne cite pas. Source : crawl/index.json pages[].json_ld = [] sur les 4 routes.
  • Pollution éditoriale héritée d'un template multi-site CoreGaming (CSS external_css/SPORTCASH/, JS cg_* skinCode=SPORTCASH) : la prose meta + keywords reste celle d'un opérateur "Sportcash.com" ciblant "Ivory Coast", pas Bet224 / Guinée. Sources : raw_html_sport_home.l24, l27, l140, l241.
  • Canonical incohérent : sport-home retourne canonical vide alors que les 3 autres routes ont un canonical pleinement formé. Source : crawl/index.json pages[0].canonical = "" vs pages[1,2,3].canonical valides.
  • YMYL gambling : aucun markup structurant la nature "site de paris sportifs" (pas de @type: Organization avec legalName, pas de sameAs vers profils sociaux, pas de mention âge légal détectable en raw HTML sport-home). Pour un LLM appelé à citer une source d'autorité gambling Guinée, bet224.gn ne fournit aucun signal de confiance machine-readable. Cross-angle TRUST.

Findings

F-SEO-01-01 : Title et meta description dupliqués + brand erronée "Sportcash.com" sur 3 routes sur 4

  • Sévérité : critical
  • Route(s) : sport-home, sport, promotions
  • Source primaire :
  • crawl/index.json pages[0].title = "www.bet224.gn Guinee | Jouez en Ligne | Sport, Jeux Digitaux, Virtuel, Loto" (76 chars)
  • crawl/index.json pages[1].title = "www.bet224.gn Guinee | Jouez en Ligne | Sport, Jeux Digitaux, Virtuel, Loto" (strictement identique à pages[0])
  • crawl/index.json pages[3].title = "www.bet224.gn Guinee | Jouez en Ligne | Sport, Jeux Digitaux, Virtuel, Loto" (strictement identique à pages[0])
  • crawl/index.json pages[0].description = "Sportcash.com : sûr et fiable, les meilleures cotes de paris sportifs, le Loto et des jeux divertissants vous attendent!" (122 chars, brand "Sportcash.com" ≠ Bet224)
  • crawl/index.json pages[1].description identique à pages[0]
  • crawl/index.json pages[3].description = "Sportcash.com vous offre des Promotions et des Bonus exclusifs pour vos paris..." (brand erronée également)
  • raw_html_sport_home.l23 confirme <title> + raw_html_sport_home.l24 confirme <meta name="description">
  • Constat :

3 des 4 routes principales (sport-home, sport, promotions) ont un title strictement identique, qui ne mentionne pas la brand canonique "Bet224" mais préfixe par "www.bet224.gn", ce qui est un signal de domain-name leaking et non un title optimisé (Google tronque sur 60 chars, ici 76 chars). Les meta descriptions de ces 3 routes citent "Sportcash.com" qui est une marque différente (autre opérateur CoreGaming, cf external_css/SPORTCASH/default_contogioco_desktop.css?v=20260304016 ligne 140), donc Google ré-écrit la SERP et un LLM qui scrape cette description retourne une mauvaise attribution de marque.

  • Impact attendu :

Côté SEO : impossibilité de cibler en SERP "bet224" brand, "casino bet224", "code promo bet224", "bonus bet224" (4 keywords cibles distincts dans keywords-mapping) avec une seule formulation dupliquée. Google va déduper et n'afficher qu'une seule des 3 routes en SERP par cluster sémantique. Côté AI search : un LLM cite "Sportcash.com" comme source d'autorité paris sportifs, pas Bet224. Côté brand consistency : utilisateur en SERP qui voit "Sportcash.com" sur un domaine "bet224.gn" est désorienté (signal de site contrefait ou hacked).

  • Root cause :

Template CMS CoreGaming "skinCode=SPORTCASH" pas re-localisé pour la skin GUINEA. Les titres + meta sont des labels hérités de l'instance Sportcash (Côte d'Ivoire), pas customisés pour Bet224. Fix : reconfigurer les templates SEO par route dans le back-office CMS (modifier les <title> et <meta description> par template route).

F-SEO-01-02 : Aucun JSON-LD Schema.org sur les 4 routes (AI search non éligible)

  • Sévérité : critical
  • Route(s) : sport-home, sport, casino, promotions
  • Source primaire :
  • crawl/index.json pages[0,1,2,3].json_ld = [] (array vide sur les 4 routes)
  • Grep application/ld\+json sur les 4 raw HTML : 0 occurrence sur chaque fichier
  • Constat :

Aucune des 4 routes principales ne déclare de JSON-LD Schema.org. Il manque a minima un Organization (nom, logo, URL, sameAs vers réseaux sociaux), un WebSite (nom + searchAction si recherche interne, ce qui est le cas), et selon les routes : BreadcrumbList, ItemList pour le catalogue de cotes (sport) et de jeux (casino), Offer pour les promotions. Le brand canonical_display est "Bet224" (cf site-context.yaml) mais nulle part dans le markup il n'est exposé en machine-readable.

  • Impact attendu :

AI search : Perplexity, ChatGPT search, Gemini, Bing Copilot s'appuient massivement sur Schema.org pour extraire les entités et arbitrer entre sources concurrentes. Sans markup, bet224.gn n'est pas éligible à apparaître en answer engine (citation, knowledge panel équivalent) sur des requêtes "site de paris Guinée", "casino en ligne Guinée", "bonus paris sportifs Bet224". SEO classique : pas de rich snippets en SERP Google, donc taux de clic dégradé vs concurrents qui en exposent.

  • Root cause :

Template CMS CoreGaming n'inclut pas de JSON-LD côté serveur (rendu HTML brut sans bloc <script type="application/ld+json">). Fix : injecter au build / au render serveur 1 bloc Organization global (footer) + 1 bloc WebPage par route + spécifiques (ItemList pour catalogue, Offer/Promotion pour promotions).

F-SEO-01-03 : Open Graph et Twitter Cards absents (partage social cassé sur 4 routes)

  • Sévérité : serious
  • Route(s) : sport-home, sport, casino, promotions
  • Source primaire :
  • Grep og: sur les 4 raw HTML : 0 occurrence sur chaque fichier
  • Grep twitter: sur les 4 raw HTML : 0 occurrence sur chaque fichier
  • raw_html_sport_home.l22-28 : seul markup meta présent = viewport, description, robots, googlebot, keywords. Aucun <meta property="og:"> ni <meta name="twitter:">.
  • Constat :

Aucune des 4 routes ne déclare de tags Open Graph (og:title, og:description, og:image, og:url, og:type, og:site_name) ni de Twitter Cards (twitter:card, twitter:title, twitter:image). Un lien partagé sur Facebook, WhatsApp, X, LinkedIn, Telegram (les 3 derniers étant des canaux de croissance gambling actifs en Afrique de l'Ouest) affiche un preview cassé ou par défaut.

  • Impact attendu :

Friction de share social majeure sur l'acquisition organique virale (parieurs partageant un combiné, un bonus). Côté AI search : certains crawlers LLM (notamment Bing Copilot) lisent les og:* comme fallback quand JSON-LD est absent. Ici les deux sont absents donc double trou.

  • Root cause :

Idem F-SEO-01-02 : template CMS sans injection metadata sociale. Fix simultané possible (même back-office, mêmes variables route).

F-SEO-01-04 : Aucun markup âge légal ni mention SafeForKids (YMYL gambling)

  • Sévérité : serious
  • Route(s) : sport-home, sport, casino, promotions
  • Source primaire :
  • Grep 18 ans|joueurs majeurs|jeu responsable|interdit aux mineurs|majeur sur raw_html_sport_home.raw.html : occurrences détectées uniquement dans le bundle JS labels (var cg_LABEL ligne 250, code applicatif non exposé en contenu indexable) mais aucune balise visible dans le DOM head / body principal du shell SSR.
  • Footer du site (raw_html_sport_home.l752-816) : ne contient ni mention âge légal, ni lien "Jeu responsable", ni "Responsible Gaming", ni logo associé. Les seuls liens légaux footer sont Politique de Confidentialité et Conditions Générales pointant vers /promo/tutte/bet224_* (pages promo recyclées, pas pages légales dédiées).
  • site-context.yaml to_confirm liste explicitement "Age legal pour parier en Guinee" et "Dispositif de verification d'age (age-gate) avant acces au contenu de jeu" comme non sourcés. Aucune meta <meta name="rating" content="adult"> ni <meta name="rating" content="RTA-5042-1996-1400-1577-RTA"> ni en-tête HTTP Rating-Label détectable au crawl shell.
  • Constat :

Le site n'expose aucun signal machine-readable indiquant qu'il est destiné à un public majeur. Pas de mention "18+" ni équivalent en footer SSR, pas de balise meta de classification de contenu (RTA, ICRA, meta rating="adult"), pas de markup Schema.org WebSite avec attribut audience ou propriété équivalente, pas de lien direct vers ressources de jeu responsable. L'âge légal exact en Guinée n'est pas sourcé en session (cf site-context.yaml to_confirm), donc l'absence de mention est doublement problématique : ni info utilisateur, ni info crawler.

  • Impact attendu :

Côté AI search : un LLM générique appelé à citer "sites de paris adaptés aux adultes Guinée" peut citer ou non bet224 sans pondération de risque mineur, car aucun signal n'oriente. Côté trust SEO : Google a une politique restrictive sur le contenu gambling (cf Gambling & Games Ads Policy, Quality Rater Guidelines section YMYL) qui pénalise les pages sans signaux de responsabilité. Côté régulation : la mention obligatoire d'âge est probable en Guinée (à sourcer Legal-check + ARSJPA), donc défaut potentiel de conformité gambling. Cross-angle TRUST.

  • Root cause :

Template footer minimaliste ne porte aucun bloc régulation. La skin GUINEA n'a pas été enrichie côté CMS pour le contexte gambling local (vs sport généraliste). Fix simultané avec F-TRUST sur footer complet régulation.

F-SEO-01-05 : Canonical incohérent sur sport-home (vide alors que les 3 autres routes l'ont valide)

  • Sévérité : moderate
  • Route(s) : sport-home
  • Source primaire :
  • crawl/index.json pages[0].canonical = "" (sport-home)
  • crawl/index.json pages[1].canonical = "https://www.bet224.gn/sport"
  • crawl/index.json pages[2].canonical = "https://www.bet224.gn/casino"
  • crawl/index.json pages[3].canonical = "https://www.bet224.gn/promotions"
  • Grep <link rel="canonical" sur raw_html_sport_home.raw.html : 0 occurrence dans les 30 premières lignes head, alors que les 3 autres raw HTML l'ont en ligne 22.
  • Constat :

La route /sport-home n'expose aucun <link rel="canonical">. Combiné au fait que cg_LANDING_URL = '/sport-home' (raw_html_sport_home.l~220) signifie que / et /sport-home sont des URL équivalentes côté serveur, sans canonical pointant vers l'une d'elles, Google et les LLM doivent choisir librement (souvent en faveur de / racine, alors que le contenu est livré sur /sport-home). Cela dilue le link equity et embrouille l'attribution de citations LLM.

  • Impact attendu :

Risque concret de duplicate content / vs /sport-home (le crawl en a observé un, le serveur en sert sans doute un autre). Citations LLM peuvent pointer vers /sport-home (URL non canonique) au lieu de la racine, fragmentant le signal d'autorité. Pour la SERP brand "bet224", la home affichée peut être la mauvaise URL.

  • Root cause :

Bug de template route landing : le canonical par défaut n'est pas posé pour la route d'entrée. Probablement une condition CMS qui exclut la landing route du canonical render.

  • Sévérité : moderate
  • Route(s) : all
  • Source primaire :
  • Brief subagent-brief-product-audit.md v1.1 section 7 : "version condensée du brief seo-audit v2.1.4. Ne pas re-faire un audit SEO complet... Si l'audit produit a besoin d'un SEO approfondi, vendre seo-audit séparément."
  • Inputs absents flaggés explicitement dans la mission : link_graph.json non produit côté product-audit, en parse_status=no_html (inutilisable pour rendering/json_ld structurés), pas de mesure de citations LLM Perplexity / ChatGPT / Gemini / Bing Copilot, pas d'analyse AGG patterns (Answer Generation Gap), pas de volume de recherche par keyword cible (keywords-mapping explicite "Pas de volume de recherche affirme (non verifie)").
  • Constat :

Le scope condensé SEO de l'audit produit couvre uniquement les findings structurels markup. Ne sont PAS couverts : la cartographie intra-site (in/out degree par page, pages orphelines, profondeur de clic depuis la home), les citations effectives sur Perplexity / ChatGPT search / Gemini / Bing Copilot pour les 11 keywords primaires + secondaires mappés, les patterns AGG (gap entre réponses LLM et contenus existants sur le site), les pages 404 / shell vide listées comme gaps (cf keywords-mapping bas du fichier : 9 catégories de pages manquantes incluant jeu-responsable, licence, mentions-legales, bonus, loto, faq, a-propos, cgu, privacy), et l'analyse comparative concurrentielle (1xBet, Premier Bet, autres opérateurs Guinée).

  • Impact attendu :

L'audit produit fournit les findings structurels qui débloquent un travail SEO sérieux (sans markup réécrit, aucune action SEO downstream ne paie). En revanche, l'optimisation SEO + AI search complète (priorisation par keyword, plan de contenu pour les 9 gaps de pages, mesure de citations LLM benchmarkée, intra-linking, AGG opportunities) requiert un audit dédié seo-audit séparé.

  • Root cause :

Scope contractuel produit-audit, pas un défaut technique. Reco R-SEO-01-06 propose le path commercial.

Cross-angle dependencies

  • F-SEO-01-01 (titles dupliqués + brand "Sportcash" erronée) recoupe [REF: DEEP-TRUST-NN/F-NN] à venir : la pollution éditoriale héritée du template Sportcash est un signal de trust dégradé (brand confusion, signal site contrefait potentiel). À fusionner avec la reco trust si l'angle TRUST identifie la même cause racine.
  • F-SEO-01-02 (zéro JSON-LD) et F-SEO-01-04 (zéro markup âge légal) recoupent [REF: DEEP-TRUST-NN/F-NN] : absence de signaux machine-readable de régulation gambling. La reco R-SEO-01-04 sur le footer régulation est à mutualiser avec les recos TRUST sur le footer mentions légales + licence + lien jeu responsable, c'est probablement le même chantier template footer.
  • F-SEO-01-01 (titles peu différenciés) recoupe [REF: DEEP-CONV-NN/F-NN] à venir : un title qui ne mentionne pas la valeur ajoutée par route impacte le taux de clic SERP (premier point de conversion). La reco R-SEO-01-01 sur les copy-ready titles est à valider en cohérence avec les CTAs primary observés dans conversion-signals/<slug>.json pour aligner promesse SERP et promesse page.
  • F-A11Y-01-01 (logo header sans alt) déjà documenté dans [REF: DEEP-A11Y-01/F-01] : la reco a11y aria-label ou alt sur le logo apporte aussi un signal SEO image (logo Bet224 indexable comme entité). Fix unique, double bénéfice.

Limites

  • Pas de page-signals/<slug>.signals.json structurés : parse_status=no_html sur tous les fichiers signals, donc impossible de lister les headings.h1_count, headings.tree, rendering.ssr_html_size_bytes, rendering.classification, og_twitter parsés, json_ld parsés en mode programmatique. Fallback raw HTML utilisé. Limitation : impossible de produire un audit AGG ou link_graph complet sans signals v1.4 fonctionnels.
  • Pas de link_graph.json côté product-audit : impossible d'analyser l'intra-linking (pages orphelines, in/out degree par page, ancres dupliquées, profondeur de clic depuis home). Reco déléguée à un audit seo-audit séparé (R-SEO-01-06).
  • Pas de crawl des pages mentions-légales / CGU / jeu-responsable / licence côté product-audit : ces routes sont absentes du crawl index.json (4 routes principales uniquement). Cross-vérification effectuée côté seo-audit/toolkit/clients/bet224/crawl/html/ qui contient ces fichiers raw : ils font tous exactement 840 lignes (shell vide identique = page 404 ou shell SSR sans contenu utile). Diagnostic flagué dans keywords-mapping bas du fichier comme "GAPS DE CONTENU 23 routes 404 / shell vide" mais non audité ici en détail.
  • Pas de mesure de citations LLM : Perplexity, ChatGPT search, Gemini, Bing Copilot non interrogés sur les 11 keywords primaires + 30+ secondaires mappés. Hors scope condensé. Reco déléguée R-SEO-01-06.
  • Pas de mesure AGG patterns : aucune question LLM cible mesurée vs contenu existant. Hors scope condensé.
  • Pas de mesure SERP réelle : pas de scrape Google Guinée pour observer le ranking actuel ni d'analyse concurrentielle (1xBet, Premier Bet). Hors scope.
  • Pas de mesure de volume de recherche par keyword : keywords-mapping explicite "Pas de volume de recherche affirme (non verifie)". Pas d'accès Keyword Planner / Ahrefs / Semrush dans la session.
  • Robots.txt et sitemap.xml non testés directement : WebFetch non utilisé dans cette passe pour respecter le scope condensé. Indicateurs raw HTML positifs (meta robots index,follow sur les 4 routes), mais existence et qualité du sitemap.xml et de robots.txt non vérifiées. À couvrir dans audit seo-audit séparé.
  • Rendering hybrid vs SSR/CSR pur : crawl/index.json retourne rendering_mode: "hybrid" sur les 4 routes, sans signals.json parsé pour départager SSR vs CSR. Estimation basée raw HTML : contenu meta + footer présent en SSR, donc rendering hybride avec base SSR (positif pour SEO + LLM). Confirmation programmatique impossible sans signals v1.4 fonctionnels.
  • Casing brand "Bet224" non confirmé : site-context.yaml flagge "[A VERIFIER] casing reelle post-crawl". Le crawl observe "www.bet224.gn" en title (préfixe domain), "bet224.gn" en url, "Bet 224" dans logo path (logo-bet-224.png), "Sportcash.com" en description (legacy CMS). Aucune confirmation explicite de la stylisation cible. Les copy-ready ci-dessus assument "Bet224" canonique (cohérent avec site-context.yaml canonical_display) mais à confirmer client avant déploiement.

Angle : TRUST

Persona

Source : site-context.yamlvoice_and_tone.persona_primary ("parieur sportif en Guinée, très majoritairement mobile, intéressé par le football en priorité").

  • sport-home : parieur sportif en intent "consulter l'offre du jour", probablement première visite. Sur le plan trust, il atterrit sur une page où il ne voit AUCUNE preuve visible d'agrément régulateur (logo ARSJPA présent dans le DOM mais peu visible et sans href), AUCUNE mention d'âge légal, AUCUN lien jeu responsable. Le bandeau hero est dominé par 2 promesses de bonus en GNF. Le footer est caché derrière un bouton "OUVRIR PIED DE PAGE". L'opérateur (raison sociale, adresse, contact) est invisible. Source : screenshots/sport-home/desktop.png + conversion-signals/sport-home.json.
  • sport : même persona en intent "consulter le détail d'une discipline". Mêmes manquements trust transverses car template global identique. S'y ajoute le bandeau promo hero.
  • casino : persona élargie (joueur casino, plus exposé au risque addictif sur jeux crash type Aviator). Mêmes manquements trust. S'y ajoute un widget "Gains récents" (montants spécifiques affichés) qui amplifie le besoin de garde-fous trust visibles (jeu responsable, mention d'âge), absents.
  • promotions : persona en intent "découvrir un bonus avant de s'inscrire ou déposer". Cards "MAXI BONUS / AUGMENTE TES GAINS JUSQU'À 500 %" très visibles ; conditions de mise (wagering) non affichées above-fold, ce qui est typiquement le pattern où le besoin d'une page T&C accessible est maximal. Or, aucune page mentions-legales / licence / jeu responsable / privacy n'est accessible (toutes en soft 404, cf findings F-TRUST-01-02 à F-TRUST-01-05).

Synthèse exécutive

  • 5 pages clés du périmètre trust sont des soft 404 : mentions-legales, licence, jeu-responsable, responsible-gaming, privacy, politique-confidentialite, ainsi que contact, a-propos, qui-sommes-nous, aide, help, faq, cgu, conditions, terms, bonus. Source : grep body page="404" dans seo-audit/.../crawl/html/*.raw.html retourne 23 fichiers. Sur YMYL gambling, l'absence de page mentions légales et de page licence accessibles est un manquement structurel majeur, indépendamment du cadre réglementaire GN à confirmer (site-context.yaml to_confirm "Cadre data... a sourcer juridique client").
  • Le footer effectif ne contient que 2 liens légaux ("Politique de Confidentialité" + "Conditions Générales") qui pointent vers /promo/tutte/bet224_politique_confidentialite et /promo/tutte/bet224_conditions_generales (PAS dans le crawl, contenu inconnu). Source : conversion-signals/sport-home.jsondetailed.trust_signals.legal_links (4/4 routes). Aucun lien vers mentions légales, jeu responsable, contact, licence, aide. Le footer est par défaut caché derrière un bouton accordion "OUVRIR PIED DE PAGE" (sport-home.raw.html:746 + screenshots/*/desktop.png bouton rouge "OUVRIR PIED DE PAGE" bas-droit).
  • Aucune mention d'âge légal (18+ ou autre) ni dispositif d'age-gate visible sur les 4 routes. Source : grep 18\+|interdit aux mineurs dans sport-home.raw.html → aucune occurrence dans le contenu affiché en français (seules occurrences = labels JSON italiens hard-codés header.disclaimer = "Il gioco è vietato ai minori di diciotto anni", non traduits, non affichés, et référant au régulateur italien ADM). Le seuil d'âge légal en Guinée n'est pas sourcé en session (cf site-context.yaml to_confirm "Age legal pour parier en Guinee").
  • Logo ARSJPA présent dans le DOM mais non fonctionnel et présentation décorative : <img src="https://www.bet224.gn/external_css/GUINEA/img/ARSJPA.png"> (sport-home.raw.html:389) dans un <a class="cg-ext-link pointer" onclick=""> SANS href, SANS alt text, dans un container min-width:35px. Ne prouve pas l'agrément et ne renvoie pas vers arsjpa.gov.gn. Identique sur les 42 pages crawlées.
  • Identifiants SIRET / VAT-EU détectés mais en faux positifs : conversion-signals/index.jsonaggregate.routes_with_siret_or_vat = 2, mais sport.jsonvat_excerpt = "BETBUILDER" et promotions.jsonvat_excerpt = "DE PROFITER" ne sont PAS des numéros VAT-EU réels, juste des morceaux de texte capturés par regex. Aucun identifiant commercial guinéen attendu (équivalent RCCM / numéro d'agrément ARSJPA) n'est exposé. Aucun email, téléphone, adresse postale visible (aggregate.routes_with_contact_email = 0, routes_with_contact_phone = 0).
  • Cookie banner non conforme aux standards internationaux : un seul bouton "OK" (accept all), pas de "Refuser" ni de granularité, wording "En poursuivant votre navigation, vous acceptez l'utilisation de tous les cookies" (consent passif). Lien "Plus d'informations" pointe vers un PDF (/external_cms/pdf/Cookies_Policy.pdf) au lieu d'une page navigable. Source : screenshots/sport-home/desktop.png bandeau top + sport-home.raw.html:349-355. Cadre data guinéen non sourcé en session.

Findings

F-TRUST-01-01 : Logo ARSJPA présent dans le DOM mais non fonctionnel, sans href ni alt, présentation décorative qui ne prouve pas l'agrément

  • Sévérité : critical
  • Route(s) : sport-home, sport, casino, promotions
  • Source primaire :
  • sport-home.raw.html:386-392 : <div id="cg-social-link-container" class="blocco-header login-form-header margine-su-1x" style="display: flex; margin-top:0px"><div id="" class="form-group margine-dx" style="min-width:35px"><a class="cg-ext-link pointer" onclick=""><img src="https://www.bet224.gn/external_css/GUINEA/img/ARSJPA.png"><span></span></a></div></div>
  • Le <a> a onclick="" (vide) et SANS href. L'image n'a pas d'attribut alt.
  • Le container parent est en min-width:35px (très étroit). Pattern identique sur les 42 fichiers raw.html du crawl seo-audit (grep ARSJPA retourne 42 résultats).
  • site-context.yamlexternal_authorities[0].caveat : "Statut d'agrement de Bet224 NON verifie - ne jamais affirmer que Bet224 est ou n'est pas agree"
  • Source visuelle : - screenshots/sport-home/desktop.png zone header haut-droit (x ≈ 480-720, y ≈ 30-66) : le logo ARSJPA n'est pas distinctement visible à 1440px de largeur (présent en DOM, masqué visuellement par sa taille et le styling de container 35px).
  • Pattern identique sur les 4 routes (vérifié casino, promotions, sport).
  • Constat :

L'image ARSJPA.png est embarquée dans tout le template du site mais (1) sans alt text accessible, (2) sans lien fonctionnel vers le registre officiel arsjpa.gov.gn, (3) dans un container CSS de 35px de min-width sans label visible. Présentée ainsi, l'image suggère visuellement un agrément (effet "tampon officiel") sans en apporter la preuve actionnable côté utilisateur. Le statut d'agrément réel de Bet224 auprès de l'ARSJPA n'est pas vérifié en session (cf site-context.yaml).

  • Impact attendu :

Pour l'utilisateur : confusion sur la légitimité de l'opérateur. Pour le régulateur ARSJPA potentiellement saisi : risque d'usage frauduleux du logo si l'opérateur n'est pas agréé, ou d'usage non conforme si agréé mais sans modalité d'affichage validée par l'ARSJPA. Pour Bet224 : risque réputationnel en cas de signalement, risque de retrait d'agrément si déjà obtenu et usage non conforme. À cadrer Legal-check + obtenir du client (1) le numéro d'agrément ARSJPA si existant, (2) les modalités d'affichage validées par l'ARSJPA si une charte existe.

  • Root cause :

Template global "GUINEA" (cf body data-systemcode="GUINEA") probablement adapté à minima depuis un template d'opérateur italien (cf F-TRUST-01-12). Le logo ARSJPA a été inséré statiquement comme image dans le container "social link" sans intégration aux pages mentions-legales ou licence (qui n'existent pas, cf F-TRUST-01-02 et F-TRUST-01-03).

F-TRUST-01-02 : Page /mentions-legales = soft 404, aucune mention légale accessible publiquement

  • Sévérité : critical
  • Route(s) : mentions-legales
  • Source primaire :
  • seo-audit/.../crawl/html/mentions-legales.raw.html:301 : <body page="404" subpage="404" class=" cg-internal-page cg-body-unlogged cg-user-no-vip " data-original="mentions-legales" data-internal="mentions-legales" data-systemcode="GUINEA">
  • mentions-legales.raw.html:684-690 : <div id="cg-404-page-outer-container">...<span class="display-1 d-block">404</span><div class="mb-4 lead">Page non trouvée</div>
  • mentions-legales.raw.html:23 : <title>bet224.gn - </title> (title vide, signal supplémentaire de page non personnalisée)
  • site-context.yamlbrand.canonical_legal: "" (raison sociale opérateur vide, à obtenir client)
  • Source visuelle : - Pas de screenshot sur cette route (hors POC). Le HTML soft 404 retourné est cependant intégré au template (header, footer, cookie banner) identique au reste du site, donc l'utilisateur arrivant sur /mentions-legales voit la chrome du site puis un message 404 standard.
  • Constat :

Aucune page de mentions légales accessible publiquement sur bet224.gn. Sur YMYL gambling, l'absence d'une page mentions légales reprenant a minima la raison sociale de l'opérateur, son siège social, son numéro d'agrément, son contact juridique est un manquement structurel transverse, indépendamment du cadre réglementaire guinéen spécifique à confirmer.

  • Impact attendu :

Pour l'utilisateur : impossible d'identifier l'opérateur, d'exercer un droit (rétractation, plainte, contestation de transaction). Pour l'autorité ARSJPA si saisie : aucun moyen de relier visuellement le site à l'entité titulaire d'un éventuel agrément. Pour Bet224 : risque réglementaire en cas d'enquête ARSJPA ou de contestation utilisateur. Impact réputationnel direct sur l'utilisateur prudent qui cherche typiquement la page mentions légales avant un premier dépôt.

  • Root cause :

Page non créée côté CMS, ou créée puis dépubliée. Aucun fallback de redirection vers une page valide. Le serveur retourne 200 avec un body page="404", donc soft 404 (pas un vrai 404 HTTP), pratique problématique également côté SEO car les moteurs indexent comme contenu valide.

F-TRUST-01-03 : Page /licence = soft 404, aucun numéro de licence ni preuve d'agrément accessible

  • Sévérité : critical
  • Route(s) : licence
  • Source primaire :
  • seo-audit/.../crawl/html/licence.raw.html:301 : <body page="404" subpage="404" ... data-original="licence" data-internal="licence" data-systemcode="GUINEA">
  • Présence de l'image ARSJPA dans le template (ligne 385) mais sans contenu de page valide.
  • site-context.yamlfacts.to_confirm[1] : "Numero de licence de Bet224 + statut d'agrement aupres de l'ARSJPA - Licence declaree par le client 2026-05-16 mais non sourcee"
  • Aucun numéro d'agrément ni texte de référence (décret, arrêté) n'est trouvé en grep sur le corpus crawlé (grep -i "agrément\|décret\|arrêté\|n°" sport-home.raw.html = aucun résultat dans contenu visible).
  • Source visuelle : - Pas de screenshot sur cette route. HTML retourné = template + message 404.
  • Constat :

Bet224 ne publie pas son numéro de licence ARSJPA (ou autre titre d'autorisation) sur le site, ni sur une page dédiée /licence (404), ni dans le footer des 4 routes principales (legal_links ne contient que CGU + Politique confidentialité), ni dans les mentions légales (404). Le seul élément visuel suggérant un agrément est l'image ARSJPA.png décorative non sourcée (F-TRUST-01-01).

  • Impact attendu :

Impossible pour l'utilisateur, le régulateur ARSJPA ou un tiers (journaliste, concurrent, autorité étrangère) de vérifier la conformité réglementaire de Bet224 à partir du site lui-même. Risque réputationnel + risque d'investigation ARSJPA si remontée d'utilisateur. Si Bet224 EST agréée, c'est aussi un manque-à-gagner trust (l'agrément est typiquement un argument fort pour le premier dépôt).

  • Root cause :

Page absente côté CMS, ou n'a jamais été créée pour la déclinaison GUINEA. Cf F-TRUST-01-12 : trace que le template est adapté d'un opérateur italien où la mention de licence ADM est centralisée différemment.

F-TRUST-01-04 : Pages /jeu-responsable et /responsible-gaming toutes deux soft 404, dispositif jeu responsable invisible

  • Sévérité : critical
  • Route(s) : jeu-responsable, responsible-gaming
  • Source primaire :
  • seo-audit/.../crawl/html/jeu-responsable.raw.html:301 : <body page="404" subpage="404" ... data-original="jeu-responsable" data-internal="jeu-responsable" data-systemcode="GUINEA">
  • seo-audit/.../crawl/html/responsible-gaming.raw.html:301 : même soft 404.
  • site-context.yamlforbidden_patterns[2] = "absence de lien visible vers jeu responsable / auto-exclusion / limites"
  • Côté DOM, présence de labels JSON internes (sport-home.raw.html ligne 250) "account.options.exclusion":"Auto-exclusion", "cgr.gioco.res.panel.perma.exclusion":"Auto-exclusion permanente", "cgr.gioco.res.panel.exclusion.ok":"Auto-exclusion activée" → le code prévoit un dispositif d'auto-exclusion en interne (accessible uniquement après login utilisateur), mais sans page publique présentant le dispositif.
  • Source visuelle : - Pas de screenshot des pages 404. Sur les 4 routes POC, aucun lien "Jeu responsable" / "Responsible gaming" / "Auto-exclusion" visible above-fold ni dans le footer effectif (legal_links ne contient pas ces termes).
  • Constat :

Le site ne propose AUCUNE page publique présentant le dispositif jeu responsable de Bet224 (ressources, limites de mise, limites de dépôt, auto-exclusion, signes d'addiction, numéro d'aide). Les routes /jeu-responsable et /responsible-gaming sont soft 404. Le dispositif d'auto-exclusion existe potentiellement en interne (labels traduits dans le code) mais n'est accessible qu'après login, donc invisible au visiteur non inscrit et au prospect évaluant la légitimité de l'opérateur.

  • Impact attendu :

Pour l'utilisateur : impossibilité d'évaluer la posture de l'opérateur sur le jeu responsable avant un premier dépôt. Pour un utilisateur déjà inscrit en difficulté : aucune ressource publique mobilisable (numéro d'aide, FAQ addiction). Sur le plan moral sectoriel : manquement majeur, le jeu responsable est un standard quasi-universel des régulateurs gambling matures (UKGC, ANJ, MGA, ADM, etc., principe de protection des publics vulnérables). Sur le plan réputationnel : risque très élevé en cas d'incident utilisateur (signalement d'addiction sans ressource fournie). Cadre GN spécifique à confirmer Legal-check, mais l'obligation morale est forte indépendamment.

  • Root cause :

Pages publiques non créées côté CMS. Probablement le concept "page publique jeu responsable accessible avant login" a été perdu dans l'adaptation depuis le template italien (où la page Gioco Responsabile est publique sur Snai, Lottomatica, etc.). Le dispositif technique interne existe mais n'est pas exposé en façade.

F-TRUST-01-05 : Pages /privacy et /politique-confidentialite toutes deux soft 404, politique de confidentialité indisponible en HTML

  • Sévérité : critical
  • Route(s) : privacy, politique-confidentialite
  • Source primaire :
  • seo-audit/.../crawl/html/privacy.raw.html:301 : <body page="404" subpage="404" ... data-original="privacy">
  • seo-audit/.../crawl/html/politique-confidentialite.raw.html:301 : même soft 404.
  • Le footer effectif (sport-home.raw.html:765) contient bien un lien <a href="/promo/tutte/bet224_politique_confidentialite" target="_blank">Politique de Confidentialité</a> mais cette URL n'a PAS été crawlée (donc contenu inconnu). Le slug indique une page dans le mécanisme "promo", inhabituel pour une politique de confidentialité (probablement réutilisation du moteur CMS promo).
  • site-context.yamlto_confirm : "Cadre data / cookies de profilage applicable en Guinee + politique de confidentialite - Le site sert un bandeau annoncant des 'cookies de profilage tiers' sans page politique de confidentialite accessible (route 404)".
  • Source visuelle : - Pas de screenshot des pages 404. Le bandeau cookie sur les 4 routes (screenshots) annonce "cookies de profilage tiers" mais l'utilisateur cliquant sur "Plus d'informations" est redirigé vers un PDF (/external_cms/pdf/Cookies_Policy.pdf), pas vers une page HTML navigable.
  • Constat :

Aucune page HTML standalone de politique de confidentialité accessible aux URLs canoniques attendues (/privacy, /politique-confidentialite). La seule politique cookie disponible est un PDF dans /external_cms/pdf/. Le lien "Politique de Confidentialité" du footer pointe vers une URL non crawlée dans un mécanisme "promo" (/promo/tutte/bet224_politique_confidentialite), ce qui interroge la pérennité et la fiabilité du contenu.

  • Impact attendu :

Pour l'utilisateur : difficile d'exercer un droit data (information, opposition, accès, suppression) sans page navigable. Pour le bandeau cookie qui annonce des "cookies de profilage tiers" : opacité totale sur QUELS cookies, QUELLES finalités, QUELLES durées. Cadre data GN à confirmer Legal-check, mais le pattern est moralement non-conforme aux standards internationaux RGPD-like (UE) ou PIPA (Afrique de l'Ouest). Risque utilisateur prudent qui ne déposera pas + risque légal selon cadre GN.

  • Root cause :

Pages HTML jamais créées. Politique cookie en PDF probablement héritée du template italien. Lien footer pointant vers un module promo = bug ou solution de contournement non pérenne (probabilité que cette page disparaisse à la prochaine refonte du module promo).

  • Sévérité : critical
  • Route(s) : sport-home, sport, casino, promotions
  • Source primaire :
  • sport-home.raw.html:746 : <a id="consultaFooter" data-toggle="collapse" class="consulta-footer fissato accordion-toggle toggle-nascondi" href="#nascondifooter" role="button" aria-expanded="false" aria-controls="nascondi-footer">OUVRIR PIED DE PAGE</a>
  • sport-home.raw.html:752 : <footer class="collapse cg-lazy" id="nascondifooter"> (class collapse Bootstrap = caché par défaut, cg-lazy = chargé en lazy)
  • sport-home.raw.html:762-767 : seul contenu visible une fois ouvert = section "AIDER" contenant 3 liens : "Registration" (modal), "Politique de Confidentialité" (vers /promo/tutte/bet224_politique_confidentialite), "Conditions Générales" (vers /promo/tutte/bet224_conditions_generales).
  • conversion-signals/sport-home.jsondetailed.trust_signals.legal_links_count = 2 (4/4 routes, valeur identique).
  • conversion-signals/index.jsonaggregate.routes_with_legal_links = 4 MAIS uniquement 2 liens par route (CGU + Privacy), pas mentions légales / jeu responsable / contact / licence.
  • Source visuelle : - screenshots/sport-home/desktop.png zone bas-droite (x ≈ 1276, y ≈ 876) : bouton rouge "OUVRIR PIED DE PAGE" (<a class="consulta-footer fissato ...">).
  • screenshots/sport/desktop.png même bouton (x ≈ 1276, y ≈ 876).
  • screenshots/casino/desktop.png même bouton (x ≈ 1243, y ≈ 861).
  • screenshots/promotions/desktop.png même bouton (x ≈ 1243, y ≈ 861).
  • Constat :

Le pied de page est caché par défaut sur les 4 routes principales. Un utilisateur en navigation classique (scroll bas) ne le voit pas. Il faut cliquer sur "OUVRIR PIED DE PAGE" pour le déployer. Une fois ouvert, il ne contient que 2 liens légaux (CGU + Privacy), pas mentions légales, pas jeu responsable, pas contact, pas licence, pas adresse opérateur. Le footer est aussi cg-lazy, donc le contenu est chargé seulement à l'interaction.

  • Impact attendu :

Pour l'utilisateur : 99 % des utilisateurs n'ouvriront jamais le footer (pattern UX d'accordion bottom typiquement ignoré). Pour le trust : les mentions légales obligatoires (cadre régulateur à confirmer) ne sont accessibles qu'après une interaction délibérée. Pour les moteurs de recherche : le contenu lazy + collapse peut ne pas être indexé. Pour l'accessibilité (cf cross-angle A11Y) : navigation clavier complexifiée (collapse Bootstrap + cg-lazy).

  • Root cause :

Pattern accordion "OUVRIR PIED DE PAGE" hérité probablement du template italien consulta-footer (consulta = "consulter" en italien). Choix design / UX d'origine, non révisé pour le cadre YMYL gambling où le footer trust devrait être visible par défaut.

F-TRUST-01-07 : Aucune mention d'âge légal ni dispositif d'age-gate avant accès au catalogue de jeu

  • Sévérité : critical
  • Route(s) : sport-home, sport, casino, promotions
  • Source primaire :
  • Grep sur sport-home.raw.html : aucune occurrence de "18+" / "interdit aux mineurs" / "joueur excessif" dans le contenu affiché en français. Seules occurrences (ligne 250, labels JSON) : header.disclaimer = "Il gioco è vietato ai minori di diciotto anni" (italien, hard-codé, non traduit, non affiché), "esercizio.minimoeta" = "18" (label backoffice italien, non affiché en façade).
  • conversion-signals/sport-home.jsondetailed.trust_signals.footer_text_length_chars = 1236 (footer court, ne contient pas la mention d'âge).
  • site-context.yamlforbidden_patterns[3] = "absence de mention d'age legal (18+ ou seuil legal guineen a confirmer)"
  • site-context.yamlto_confirm : "Age legal pour parier en Guinee - Mention obligatoire probable. Valeur exacte non connue, NE PAS supposer 18 par defaut sans source guineenne", et "Dispositif de verification d'age (age-gate) avant acces au contenu de jeu - Distinct de la simple mention d'age. Principe sectoriel quasi-universel".
  • Pas d'écran d'age-gate observé : screenshots/sport-home/desktop.png montre directement le catalogue de paris sans interstitiel ; idem pour les 3 autres routes.
  • Source visuelle : - screenshots/sport-home/desktop.png, screenshots/sport/desktop.png, screenshots/casino/desktop.png, screenshots/promotions/desktop.png : aucune mention "18+" / "Interdit aux mineurs" / "Réservé aux adultes" visible above-fold, dans le header, ni dans le footer ouvert (header montre uniquement logo + login + langue + ARSJPA décoratif).
  • Constat :

Bet224 n'affiche aucune mention d'âge légal (18+ ou autre) sur les 4 routes principales et ne propose pas d'age-gate (écran de vérification d'âge avant accès au catalogue de cotes, de matches, de jeux casino). Un mineur navigant sur bet224.gn voit directement le catalogue sport et casino, y compris des jeux crash (Aviator) particulièrement addictifs. Le seuil d'âge légal en Guinée n'est pas sourcé en session (interdit de supposer 18 par défaut sans source officielle GN), MAIS le principe d'interdiction aux mineurs est sectoriellement universel.

  • Impact attendu :

Pour la protection des mineurs : risque direct de captation d'un public mineur (interdit moralement et probablement légalement, à confirmer Legal-check). Pour l'opérateur : risque très élevé en cas de signalement ou d'enquête (médias, association, ARSJPA). Risque réputationnel et risque pénal selon cadre GN. Sur le plan moral sectoriel : manquement gravissime, quasi-universellement sanctionné par les régulateurs gambling matures. À traiter en priorité absolue indépendamment du cadre GN spécifique.

  • Root cause :

Adaptation depuis le template italien où le disclaimer d'âge est dans header.disclaimer = "Il gioco è vietato ai minori di diciotto anni". Lors de la traduction en français pour la déclinaison GUINEA, ce disclaimer n'a PAS été traduit ni affiché. L'age-gate n'a probablement jamais été implémenté pour aucune déclinaison de ce template.

  • Sévérité : critical
  • Route(s) : mentions-legales, licence, jeu-responsable, responsible-gaming, privacy, politique-confidentialite, cgu, conditions, terms, contact, a-propos, qui-sommes-nous, aide, help, faq, bonus
  • Source primaire :
  • Grep body page="404" sur seo-audit/.../crawl/html/*.raw.html retourne 23 fichiers, dont les 16 pages "support / legal" listées ci-dessus + pages techniques (multi-live, top-match, esport, loto, etc.).
  • Liste exhaustive sourcée : mentions-legales.raw.html, licence.raw.html, jeu-responsable.raw.html, responsible-gaming.raw.html, privacy.raw.html, politique-confidentialite.raw.html, cgu.raw.html, conditions.raw.html, terms.raw.html, contact.raw.html, a-propos.raw.html, qui-sommes-nous.raw.html, aide.raw.html, help.raw.html, faq.raw.html, bonus.raw.html (toutes les 16 retournent <body page="404"...>).
  • Toutes retournent HTTP 200 (pas un vrai 404), donc soft 404 = problème indexation SEO + perception utilisateur d'un site valide qui n'a juste pas le contenu attendu.
  • Source visuelle : - Pas de screenshot direct des pages 404. HTML rendu = template complet (header + cookie banner + footer caché) + bloc 404 Page non trouvée.
  • Constat :

Une partie massive de l'infrastructure de pages "support + legal + about" attendue d'un opérateur gambling YMYL n'existe pas côté serveur. Les seules URLs légales fonctionnelles sont les 2 du footer pointant vers le module promo (/promo/tutte/bet224_politique_confidentialite + /promo/tutte/bet224_conditions_generales), non crawlées donc contenu inconnu.

  • Impact attendu :

Pour l'utilisateur : impossibilité d'accéder à toute information opérateur, contractuelle, support, légale via les URLs canoniques attendues. Pour le SEO : 16 soft 404 indexées comme contenu valide = signal négatif Google. Pour le régulateur ARSJPA : aucun contenu démontrant la conformité (mentions, licence, jeu responsable, T&C) accessible publiquement. Pour la réputation : si un journaliste, association ou autorité tente de vérifier l'opérateur via les URLs standard, échec systématique.

  • Root cause :

Adaptation incomplète du template depuis la déclinaison italienne. Les pages support / legal / about ont vraisemblablement été désactivées ou jamais portées en GUINEA. La solution de contournement (mettre Politique et CGU dans le module promo) est non pérenne et fragmentaire.

F-TRUST-01-08 : Identifiants commerciaux SIRET/VAT-EU détectés en faux positifs ; aucun identifiant guinéen attendu (RCCM ou n° ARSJPA) exposé

  • Sévérité : serious
  • Route(s) : sport-home, sport, casino, promotions
  • Source primaire :
  • conversion-signals/index.jsonaggregate.routes_with_siret_or_vat = 2 (sport et promotions)
  • conversion-signals/sport.jsondetailed.trust_signals.has_vat_eu = true, vat_excerpt = "BETBUILDER" (faux positif : "BETBUILDER" n'est pas un VAT EU)
  • conversion-signals/promotions.jsondetailed.trust_signals.has_vat_eu = true, vat_excerpt = "DE PROFITER" (faux positif : pas un VAT EU)
  • conversion-signals/sport-home.json et conversion-signals/casino.jsonhas_siret = false, has_vat_eu = false, has_rcs = false.
  • site-context.yamllocation.country = "GN" (Guinée), donc ni SIRET (FR), ni VAT-EU (UE), ni RCS (FR) ne sont les identifiants attendus. L'équivalent guinéen attendu est typiquement un numéro RCCM (Registre du Commerce et du Crédit Mobilier OHADA) et/ou un numéro d'agrément ARSJPA. Aucun n'est exposé.
  • Source visuelle : - Pas de bloc identifiants commerciaux visible sur les screenshots des 4 routes (header + above-fold + footer ouvert). Footer ouvert ne contient que 3 liens "AIDER" sans information opérateur.
  • Constat :

Les détecteurs SIRET / VAT-EU ont remonté 2 faux positifs ("BETBUILDER", "DE PROFITER" sont juste des morceaux de texte capturés par regex permissive). Aucun identifiant commercial réel n'est exposé sur les 4 routes. Pour la juridiction guinéenne, l'identifiant attendu est un RCCM (OHADA) + un numéro d'agrément ARSJPA. Aucun n'est trouvé dans le crawl.

  • Impact attendu :

Pour l'utilisateur : impossible d'identifier l'entité juridique exacte derrière Bet224 (raison sociale, forme juridique, capital, immatriculation). Pour le régulateur : aucun lien visible entre le site et l'entité titulaire d'un éventuel agrément. Pour Bet224 : risque réglementaire en cas d'enquête. Cross-link à F-TRUST-01-02 (mentions légales soft 404). Note méthodologique : le faux positif des détecteurs SIRET/VAT a induit aggregate.routes_with_siret_or_vat = 2 qui surévalue artificiellement la complétude trust ; à patcher dans le détecteur conversion-signals v1.3 (cf cross-angle).

  • Root cause :

Aucune info opérateur publiée. Sur l'aspect détecteur : regex VAT-EU trop permissive (ne valide pas le format XX[0-9]+ strict, capture des mots majuscules de longueur similaire).

F-TRUST-01-09 : Aucun contact opérateur visible (email, téléphone, adresse, formulaire support) sur 4 routes

  • Sévérité : serious
  • Route(s) : sport-home, sport, casino, promotions
  • Source primaire :
  • conversion-signals/index.jsonaggregate.routes_with_contact_email = 0, aggregate.routes_with_contact_phone = 0 (4/4 routes sans email ni téléphone visible)
  • conversion-signals/sport-home.jsondetailed.trust_signals.contact_email_visible = false, contact_phone_visible_in_footer = false, contact_links_count = 0
  • Pattern identique sur les 4 routes (sport.json, casino.json, promotions.json).
  • seo-audit/.../crawl/html/contact.raw.html:301 : body page="404" (page contact = soft 404).
  • seo-audit/.../crawl/html/aide.raw.html:301 et help.raw.html:301 : également soft 404.
  • sport-home.raw.html cherche cg-contatti (ligne 315) : <div class="blocco-header flex-container cg-contatti"></div> (container vide, pas d'email ni téléphone injecté).
  • Source visuelle : - screenshots/sport-home/desktop.png, screenshots/sport/desktop.png, screenshots/casino/desktop.png, screenshots/promotions/desktop.png : aucune zone "Contact", "Support 24/7", "Aide", "Service client" visible above-fold ni dans le footer fermé. Le footer ouvert (testé via inspection raw HTML) ne contient pas de bloc contact.
  • Constat :

Aucun email, numéro de téléphone, adresse postale ou formulaire de contact n'est exposé sur les 4 routes principales. Les pages /contact, /aide, /help sont toutes soft 404. Le container cg-contatti du header est présent dans le DOM mais vide.

  • Impact attendu :

Pour l'utilisateur : impossible de contacter Bet224 avant un premier dépôt (utilisateur prudent qui veut tester le support) ou en cas de problème (dépôt non crédité, retrait bloqué, fermeture de compte). Sur YMYL gambling, l'absence de support visible est typiquement un anti-pattern sanctionné par les régulateurs matures. Pour la conversion : impact négatif sur premier dépôt + sur rétention (problème non résolu = churn). Pour le risque légal : à confirmer Legal-check (cadre GN), mais obligation morale forte.

  • Root cause :

Container cg-contatti non rempli côté CMS. Probablement le template italien remplit ce container avec le téléphone du Concessionario ; lors de l'adaptation GUINEA, le contact n'a pas été configuré. Pages contact / aide non créées côté CMS.

  • Sévérité : serious
  • Route(s) : sport-home, sport, casino, promotions
  • Source primaire :
  • sport-home.raw.html:349-355 : <div id="cg-barra-cookies" class="row inline-flex flex-row justify-content-center cg-hide"><div>Ce site utilise des cookies, y compris des cookies de profilage tiers. Si vous souhaitez en savoir plus ou désactiver certains ou tous les cookies, lisez les informations. En poursuivant votre navigation, vous acceptez l'utilisation de tous les cookies.</div><div class="d-inline-flex flex-row justify-content-center"><a class="cg-cookies-ok" onclick="cg_acceptsCookies()">OK</a><a class="cg-cookies-more-info" href="/external_cms/pdf/Cookies_Policy.pdf" target="_blank">Plus d'informations</a></div></div>
  • Boutons : "OK" (accept all) + "Plus d'informations" (lien PDF externe). PAS de bouton "Refuser" ni de granularité (fonctionnels / analytics / profilage).
  • Wording : "En poursuivant votre navigation, vous acceptez l'utilisation de tous les cookies" → consent passif (poursuite navigation = accept implicite).
  • site-context.yamlto_confirm : "Cadre data / cookies de profilage applicable en Guinee + politique de confidentialite - Le site sert un bandeau annoncant des 'cookies de profilage tiers' sans page politique de confidentialite accessible (route 404)".
  • Source visuelle : - screenshots/sport-home/desktop.png zone bandeau top (x ≈ 0-720, y ≈ 0-22) : bandeau noir "Ce site utilise des cookies, y compris des cookies de profilage tiers. ... En poursuivant votre navigation, vous acceptez l'utilisation de tous les cookies." avec UN SEUL bouton vert "OK" (x ≈ 626, y ≈ 7) + lien bleu "Plus d'informations" (x ≈ 660, y ≈ 7).
  • Pattern identique sur les 4 routes (vérifié screenshots/sport/desktop.png, casino/desktop.png, promotions/desktop.png).
  • Constat :

Le bandeau cookie ne propose pas de "Refuser" symétrique au "OK". Il n'y a pas de granularité (impossible de refuser uniquement le profilage tiers). Le wording "En poursuivant votre navigation, vous acceptez" est un consent passif (pattern contesté par CNIL FR 2020, GDPR EDPB, considéré non valide dans la plupart des juridictions matures). Lien "Plus d'informations" pointe vers PDF (/external_cms/pdf/Cookies_Policy.pdf) au lieu d'une page HTML navigable.

  • Impact attendu :

Pour l'utilisateur : aucun choix réel sur les cookies de profilage. Pour le cadre data GN : à confirmer Legal-check (non sourcé en session), mais probable non-conformité à toute approche moderne de consentement. Pour Bet224 : risque légal selon cadre GN + risque réputationnel (utilisateur qui veut refuser ne peut pas, frustration). Effet conversion direct : neutre, mais détérioration trust.

  • Root cause :

Template historique italien probablement, où le consent passif "navigando accetti" était toléré jusqu'à GDPR 2018. Non re-customisé pour standards 2024+. Cross-link F-CONV-01-08 (même finding angle CONV) ; reco potentiellement fusionnable.

F-TRUST-01-13 : Bonus very visibles above-fold mais conditions de mise (wagering) invisibles ; T&C bonus inaccessibles via URL standard

  • Sévérité : serious
  • Route(s) : sport-home, sport, promotions
  • Source primaire :
  • screenshots/sport-home/desktop.png zone hero (y ≈ 75-150) : 2 bannières "GAGNEZ 100% DE BONUS SUR VOTRE 1ER DÉPÔT JUSQU'À 1,000,000 GNF !" + "10% CASHBACK CHAQUE SEMAINE JUSQU'À 500,000 GNF !" (texte embarqué dans JPG donc non extrait par detector text mais visible).
  • screenshots/sport/desktop.png zone hero (y ≈ 80-130) : même bannière "GAGNEZ 100% DE BONUS ...".
  • screenshots/promotions/desktop.png zone hero (y ≈ 50-160) : bannière "MAXI BONUS / AUGMENTE TES GAINS JUSQU'À 500% ! PARIEZ ICI" + 3 cards "MAXI BONUS / CASHBACK SPORT / WELCOME SPORT" sans mention condition de mise visible.
  • seo-audit/.../crawl/html/bonus.raw.html:301 : body page="404" (page bonus = soft 404, donc T&C bonus dédiés non accessibles à cette URL).
  • site-context.yamlforbidden_patterns[1] = "conditions de mise (wagering) cachees ou en caracteres minuscules".
  • Cross-link : DEEP-CONV-01 → F-CONV-01-01 traite l'aspect wording promesse de gain. Le présent finding traite l'aspect trust = T&C inaccessibles.
  • Source visuelle : - Détaillée ci-dessus dans Source primaire.
  • Constat :

Les bonus sont massivement mis en avant (4 cards visibles sur 4 routes, chiffres importants en GNF), mais les conditions de mise (wagering requirements, ex. "30x sur le bonus avant retrait possible") ne sont jamais affichées above-fold. Une page /bonus qui pourrait centraliser les T&C est soft 404. L'utilisateur doit déduire qu'il faut chercher dans les CGU (/promo/tutte/bet224_conditions_generales, non crawlées) pour trouver le détail.

  • Impact attendu :

Pour l'utilisateur : incompréhension probable des conditions réelles d'éligibilité au bonus (souvent : dépôt minimum, wagering 30-50x, jeux exclus, plafond de gain). Risque de déception forte au moment du retrait. Sur le plan trust : pattern reconnu comme dark pattern par UKGC, ANJ, MGA. Pour Bet224 : risque de plainte utilisateur + risque réglementaire selon cadre GN (à confirmer Legal-check). Pour la réputation : pattern qui alimente les avis négatifs gambling.

  • Root cause :

Bannières JPG préparées sans mention de conditions (probablement pour ne pas alourdir le visuel). Page /bonus non créée côté CMS GUINEA, donc pas de page T&C bonus dédiée. T&C noyés dans les CGU générales si accessibles.

F-TRUST-01-12 : Traces de plateforme white-label italienne dans le code (ADM, Concessionario, RUA, italian language) sans contextualisation GN

  • Sévérité : moderate
  • Route(s) : sport-home, sport, casino, promotions
  • Source primaire :
  • sport-home.raw.html:250 (bloc var cg_LABEL, fichier de labels JSON localisés) : présence de chaînes italiennes hard-codées non traduites, exemples :
  • "exclusion.determ":"Ti ricordiamo che in caso di autoesclusione, il Concessionario sarà tenuto a comunicare tale volontà all\\'Anagrafe dei Conti di Gioco, gestita dall\\'ADM, inserendoti nel Registro Unico degli Autoesclusi (RUA)..."
  • "signup.label.7days":"7 jours" (français), MAIS "recover.center.otp.title.type.email":"Controlla la tua posta elettronica" (italien)
  • Présence des chaînes "ADM" (régulateur italien), "Concessionario", "RUA" (Registro Unico degli Autoesclusi italien), "Anagrafe dei Conti di Gioco" (régulateur italien), "Il gioco è vietato ai minori di diciotto anni".
  • body data-systemcode="GUINEA" (sport-home.raw.html:301) confirme une déclinaison GN d'un template multi-pays.
  • Class CSS consulta-footer (italien : "consulter le footer"), nascondi (italien : "cacher"), nascondifooter (italien) : structure de classes en italien.
  • Source visuelle : - Ces chaînes italiennes ne sont PAS affichées en façade utilisateur (présence uniquement dans les labels JSON qui ne servent qu'après login ou dans des modales internes). Donc effet utilisateur direct = nul pour le visiteur non inscrit. Effet sur audit trust = trace de white-label, signal d'attention pour Legal-check.
  • Constat :

Le code source révèle que bet224.gn est une déclinaison guinéenne ("GUINEA") d'un template multi-pays initialement développé pour le marché italien (régulateur ADM, dispositifs ADM-spécifiques RUA, Anagrafe). Les labels JSON, les classes CSS, le wording disclaimer d'âge italien sont restés. Cela ne pose pas de problème pour le visiteur non-inscrit (chaînes non affichées), mais (1) signale un manque de localisation profonde, (2) suggère qu'après login l'utilisateur peut tomber sur des écrans italiens, (3) pose la question de la responsabilité éditoriale et juridique de l'opérateur (qui contrôle les contenus côté CMS guinéen ? Le concessionario italien ou une entité guinéenne séparée ?).

  • Impact attendu :

Pour le visiteur non-inscrit : faible (chaînes non affichées). Pour l'utilisateur inscrit : risque d'écrans en italien dans certains parcours (auto-exclusion, vérification documents, recovery). Pour l'audit trust : signal d'attention. Pour Legal-check : à clarifier, quelle est l'entité opératrice réelle ? Bet224 est-il un concessionario indépendant titulaire d'agrément ARSJPA, ou un white-label d'un opérateur italien avec ARSJPA délégué ? L'agrément ARSJPA porte-t-il sur l'entité guinéenne ou l'entité italienne ?

  • Root cause :

Plateforme technique white-label probablement fournie par un éditeur italien (SKS365 / Skill On Net / similaire, non sourcé en session). Adaptation marché GN limitée aux contenus visibles et au branding. Couche profonde (labels backoffice, modales internes) non traduite.

  • Sévérité : moderate
  • Route(s) : sport-home, sport, casino, promotions
  • Source primaire :
  • sport-home.raw.html:353 : <a class="cg-cookies-more-info" href="/external_cms/pdf/Cookies_Policy.pdf" target="_blank">Plus d'informations</a>
  • Le lien ouvre un PDF dans un nouvel onglet. PAS de page HTML cookie policy navigable accessible par URL canonique (/cookies, /cookie-policy non testés mais cohérent avec le pattern soft 404 transverse F-TRUST-01-11).
  • Le bandeau cookie indique pourtant explicitement la présence de "cookies de profilage tiers" (sport-home.raw.html:350), ce qui implique une obligation typique de listing détaillé (fournisseurs tiers, finalités, durées), non vérifiable côté HTML.
  • Source visuelle : - screenshots/sport-home/desktop.png bandeau top : lien bleu "Plus d'informations" à droite du bouton "OK".
  • Constat :

L'utilisateur souhaitant comprendre les cookies utilisés est renvoyé vers un PDF externe au lieu d'une page HTML navigable. Friction de lecture (téléchargement, ouverture lecteur PDF, pas de search-in-page natif efficace, pas de lien profond vers une section), accessibilité dégradée (PDF moins accessible qu'HTML pour les lecteurs d'écran, pas de zoom CSS responsive). Pour les "cookies de profilage tiers" mentionnés, le détail des fournisseurs (Google Analytics G-VLQSP6C303 visible en code, GTM-MZ7JZBPZ visible en code, autres ?) n'est pas vérifiable côté front sans télécharger le PDF.

  • Impact attendu :

Pour l'utilisateur : friction maximale pour comprendre ses cookies = pratique non-conforme aux standards de transparence moderne. Pour l'accessibilité (cf cross-angle A11Y) : PDF non navigable au clavier facilement, friction lecteur d'écran. Pour le SEO : contenu non indexé HTML. Pour la conformité (cadre GN à confirmer) : à valider Legal-check, mais standard international = page HTML navigable obligatoire.

  • Root cause :

Politique cookie héritée du template italien sous forme de PDF. Pas de portage HTML pour la déclinaison GUINEA. Le PDF est lui-même probablement obsolète (à vérifier date du PDF lors d'un crawl ciblé).

Cross-angle dependencies

  • F-TRUST-01-01 (logo ARSJPA sans alt) recoupe [REF: DEEP-A11Y-01] (règle axe-core image-alt). Si DEEP-A11Y-01 a remonté une violation image-alt sur le node <img src="...ARSJPA.png">, R-TRUST-01-05 et la reco A11Y associée doivent être fusionnées par assemble_audit.py (même correctif, mêmes routes).
  • F-TRUST-01-04 (jeu responsable absent) recoupe [REF: DEEP-CONV-01/F-CONV-01-02] (absence lien jeu responsable footer mesurée côté CONV). R-TRUST-01-02 et R-CONV-01-02 traitent le même périmètre via 2 approches (CONV = ajouter liens footer, TRUST = créer les pages cible). À fusionner en reco unique "Créer pages + linker depuis footer" dans assemble_audit.py.
  • F-TRUST-01-06 (footer caché) recoupe [REF: DEEP-CONV-01/F-CONV-01-04] et probablement [REF: DEEP-UX-01/F-XX] (pattern accordion bottom = anti-pattern UX) et [REF: DEEP-A11Y-01/F-XX] (navigation clavier complexifiée par collapse + lazy). R-TRUST-01-03 traite la solution structurelle. Cross-angle convergence forte, à fusionner.
  • F-TRUST-01-07 (mention âge + age-gate absent) recoupe [REF: DEEP-CONV-01/F-CONV-01-02] (forbidden_pattern). R-TRUST-01-04 = solution complète, R-CONV-01-02 = solution partielle (mention seule). À fusionner avec priorité R-TRUST-01-04 (plus complet : age-gate + mention).
  • F-TRUST-01-08 (faux positifs SIRET/VAT) recoupe [REF: DEEP-CONV-01] indirectement (détecteurs partagés). La reco R-TRUST-01-08 inclut un patch détecteur v1.3 à propager côté toolkit (cross-cutting infra, pas spécifique bet224).
  • F-TRUST-01-09 (contact absent) recoupe [REF: DEEP-CONV-01/F-CONV-01-06]. Reco R-TRUST-01-09 = même périmètre que R-CONV-01-06. À fusionner.
  • F-TRUST-01-10 (cookie banner) recoupe [REF: DEEP-CONV-01/F-CONV-01-08] (même finding angle CONV). R-TRUST-01-06 et R-CONV-01-XX = même action. À fusionner.
  • F-TRUST-01-13 (wagering invisible) recoupe [REF: DEEP-CONV-01/F-CONV-01-01] (promesses de gain interdites). R-TRUST-01-07 et R-CONV-01-01 sont complémentaires : R-CONV traite le wording forbidden, R-TRUST traite l'absence de T&C accessibles. À garder distinctes mais référencer mutuellement.
  • F-TRUST-01-14 (cookie policy PDF) recoupe [REF: DEEP-A11Y-01] (PDF moins accessible que HTML pour lecteurs d'écran). Cross-angle léger, pas de fusion nécessaire.
  • R-TRUST-01-01 (Legal-check + obtention client) est le PRÉALABLE à toutes les autres recos TRUST. Tant que R-TRUST-01-01 n'est pas exécutée, tous les conformite_legale: false des recos R-TRUST-01-02 à R-TRUST-01-11 doivent rester false. Une fois Legal-check rendu, repasser les recos en true selon retour. Escalade obligatoire au red team Legal-check pour arbitrage final.

Limites

  • Statut d'agrément Bet224 auprès de l'ARSJPA non vérifié : la liste officielle "Plateformes agréées" sur arsjpa.gov.gn n'a pas été extraite en session (cf site-context.yaml external_authorities[0].caveat). Vérification requise par Legal-check + client (cf R-TRUST-01-01).
  • Contenu des pages CGU + Politique de confidentialité non vérifié : le footer pointe vers /promo/tutte/bet224_politique_confidentialite et /promo/tutte/bet224_conditions_generales, URLs non crawlées dans cette passe. Contenu réel inconnu, donc impossible d'auditer la conformité substantielle. À ajouter au crawl v2.
  • Cadre réglementaire guinéen non sourcé : seuil d'âge légal, mentions obligatoires en pied de page, cadre data / consentement cookies, cadre publicitaire gambling, dispositif d'auto-exclusion centralisé (équivalent RUA italien existe-t-il en GN ?). Tous ces points sont en site-context.yaml to_confirm et bloquent le passage de conformite_legale: false à true sur les recos TRUST. À sourcer Legal-check.
  • Raison sociale opérateur non identifiée : site-context.yamlbrand.canonical_legal: "". Bloque la rédaction finale des copy-ready des recos R-TRUST-01-02 (mentions légales), R-TRUST-01-03 (disclaimer footer), R-TRUST-01-08 (identifiants), R-TRUST-01-09 (contact). À obtenir client.
  • Géo-restriction d'accès non auditable : aucune source crawl ne permet d'évaluer si Bet224 applique un blocage géographique (juridictions où l'offre serait illégale, ex. accès depuis pays voisins où gambling interdit). Cf site-context.yaml to_confirm. À cadrer Legal-check + direction.
  • Parcours utilisateur inscrit non audité : les écrans après login (où les chaînes italiennes hard-codées sont susceptibles d'apparaître, cf F-TRUST-01-12) n'ont pas été crawlés. Audit limité au visiteur anonyme.
  • Screenshots mobile absents : seuls les screenshots desktop (1440px) sont disponibles. Les findings trust transverses (cookie banner, mention âge, age-gate, footer caché) sont probablement aggravés sur mobile (typiquement < 50 % du viewport disponible). Cf cross-angle MOBILE pour analyse spécifique. Patch crawl v2 = ajouter mobile screenshots.
  • Modal d'inscription / dépôt / cashout non auditée : aggregate.forms_total_all_routes = 0, signifiant que le funnel signup-deposit (où les obligations KYC, vérification d'âge réelle, consent data, T&C bonus à l'inscription se jouent) n'est pas couvert. Audit trust limité aux pages publiques.
  • Détecteur conversion-signals v1.2 ne capture pas les cookie banners : F-TRUST-01-10 est documenté par observation visuelle directe sur screenshot, pas par signal automatique. Patch détecteur v1.3 à prévoir (cross-angle infra).
  • Aucune analytics de comportement utilisateur fournies par le client : impossibilité de mesurer combien d'utilisateurs ouvrent réellement le footer caché, combien refusent les cookies (ils ne peuvent pas refuser dans la version actuelle), combien quittent face à l'absence d'info opérateur. Trust findings basés sur observation structurelle, pas sur impact mesuré utilisateur.
  • Vérification PDF Cookies_Policy.pdf : le contenu, la date et la pertinence du PDF référencé /external_cms/pdf/Cookies_Policy.pdf n'ont pas été vérifiés (pas dans le crawl). À ajouter v2.
  • Pages tierces du module promo : URL /promo/tutte/bet224_politique_confidentialite et /promo/tutte/bet224_conditions_generales non crawlées, donc impossible de savoir si ce qu'elles servent EST une politique de confidentialité valide ou un placeholder. Fragilité supplémentaire à signaler.

Angle : UI

Persona

Source : site-context.yaml voice_and_tone.persona_primary.

  • sport-home : parieur sportif en Guinée, très majoritairement mobile, intéressé en priorité par le football. Sur cette route il atterrit pour scanner l'offre du jour. La page lui présente un logo Bet224 stylisé multicolore (jaune / vert / rouge), un bandeau cookies sombre, deux bannières promo jaunes (1 000 000 GNF, 10 % cashback), une nav sport rouge et des tableaux de cotes denses. Premier contact identité visuelle : surchargé et concurrentiel.
  • sport : même persona, intent "construction d'un pari" sur une compétition. Densité d'information maximale (sidebar gauche + tableau central + ticket droit). La palette compte 14 backgrounds distincts mesurés cross-elements (design-system/sport.jsonaggregated.unique_background_colors = 14), record du POC.
  • casino : persona élargie (joueur casino en ligne). Carrousels horizontaux où chaque carte de jeu Spribe (Aviator / Dice / Goal / Plinko / Mines / Mini Roulette / Hilo) introduit sa propre couleur de fond saturée. La page est aussi la seule à dépasser 1 fold (screenshots/index.jsoncaptures[2].desktop_full_height_px = 1629). Effet ressenti : kaléidoscope, pas de hiérarchie d'élévation.
  • promotions : persona en intent "découverte d'un bonus" avant inscription. Trois cartes promo MAXI BONUS / CASHBACK SPORT / WELCOME SPORT avec deux familles concurrentes : CTA secondaire vert (EN SAVOIR PLUS) et CTA primaire rouge OUVRIR PIED DE PAGE fixé en bas. Hiérarchie visuelle des CTAs ambiguë (cf cross-angle CONV).

Synthèse exécutive

  • Le design system observé est chaotique cross-route : 12 couleurs de texte uniques + 18 couleurs de fond uniques + 12 tailles de police + 11 border-radius distincts + 17 valeurs de padding-left mesurées. Source : design-system/index.jsonaggregate.colors.unique_foreground_count = 12, aggregate.colors.unique_background_count = 18, aggregate.typography.unique_font_size_count = 12, aggregate.borders.border_radius[].value (11 entrées), aggregate.spacing.padding_left[].value (12 entrées). Aucun brand guideline fourni par le client donc la cohérence interne est l'unique référentiel.
  • Brand color split : trois couleurs concurrentes occupent simultanément le rôle de "primary action" sur le même viewport (#b21116 rouge brand 33 fonds + #40b840 vert clair 22 fonds + #0e6634 vert foncé 10 fonds). Source : design-system/index.jsonaggregate.colors.background_top[2,3,5]. Header sport-home : bouton Login rouge à côté du bouton Inscription vert, sans relation visuelle de hiérarchie (primary vs secondary indistinguable).
  • Échelle typographique non modulaire avec valeurs sub-pixel : 10 / 10.5 / 12 / 12.5 / 12.6 / 13 / 14 / 14.4 / 15 / 16 / 18 / 24 px, soit 10 valeurs entre 10 px et 16 px. Source : aggregate.typography.font_sizes[].value. Les paliers 10.5 / 12.5 / 12.6 / 14.4 px sont des artefacts de calcul em x font-size parent, signe d'absence de tokens typographiques déclarés.
  • Spacing et radius ad-hoc avec valeurs sub-pixel et plages exotiques : padding 1.5 / 1.8 / 3.75 / 4.5 / 7.5 px (aggregate.spacing.padding_top[].value), border-radius 0 / 2.5 / 3 / 4 / 5 / 6 / 8 / 12 / 100 % / 600 px / 999 px (aggregate.borders.border_radius[].value). Cohabitation 100 % et 999 px et 600 px pour produire des formes circulaires équivalentes = absence de convention partagée.
  • Hiérarchie d'élévation absente : aggregate.effects.box_shadows[] ne contient qu'une seule valeur, "none" (count 496). Aucune ombre portée mesurée sur les 4 routes. Les cards de jeux casino, cartes de cotes, cartes de promo, header, footer reposent uniquement sur des contrastes de couleurs pour se distinguer. Sur un site dense en informations (notamment casino et sport), c'est un déficit de lisibilité.
  • Logo Bet224 stylisé multicolore (jaune / vert / rouge) en haut à gauche : porte simultanément les trois couleurs concurrentes du système. Source visuelle : screenshots/sport-home/desktop.png zone x=15-145, y=35-70. Effet ressenti : le logo lui-même brouille la lecture de la hiérarchie des CTAs.

Findings

F-UI-01-01 : Brand colors concurrentes pour le rôle CTA primaire (rouge + 2 verts)

  • Sévérité : serious
  • Route(s) : sport-home, sport, casino, promotions
  • Source primaire :
  • design-system/index.jsonaggregate.colors.background_top[2].value = "rgb(178, 17, 22)" (#b21116), count = 33, contexts = ["[class*='btn']", "[role='button']", "a", "button", "li"]
  • design-system/index.jsonaggregate.colors.background_top[3].value = "rgb(64, 184, 64)" (#40b840), count = 22, contexts = ["[class*='btn']", "[role='button']", "a", "button"]
  • design-system/index.jsonaggregate.colors.background_top[5].value = "rgb(14, 102, 52)" (#0e6634), count = 10, contexts = ["button"]
  • design-system/index.jsonaggregate.colors.background_top[4].value = "rgb(255, 0, 0)" (#ff0000), count = 15, contexts = ["[class*='badge']"] (rouge pur supplémentaire pour badges, n'utilise pas le rouge brand #b21116)
  • Source visuelle : - screenshots/sport-home/desktop.png zone x=1245-1310, y=35-75 : bouton Login fond rouge #b21116 à côté du bouton Inscription fond vert #40b840. Aucune hiérarchie visuelle (mêmes dimensions, mêmes radius, mêmes poids typographiques).
  • screenshots/promotions/desktop.png zone x=735-855, y=485-525 : CTAs EN SAVOIR PLUS en vert #0e6634 (vert foncé, contexte cards promo). En bas droite x=575-720, y=535-570 : OUVRIR PIED DE PAGE en rouge #b21116. Trois rôles d'action coexistent en même viewport sans clé de lecture.
  • screenshots/sport-home/desktop.png zone x=10-260, y=80-100 : nav sports Sports / Virtuel / Promo / Casino avec Sports en rouge #b21116. Le rouge sert simultanément à "primary CTA" (Login), à "rubrique active" (Sports), à "badge" (#ff0000), à "labels d'alerte ticket".
  • Constat :

Trois couleurs distinctes occupent simultanément le rôle de couleur d'action / primary CTA : rouge brand #b21116, vert clair #40b840, vert foncé #0e6634. Sur le header sport-home, le bouton Login (rouge) et le bouton Inscription (vert) sont visuellement de même importance, alors que Inscription est l'action de conversion prioritaire pour un site de paris (objectif d'acquisition). Aucune convention "primary / secondary / destructive" n'émerge. Le rouge sert simultanément à signaler l'action principale, l'item de navigation actif, le badge d'alerte (avec deux nuances de rouge différentes en plus, #b21116 brand vs #ff0000 pur), ce qui dilue la signification.

  • Impact attendu :

Pour le persona parieur mobile primaire, la hiérarchie des actions n'est pas lisible au premier regard. Le CTA de conversion principal (Inscription) est en compétition visuelle directe avec Login, qui est une action utilisateur déjà-acquis. Conséquence probable : taux de clic Inscription diminué (à mesurer si analytics disponibles). Sur les routes casino et promotions, la multiplication des accents colorés réduit aussi la rétention du chemin de lecture.

  • Root cause :

Absence de design tokens couleur (--color-primary, --color-success, --color-danger) déclarés explicitement. Les CSS custom properties ne sont pas extractibles avec analyze_design_system.py v1.0 qui ne capture que les computed styles (cf schemas-product-audit-v1.0.md limites connues design-system). Les couleurs sont vraisemblablement écrites en dur dans plusieurs fichiers CSS, sans convention partagée.

F-UI-01-02 : Échelle typographique non modulaire avec 10 valeurs sub-16px et artefacts sub-pixel

  • Sévérité : serious
  • Route(s) : sport-home, sport, casino, promotions
  • Source primaire :
  • design-system/index.jsonaggregate.typography.unique_font_size_count = 12
  • design-system/index.jsonaggregate.typography.font_sizes[].value énumérées : 10px (count 147), 12px (134), 16px (54), 10.5px (35), 14px (31), 15px (27), 18px (23), 24px (15), 12.6px (14), 13px (12), 12.5px (2), 14.4px (2)
  • Per-route : design-system/casino.json route signalée 10 sizes uniques (design-system/index.jsonper_route[2].unique_font_sizes = 10), sport-home 8, sport 8, promotions 9
  • Source visuelle : - screenshots/sport-home/desktop.png zone x=10-260, y=80-100 : nav sports rendue en taille très fine (correspond à 10px ou 10.5px, le plus fréquent dans le set, count 147+35). Lisibilité limite sur viewport desktop 1440.
  • screenshots/casino/desktop.png zone y=350-500 (carrousel Top 10) : les numéros 1-2-3-4-5 en énorme (estimés ~72-96 px, non capturés par le sampler car déclarés en em ou Image / SVG), alors que les libellés Top Providers etc. sont en 16-18 px. Saut typographique extrême sans niveaux intermédiaires.
  • Constat :

L'échelle typographique compte 12 valeurs cross-route mesurées, dont 10 entre 10 px et 16 px (10px, 10.5px, 12px, 12.5px, 12.6px, 13px, 14px, 14.4px, 15px, 16px). Les valeurs 10.5px, 12.5px, 12.6px, 14.4px sont caractéristiques d'un calcul em ou rem appliqué à un parent dont la taille est variable, signe d'absence de tokens typographiques explicites. La valeur dominante 10px (count 147) est plus petite que la recommandation universelle ergonomie web 12 px minimum pour body, et plus petite que le default browser 16 px par un facteur 1.6 fois.

  • Impact attendu :

Lisibilité dégradée pour la nav, les libellés de catégorie, les méta-informations (heures, ratios). Sur mobile, où le persona primaire est concentré, un 10px rendu sur écran réduit devient quasiment illisible. La multiplication des niveaux dans la plage 10-16 px empêche aussi le designer d'établir une hiérarchie claire (qu'est-ce qui est un label H4 vs un caption vs un body small ?). Implication a11y croisée : sur axes WCAG 1.4.4 (reflow / zoom) et 1.4.12 (text spacing), une typographie en sub-pixel est fragile au redimensionnement.

  • Root cause :

Cocktail probable : reset CSS héritage (Bootstrap legacy font-size: .875rem qui donne 14px x 0.9 = 12.6px sur certains containers), absence de design tokens --font-size-xs / sm / base / md / lg / xl, multiples feuilles CSS empilées sans réconciliation.

F-UI-01-04 : Onze valeurs de border-radius distinctes, conventions cercle multiples

  • Sévérité : serious
  • Route(s) : sport-home, sport, casino, promotions
  • Source primaire :
  • design-system/index.jsonaggregate.borders.border_radius[] énumérés (count décroissant) : 0px (329), 4px (51), 3px (32), 2.5px (26), 999px (14), 100% (12), 5px (11), 12px (9), 6px (7), 8px (4), 600px (1)
  • Soit 11 valeurs uniques de radius dans le système.
  • Boutons et inputs partagent au moins 4 conventions distinctes : 4px (count 51 sur a, button, input), 3px (32 sur button, input, [class*='btn'], [class*='badge']), 2.5px (26 sur [class*='btn'], [class*='cta'], a, button, input, select), 12px (9 sur button, [class*='button']).
  • Trois conventions distinctes pour produire un cercle : 999px (14 sur [class*='button'], [role='button'], button), 100% (12 sur [role='button'], a, li), 600px (1 sur a).
  • Source visuelle : - screenshots/sport-home/desktop.png zone x=1245-1395, y=35-75 : boutons Login (rouge) et Inscription (vert) avec coins arrondis légers (radius ~4px estimé). Sur la même page, zone x=665-825, y=100-130 : bouton 2 COLONNES à droite a un radius nettement plus prononcé (~12 px estimé). Deux boutons CTA principaux + un toggle layout = trois conventions.
  • screenshots/promotions/desktop.png zone y=485-525 : EN SAVOIR PLUS (cards promo) radius ~2.5px (presque carré). vs Login x=1245-1310, y=35-75 radius 4px. Boutons d'actions différents dans la même viewport avec radius différents.
  • screenshots/casino/desktop.png zone y=120 ligne Most Wanted / Alexander's Fortune / Aviator / AVAJET : badges ronds des jeux (radius 100% probable). Mais zone y=140 (icônes joueurs avatars) : autre radius rond. Cohabitation 100% et 999px invisible à l'œil mais inutile à coder.
  • Constat :

Onze valeurs distinctes de border-radius mesurées cross-route. Aucune logique d'échelle (les valeurs 2.5px, 3px, 4px, 5px, 6px, 8px sont toutes représentées dans des contextes recouvrants button / a / input). Trois conventions pour générer un cercle parfait (999px, 100%, 600px) avec un cas singleton à 600px qui suggère un copier-coller hasardeux. Boutons CTA principaux (Login, Inscription) à 4px mais d'autres boutons CTA [class*='cta'] à 2.5px.

  • Impact attendu :

Incohérence visuelle perçue subliminalement (le site "fait artisanal" car ses formes ne sont pas accordées). Dette technique : chaque nouveau composant doit choisir parmi 11 valeurs sans guideline. Risque de divergence accrue avec le temps.

  • Root cause :

Pas de design tokens radius (--radius-sm, --radius-md, --radius-pill). Valeurs sub-pixel 2.5px viennent probablement d'un em x base parent atypique (signe que le calcul est dynamique, pas un choix designer). 999px et 100% cohabitent par habitudes CSS distinctes des contributeurs.

F-UI-01-03 : Quatre familles de polices détectées, trois stacks system parasites

  • Sévérité : moderate
  • Route(s) : sport-home, sport, casino, promotions
  • Source primaire :
  • design-system/index.jsonaggregate.typography.unique_font_family_count = 4
  • design-system/index.jsonaggregate.typography.font_families[] :
  • "DMSans, sans-serif" count 490, contexts ["a", "body", "footer", "h2", "h5", "main"] (famille principale réelle)
  • "-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Oxygen-Sans, Ubuntu, Cantarell, \"Helvetica Neue\", sans-serif" count 3, contexts ["html"] (stack system sur html)
  • "\"Open Sans\", Arial, sans-serif" count 2, contexts ["body"] (Open Sans déclaré sur certains body)
  • "-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Oxygen, Ubuntu, Cantarell, \"Open Sans\", \"Helvetica Neue\", sans-serif" count 1, contexts ["html"] (deuxième stack system légèrement différent)
  • Source visuelle : - Non observable au pixel près sur les screenshots (les 3 stacks parasites représentent 6 nodes au total vs 490 pour DMSans, donc visuellement absorbés par le rendering principal). Mais la déclaration de 4 familles distinctes sur les éléments racines html et body est mesurée structurellement.
  • Constat :

DMSans est la police principale réelle du site (count 490, présente sur body, headings, links, footer, main). Trois autres stacks de polices sont déclarés simultanément, dont deux variantes presque identiques du stack system-ui sur html (différence d'orthographe entre Oxygen-Sans et Oxygen) et un fallback "Open Sans", Arial, sans-serif sur certains body. Aucun de ces fallbacks ne s'applique en pratique (DMSans charge correctement), mais leur cohabitation dans la cascade indique l'empilement de plusieurs frameworks CSS non réconciliés (réinitialisation html { font: ... } Bootstrap + autre framework + override DMSans).

  • Impact attendu :

Aucun rendu dégradé visible si DMSans charge correctement. Impact réel : poids CSS supplémentaire (multiples déclarations conflictuelles), risque de FOUT (flash of unstyled text) plus marqué si DMSans tarde à charger (le fallback Helvetica Neue ou Open Sans est très différent métriquement de DMSans, donc shift visible). Dette de maintenance : un futur designer ne sait pas quelle famille est canonique.

  • Root cause :

Empilement de frameworks CSS : reset Bootstrap, surcouche template, ajout custom DMSans. Aucune purge des règles intermédiaires.

F-UI-01-05 : Spacing ad-hoc avec valeurs sub-pixel et 12 valeurs distinctes de padding-left

  • Sévérité : moderate
  • Route(s) : sport-home, sport, casino, promotions
  • Source primaire :
  • design-system/index.jsonaggregate.spacing.padding_left[] 12 valeurs : 0px (312), 6px (44), 8px (35), 5px (18), 24px (16), 7.5px (13), 9px (13), 20px (12), 10px (12), 12px (11), 15px (8), 16px (2)
  • aggregate.spacing.padding_right[] 14 valeurs distinctes (mêmes patterns), introduisant aussi 17.5px et 28px
  • aggregate.spacing.padding_top[] 15 valeurs distinctes dont sub-pixel 1.5px, 1.8px, 3.75px, 4.5px, 7.5px, 2.5px
  • aggregate.spacing.padding_bottom[] 15 valeurs distinctes
  • Valeurs hors échelle 4/8 mesurées : 1.5px, 1.8px, 2.5px, 3px, 3.75px, 4.5px, 5px, 6px, 7.5px, 9px, 10px, 12.0938px (margin), 15px, 19.3594px (margin), 17.5px
  • Source visuelle : - screenshots/sport-home/desktop.png zone y=80-100 (nav sports) vs y=100-130 (sous-nav PREMATCH / LIVE / MULTIBET) : le rythme vertical change visiblement (compact vs aéré) sans transition. Source paddings distincts probables (2px sur button vs 8px sur a).
  • screenshots/casino/desktop.png zone y=130-220 (cards Spribe Games) : cards ont des paddings internes variables d'une catégorie à l'autre (la card Aviator a un padding bottom différent du card Dice).
  • Constat :

Le système de spacing ne suit aucune échelle modulaire (multiples de 4 ou 8 pixels canonique). Les valeurs sub-pixel comme 1.5px, 1.8px, 3.75px, 4.5px, 7.5px, 12.0938px, 19.3594px indiquent que les paddings et marges sont calculés via em ou pourcentages dans une grille variable, sans tokens explicites. La fréquence de 0px (count 312 sur padding-left, 304 sur padding-bottom) masque le bruit, mais sur les éléments interactifs (boutons, liens), 12 à 15 valeurs uniques de padding cohabitent.

  • Impact attendu :

Rythme visuel inconsistant cross-pages. Lors d'ajouts futurs de composants, aucune référence partagée, donc chaque nouvelle classe ajoute encore une valeur unique. Pas d'effet bloquant utilisateur immédiat, mais dette long terme et difficulté de maintenance.

  • Root cause :

Empilement Bootstrap (utilities .p-1, .p-2 en rem qui produisent du sub-pixel selon font-size hérité) + classes utilitaires custom + styles inline. Aucun token spacing déclaré côté design system observable.

F-UI-01-06 : Hiérarchie d'élévation absente, zéro box-shadow mesurée

  • Sévérité : moderate
  • Route(s) : sport-home, sport, casino, promotions
  • Source primaire :
  • design-system/index.jsonaggregate.effects.box_shadows[] contient une seule entrée : {"value": "none", "count": 496, "contexts": ["body", "footer", "h2", "h5", "html", "main"]}. Aucune autre valeur d'ombre détectée sur 496 observations cumulées.
  • Pour mémoire, aggregate.effects.opacity[] contient 5 valeurs distinctes (1, 0.5, 0, 0.35, 0.7), mais l'opacité n'est pas un substitut à l'élévation.
  • Source visuelle : - screenshots/sport-home/desktop.png : le bandeau cookies, le header, la sous-nav, le carrousel de bannières promo, les Tournois à la une, le tableau Découvrir n'ont aucune ombre portée. Les sections se distinguent uniquement par changements de fond (blanc sur gris #f6f6f6 sur blanc). Aucune carte n'est élevée.
  • screenshots/casino/desktop.png zone y=130-220 (Spribe Games) : les 7 cards de jeux sont juxtaposées sans relief. Les fonds colorés saturés portent toute la charge visuelle, sans ombre pour les détacher.
  • screenshots/promotions/desktop.png zone y=265-540 (cards MAXI BONUS / CASHBACK SPORT / WELCOME SPORT) : 3 cards alignées, fond gris uniforme, contour invisible, aucune ombre. La hiérarchie repose entièrement sur la typographie et les CTAs internes.
  • Constat :

Aucune box-shadow n'est appliquée nulle part sur les 4 routes (aggregate.effects.box_shadows[] n'a qu'une valeur "none"). Un système de design moderne courant prévoit au moins 3 niveaux d'élévation (card de base, card hover, modal / popover). Bet224 n'en a aucun. Conséquence : pour distinguer une carte interactive d'un bloc passif, le site doit empiler des couleurs de fond saturées ou des bordures (cf F-UI-01-04 ci-dessus). Sur les routes denses en cards (casino, promotions, sport tableau de cotes), la lisibilité dépend uniquement du contraste de couleur.

  • Impact attendu :

Densité visuelle peu structurée sur les pages dépassant 1 fold (casino : 1629 px de hauteur scrollable mesurée, screenshots/index.jsoncaptures[2].desktop_full_height_px = 1629). Le scanner visuel ne peut pas distinguer les zones cliquables des zones d'information passive autrement que par couleur. Pour le persona mobile (qui domine), l'absence d'élévation est plus pénalisante encore (les écrans petits compensent traditionnellement par du shadow).

  • Root cause :

Choix design pré-existant (style "flat ultra plat") ou simplement absence de système d'élévation au sens design. Pas observable depuis les inputs disponibles.

F-UI-01-07 : Logo Bet224 stylisé multicolore (4 couleurs) entre en compétition avec la palette CTAs

  • Sévérité : moderate
  • Route(s) : sport-home, sport, casino, promotions
  • Source primaire :
  • screenshots/sport-home/desktop.png zone x=15-145, y=35-70 : logo Bet224 rendu avec lettres en couleurs distinctes (B noir / e jaune / t noir / 2 jaune / 2 vert / 4 rouge, en italique). Visible à l'identique sur les 4 routes (template header commun, cf cross-angle DEEP-A11Y-01 F-A11Y-01-01).
  • site-context.yamlbrand.canonical_display = "Bet224" (casing à confirmer post-crawl, marqué [A VERIFIER]) ; pas d'asset logo, pas de palette officielle, pas de guideline d'usage.
  • Couleurs du logo recoupent les 3 brand colors concurrentes : rouge #b21116 / vert #40b840 / jaune (non capturée par aggregate.colors car probablement image PNG, pas couleur CSS).
  • Source visuelle : - screenshots/sport-home/desktop.png zone x=15-145, y=35-70 (logo) vs zone x=1245-1395, y=35-75 (CTAs Login rouge + Inscription vert) : le logo utilise simultanément les couleurs des deux boutons CTA. Quand l'œil scanne du logo vers les CTAs, il n'a pas de signal différenciant "logo = identité" vs "bouton = action".
  • screenshots/sport/desktop.png : même logo, même CTAs, même cohabitation chromatique.
  • Constat :

Le logo Bet224 embarque 4 couleurs (noir + jaune + vert + rouge en italique pour les chiffres 224). Ces couleurs sont les mêmes que celles utilisées pour les CTAs (Login rouge brand, Inscription vert brand). Conséquence visuelle : le logo, normalement un point d'ancrage identitaire stable, devient un élément concurrentiel des CTAs. Aucune charte client ne précise si cette stylisation est une variante autorisée ou un PNG historique à refondre. Le site-context flagge déjà forms_to_avoid = ["bet224", "BET224", "Bet 224", "bet-224"] mais ne dit rien sur la stylisation couleur.

  • Impact attendu :

Le logo n'aide pas à fixer une couleur brand prioritaire (au contraire, il en utilise 3-4). Pour un nouveau visiteur, l'identité visuelle est floue (n'est-ce pas un site rouge ? vert ? jaune ?). Effet de confiance dégradé sur un site YMYL gambling où la signalisation visuelle de l'opérateur compte.

  • Root cause :

Logo PNG legacy (référencé external_cms/GUINEA/img/logo-bet-224.png dans le DOM, cf axe-results/sport-home/desktop.jsonviolations[1].nodes[0].target = ["a[href=\"/\"] > img"]). Probablement design initial sans charte couleur formalisée.

F-UI-01-08 : Route casino concentre la plus haute densité chromatique du POC (kaléidoscope)

  • Sévérité : moderate
  • Route(s) : casino
  • Source primaire :
  • design-system/index.jsonper_route[2].route_slug = "casino", per_route[2].unique_background_colors = 9, per_route[2].unique_colors = 8, per_route[2].unique_font_sizes = 10 (record du POC pour font_sizes)
  • Comparaison cross-route : per_route[0] sport-home 10 bg / 9 fg / 8 sizes, per_route[1] sport 14 bg / 10 fg / 8 sizes, per_route[2] casino 9 bg / 8 fg / 10 sizes, per_route[3] promotions 7 bg / 7 fg / 9 sizes
  • screenshots/index.jsoncaptures[2].desktop_full_height_px = 1629 (seule route POC dépassant 1 fold de loin ; sport-home/sport plafonnent à 900px, promotions à 950px)
  • Source visuelle : - screenshots/casino/desktop.png zone y=130-220 (Spribe Games) : 7 cards juxtaposées avec 7 couleurs de fond saturées différentes (Aviator rose / Dice violet / Goal vert / Plinko bleu marine / Mines bleu turquoise / Mini Roulette vert sapin / Hilo jaune). Aucune de ces 7 couleurs n'est dans la palette brand mesurée (aggregate.colors.background_top), elles sont probablement portées par des images de fond (background-image) non décomposées par analyze_design_system.py (qui ne capture que backgroundColor, pas backgroundImage).
  • screenshots/casino/desktop.png zone y=240-340 (Top 10) : numéros 1-5 en rouge brand très grand, fond image (carrousel Hot to Burn, Queen of Gods, Mining Hot, Book of..., Lobster Bob).
  • screenshots/casino/desktop.png zone y=370-500 (Evolution) : carrousel BlackJack répété 7 fois avec photos joueurs (humains visibles).
  • Constat :

Bien que unique_background_colors = 9 mesuré soit similaire aux autres routes, la route casino concentre la plus haute densité visuelle perçue car (a) elle dépasse 1 fold de 81 %, (b) les cards Spribe Games introduisent 7 couleurs supplémentaires non capturées par le sampler (images de fond), (c) elle a le record de unique_font_sizes (10 valeurs) signalant des sauts typographiques importants. La cohabitation des numéros géants Top 10 rouges, des photos humains noir/blanc Evolution, des logos providers gris (The Ear, Evolution, EvoPlay, GAMZIX, NETENT), et des cards saturées Amigo Gaming produit un effet kaléidoscope sans hiérarchie.

  • Impact attendu :

Cognitive load maximal sur la route de découverte des jeux, pénalisant la conversion vers un jeu spécifique. Risque de paralysie de choix. Pour le persona casino (élargi par rapport au persona primary sport), le sentiment "trop d'options non hiérarchisées" peut détourner vers un concurrent. Implication YMYL : densité visuelle élevée + couleurs saturées + animations probables (carrousels auto) peuvent être considérés comme des dark patterns d'engagement (à recouper avec angle CONV et red team Legal-check).

  • Root cause :

Stratégie commerciale "vitrine de catalogue" (montrer le maximum de jeux above-the-fold pour signaler la richesse de l'offre). Conflit avec l'objectif design "hiérarchiser pour faciliter le choix". Pas de page interne pour chaque catégorie qui permettrait de réduire la densité par route.

F-UI-01-09 : Bandeau cookies header full-width avec palette étrangère à la charte (gris + jaune + bleu)

  • Sévérité : moderate
  • Route(s) : sport-home, sport, casino, promotions
  • Source primaire :
  • design-system/index.jsonaggregate.colors.background_top[8].value = "rgb(46, 97, 232)" (#2e61e8), count 4, contexts ["a"] (bleu utilisé sur lien dont probablement Plus d'informations du banner cookies)
  • design-system/index.jsonaggregate.colors.foreground_top[6].value = "rgb(0, 123, 255)" (#007bff), count 22, contexts ["a"] (bleu Bootstrap)
  • design-system/index.jsonaggregate.colors.background_top[11].value = "rgb(128, 128, 128)" (#808080), count 2, contexts ["html"] (gris neutre pas dans la charte brand)
  • design-system/index.jsonaggregate.colors.background_top[12].value = "rgba(0, 0, 0, 0.15)", count 2, contexts ["nav"] (transparency layer header)
  • Source visuelle : - screenshots/sport-home/desktop.png zone x=0-720, y=0-30 (bandeau cookies plein écran top) : fond noir/gris très foncé, texte blanc petit, bouton OK jaune-vert vif (#cae500 estimé, pas dans la palette mesurée donc probablement appliqué inline ou via une feuille externe), bouton Plus d'informations bleu (#2e61e8 ou #007bff Bootstrap).
  • Présence du même bandeau sur les 4 routes (template global).
  • Constat :

Le bandeau cookies en haut occupe la pleine largeur, persiste sur les 4 routes, et utilise une palette étrangère à la charte du site : fond gris très foncé (vs blanc / #f6f6f6 du site), bouton OK jaune-vert (vs verts brand #40b840 ou #0e6634), bouton Plus d'informations bleu (vs absence de bleu dans le reste de la palette CTAs). Le bleu #007bff (count 22) est probablement le bleu Bootstrap par défaut, jamais réécrit. Le banner est probablement injecté par un widget tiers (CMP cookies) non thématisé.

  • Impact attendu :

Premier élément vu (en y=0, full-width) brise l'identité visuelle avant même que l'utilisateur arrive sur le contenu. Sur mobile (où le persona primaire est concentré), ce bandeau occupera proportionnellement encore plus d'espace, repoussant le contenu utile sous le fold. Impact UX et confiance.

  • Root cause :

Widget CMP cookies tiers injecté sans personnalisation visuelle (couleurs par défaut). Pas de feuille de style override appliquée. Cohabite avec le reste du chrome browser (10:53 Dimanche, 24 Mai 2026 visible en y=0 dans la capture, suggérant que la capture est faite avec barre OS visible, pas un défaut du site).

Cross-angle dependencies

  • A11Y (DEEP-A11Y-01) : R-UI-01-01 (réservation rouge #b21116 au primary CTA) ne contredit pas mais ne suffit pas à résoudre [REF: DEEP-A11Y-01/F-A11Y-01-06] (contraste Betbuilder 1.3:1) ni [REF: DEEP-A11Y-01/F-A11Y-01-07] (contraste filtre Sport 2.6:1). Les couleurs incriminées (#212121 background, #83ae30 background, etc. cf DEEP-A11Y-01.md recos A11Y-05 et A11Y-06) doivent être harmonisées dans une seule passe avec la définition des tokens couleurs proposés dans R-UI-01-01. Recommandation pour assemble_audit.py : fusionner R-UI-01-01 + R-A11Y-01-05 + R-A11Y-01-06 en une reco unique "Refonte palette de couleurs avec contrastes AA et tokens primary / success / danger / warning". Le contraste WCAG est l'argument prioritaire (a11y conformité) ; la cohérence brand suit.
  • A11Y (DEEP-A11Y-01) : R-UI-01-08 (personnalisation bandeau cookies) doit être harmonisé avec [REF: DEEP-A11Y-01/R-A11Y-01-13] (englober #cg-barra-cookies dans un landmark <aside role="region"> ou <dialog>). Le CSS override proposé en R-UI-01-08 ne casse pas le landmarking proposé en A11Y mais doit être appliqué en post-traitement DOM, pas en remplacement du wrapping sémantique.
  • CONV (à venir, DEEP-CONV-01) : F-UI-01-01 (brand colors concurrentes pour CTAs) est intrinsèquement un finding CONV aussi. Le CTA Inscription (objectif d'acquisition principal) est dilué visuellement par la cohabitation avec Login. conversion-signals/index.jsonaggregate.primary_cta à vérifier dans DEEP-CONV-01 pour savoir si le détecteur a bien identifié Inscription comme primary_cta ou si le détecteur a élu Login (qui serait alors un faux positif lié à la confusion chromatique). Recommandation pour DEEP-CONV-01 : croiser primary_cta.background_color avec aggregate.colors.background_top pour scorer la concurrence visuelle.
  • MOBILE (à venir, DEEP-MOBILE-01) : F-UI-01-06 (absence box-shadow) sera plus pénalisante sur mobile (le persona primaire) car les écrans réduits compensent traditionnellement la densité visuelle par l'élévation. F-UI-01-02 (taille 10px dominante) sera particulièrement critique sur mobile (lisibilité dégradée). Recommander dans DEEP-MOBILE-01 un mesurage des touch targets et de la lisibilité réelle à 390x844 viewport.
  • TRUST (à venir, DEEP-TRUST-01) : F-UI-01-07 (logo multicolore) recoupe la perception de confiance brand sur un site YMYL gambling. Sur les sites concurrents gambling régulés (sources non extraites en session), le logo opérateur est généralement monochrome ou bicolore strict pour signaler le sérieux. Cross-référencer avec l'analyse conversion-signals/index.jsonaggregate.routes_with_legal_links et routes_with_siret_or_vat (déjà flaggés dans le site-context.yaml facts.to_confirm). La refonte du logo (R-UI-01-07) gagne en priorité si le red team Legal-check confirme une exigence de signalétique opérateur agréé.
  • cross-angle-conflict potentiel : R-UI-01-09 (uniformisation backgrounds Spribe Games) entre en conflit avec un objectif commercial probable du client "vitrine vive". À escalader au red team UX-check pour arbitrage trade-off (cognitive load vs perception d'offre riche). Décision à documenter avant assemblage final.

Limites

  • Mobile non audité : screenshots/index.jsoncaptures[].mobile_path = null sur les 4 routes (POC desktop only). Conséquence : les jugements de hiérarchie visuelle, densité, lisibilité, échelle typographique sont desktop-only. Pour le persona primary (parieur mobile Guinée), un audit mobile complet est indispensable avant livraison FULL. Estimation finding mobile pourrait doubler ou tripler (touch target size, viewport overflow, font-size 10px illisible sur écran réduit).
  • Brand guidelines client absents : site-context.yaml ne contient ni palette officielle, ni typo officielle, ni iconographie, ni guideline d'usage du logo. Tous les jugements de cohérence visuelle reposent sur la cohérence interne observée cross-routes, pas sur un écart à une charte normative. Toute reco UI ci-dessus (notamment R-UI-01-01 sur primary CTA rouge #b21116, R-UI-01-07 sur refonte logo) doit être validée par le client. Si le client a une charte ailleurs (PDF, slide deck), elle est à fournir pour réaliser un audit de conformité.
  • CSS custom properties non extraites : analyze_design_system.py v1.0 ne capture que les computed styles, pas les :root { --token-name } déclarés (cf schemas-product-audit-v1.0.md limites connues design-system). Si Bet224 a déjà des tokens déclarés et juste mal appliqués, l'analyse les manque. Une passe statique v1.2 (cf brief) résoudrait. Lecture manuelle de raw HTML / CSS non effectuée dans ce POC (les fichiers CSS externes ne sont pas dans le crawl, et le <style> inline du raw HTML n'a pas été dépouillé). Le client peut fournir ses sources CSS pour vérification.
  • Sampling design-system plafonné : design-system/index.jsonsampled_selectors[] plafonne à 500 nodes par route (cf code analyze_design_system.py). Sur la route sport (per_route[1].nodes_sampled = 185) et casino (per_route[2].nodes_sampled = 136), le sampler n'épuise pas les nodes mais reste une approximation. Des classes très peu utilisées (par exemple un thème modal qui n'apparaît qu'en interaction) peuvent être manquées.
  • Pas d'analyse des images d'arrière-plan : les cards de jeux casino (Spribe Games, Amigo Gaming) ont leurs couleurs portées par des background-image PNG/SVG, pas par backgroundColor. analyze_design_system.py capture backgroundImage mais ne décompose pas les couleurs internes des images. Conséquence : la palette mesurée sous-estime le chaos chromatique réel de la route casino (les 7 couleurs des cards Spribe Games n'apparaissent pas dans aggregate.colors.background_top).
  • Pas d'analyse des states hover / focus / active : les analyze_design_system.py capture les états par défaut uniquement. Les éventuelles couleurs de hover (CTAs qui s'allument, cards qui s'ombrent) ne sont pas mesurées. Pour un audit UI complet, capturer ces états (V1.2 prévue).
  • Pas de comparaison aux concurrents : aucun benchmark concurrent gambling Guinée fourni en session. Les jugements "lisibilité limite", "kaléidoscope" sont qualitatifs et appuyés sur best-practices génériques UI, pas sur un comparatif sectoriel local. Si le client demande un benchmark, à inclure dans le brief séparé.
  • Pas d'A/B test analytique : aucune analytics fournie en session. Les impacts hypothétiques "conversion Inscription diminuée" sont basés sur best-practice UI, pas sur des données observées Bet224. Si le client fournit GA / mixpanel / amplitude analytics, à inclure pour priorisation affinée.

Angle : UX

Persona

Source : site-context.yaml voice_and_tone.persona_primary = "Parieur sportif en Guinee, tres majoritairement mobile, interesse par le football en priorite".

  • sport-home : parieur sportif Guinée arrivant en intent "consulter l'offre du jour" (résultat probable d'un clic sur l'URL racine puis redirection automatique vers /sport-home). Veut voir rapidement le football à venir, comparer 2-3 cotes, accéder à la liste des matchs live. Le persona est mobile mais le POC ne capture que desktop : extrapolation à valider sur capture mobile.
  • sport : même persona, en intent "construire un pari sur une compétition spécifique". Le widget Betbuilder est mis en avant en sidebar gauche mais sans explication. Le ticket de pari (panel droit) suppose un compte existant.
  • casino : persona élargie (joueur casino en ligne, NON explicité dans persona_primary mais route présente dans l'audit). Carrousels denses de jeux (43 CTAs détectés dans conversion-signals/casino.jsonsummary.ctas_total = 43, dont 23 above-fold), navigation par "rangées" de providers. Route YMYL particulièrement sensible (jeux instantanés type Aviator visibles dès l'above-fold).
  • promotions : persona en intent "découvrir les bonus avant inscription". Page très courte (index.jsonpages[3].word_count = 108), 3 cartes bonus visibles (MAXI BONUS, CASHBACK SPORT, WELCOME SPORT) avec CTAs "EN SAVOIR PLUS" et un visuel header géant "MAXI BONUS, AUGMENTE TES GAINS JUSQU'À 500 %".

Synthèse exécutive

  • Le CTA primaire détecté par analyze_conversion_signals est OUVRIR PIED DE PAGE sur 3 routes sur 4 (sport, casino, promotions) - un toggle de footer collapsé. Source : conversion-signals/index.jsonper_route[1..3].primary_cta_text. Signal direct d'une architecture où les éléments les plus visibles et appelants à l'action ne correspondent pas à l'intent utilisateur (inscription, dépôt, sélection d'un pari).
  • Le footer (<footer id="nascondifooter">) est masqué par défaut via une classe collapse cg-lazy et un bouton "OUVRIR PIED DE PAGE" (rouge, fixed bottom-right, lazy-loaded). Source : raw_html_sport_home ligne 752. Conséquence : mentions légales, politique de confidentialité, conditions générales, infos jeu responsable (si elles existent) sont 2 clics minimum sous le fold, alors que le cadre YMYL gambling impose leur visibilité.
  • Le contenu effectif du footer est lui aussi extrêmement maigre : section "AIDER" avec uniquement 3 liens (Registration, Politique de Confidentialité, Conditions Générales). Source : raw_html_sport_home lignes 761-768. Aucun lien jeu responsable, aucun contact, aucune FAQ, aucune information paiement. Cohérent avec conversion-signals/sport-home.jsondetailed.trust_signals.contact_email_visible = false, contact_phone_visible_in_footer = false, contact_links_count = 0.
  • Aucun <h1> sur les 4 routes (cf [REF: DEEP-A11Y-01/F-A11Y-01-08]). Conséquence UX : aucune promesse claire en above-the-fold pour orienter l'utilisateur ; pour un site multi-verticales (sport, casino, virtuel, promo), l'absence de titre principal détonne avec la densité visuelle (logo + nav + sous-nav + carrousel promo + tabs + listes).
  • Fuite contextuelle visible : le <title> mentionne "Sportcash.com" et le meta name="keywords" cite "Ivory Coast" (source : raw_html_sport.raw.html lignes 25-28). Ce sont des résidus du template d'origine (white-label d'une plateforme italienne déployée en Côte d'Ivoire puis adaptée Guinée). Friction de confiance : un parieur guinéen attentif détecte l'incohérence dès l'onglet du navigateur.

Findings

F-UX-01-01 : Le CTA primaire détecté est OUVRIR PIED DE PAGE sur 3 routes sur 4

  • Sévérité : critical
  • Route(s) : sport, casino, promotions
  • Source primaire :
  • conversion-signals/index.jsonper_route[1].primary_cta_text = "Previous" (sport, en réalité flèche carrousel), per_route[2].primary_cta_text = "OUVRIR PIED DE PAGE" (casino), per_route[3].primary_cta_text = "OUVRIR PIED DE PAGE" (promotions)
  • conversion-signals/casino.jsondetailed.primary_cta.text = "OUVRIR PIED DE PAGE", bbox.x = 1243, bbox.y = 861, width = 182, height = 39, background_color = "rgb(178, 17, 22)", font_size = "12px"
  • conversion-signals/promotions.jsondetailed.primary_cta.text = "OUVRIR PIED DE PAGE", mêmes coordonnées et style
  • HTML observé (raw_html_sport_home ligne 790) : <a id="consultaFooter" data-toggle="collapse" class="consulta-footer fissato accordion-toggle toggle-nascondi" href="#nascondifooter">OUVRIR PIED DE PAGE</a>
  • Source visuelle : - screenshots/casino/desktop.png : bouton rouge "OUVRIR PIED DE PAGE" visible en bas-droite (zone x~1243, y~861) sur capture full-page
  • screenshots/promotions/desktop.png : même bouton en bas-droite (zone x~1243, y~861)
  • screenshots/sport-home/desktop.png : même bouton, présent
  • Constat :

L'algorithme de détection CTA principal (poids visuel : surface × contraste × position) élit ce bouton comme primary_cta. Ce résultat n'est pas un artefact : le bouton est rouge plein (#b21116) sur fond clair, fixé en bottom-right, persistant à toutes les pages. Or sa fonction est de déplier un footer caché, pas de faire avancer l'utilisateur dans son parcours (consulter une cote, s'inscrire, déposer, parier). Aucun CTA "Inscription" ou "Déposer" n'a un poids visuel comparable au-dessus de la ligne de flottaison.

  • Impact attendu :

L'utilisateur novice ne sait pas quoi faire en arrivant. L'oeil est attiré par un bouton rouge persistant qui ne sert qu'à révéler des mentions légales. Conséquence directe sur la conversion : aucune incitation visuelle forte vers un objectif business (inscription, dépôt, pari). Conséquence indirecte sur la confiance YMYL : le bouton le plus saillant de la page est paradoxalement la seule porte d'accès aux infos institutionnelles, comportement contre-intuitif.

  • Root cause :

Le footer entier est en collapse cg-lazy (raw_html ligne 752). Pour le voir, l'utilisateur doit cliquer ce bouton. Le pattern provient probablement du template d'origine où le footer était volumineux et chargé en lazy pour la perf, mais ici il ne contient que 3 liens donc le coût d'affichage permanent serait négligeable. Le bouton n'a pas été retiré quand le footer a été allégé.

F-UX-01-11 : Aucune visibilité du jeu responsable ni de la mention d'âge à l'écran

  • Sévérité : critical
  • Route(s) : sport-home, sport, casino, promotions
  • Source primaire :
  • Grep sur raw_html_sport_home.raw.html (motifs "jeu responsable", "18+", "mineurs", "RESPONSABLE", "conditions de mise", "auto-exclusion") : 0 occurrence
  • conversion-signals/sport-home.jsondetailed.trust_signals.legal_links = [{"text":"Politique de Confidentialité"}, {"text":"Conditions Générales"}] (uniquement 2 liens, pas de "Jeu responsable")
  • conversion-signals/sport-home.jsondetailed.urgency.keywords_detected_count = 0 (pas de countdown faux détecté = OK), mais aussi pas de mention "18+" comptée
  • Cross-référence site-context.yamlforbidden_patterns cite explicitement "absence de lien visible vers jeu responsable / auto-exclusion / limites" et "absence de mention d'age legal" comme dark patterns à proscrire
  • Source visuelle : - screenshots/sport-home/desktop.png, screenshots/sport/desktop.png, screenshots/casino/desktop.png, screenshots/promotions/desktop.png : aucun visuel "18+", aucun pictogramme jeu responsable, aucun lien visible vers ressources d'aide. Le logo ARSJPA est présent dans le header (vu raw_html_sport_home ligne 389) mais discret et sans label.
  • Constat :

Sur les 4 routes auditées, aucun élément n'évoque ni le seuil d'âge légal de pari, ni l'auto-exclusion, ni le jeu responsable, ni le contact d'une ligne d'aide. Le footer (collapsé) n'en parle pas non plus. Pour un site YMYL gambling, c'est la friction la plus forte vis-à-vis du cadre déontologique sectoriel (le seuil exact en Guinée n'est pas sourcé en session, cf site-context.yamlfacts.to_confirm, mais le principe d'affichage est quasi-universel). Le persona ne dispose d'aucune ressource visible pour s'informer ou demander de l'aide.

  • Impact attendu :

UX : impossibilité pour un utilisateur en difficulté de trouver de l'aide. Réputationnel : un site gambling sans visibilité jeu responsable est un signal de qualité dégradé chez les utilisateurs informés. Réglementaire : à cadrer Legal-check, mais quasi-systématiquement un risque dans tout cadre gambling moderne.

  • Root cause :

Adaptation Guinée n'a pas intégré de bloc "Jeu responsable" dans le footer ni dans la sidebar. Logo ARSJPA présent en header mais non documenté.

  • Sévérité : serious
  • Route(s) : sport-home, sport, casino, promotions
  • Source primaire :
  • raw_html_sport_home ligne 752 : <footer class="collapse cg-lazy" id="nascondifooter">
  • raw_html_sport_home lignes 761-768 : section "AIDER" contient uniquement Registration, Politique de Confidentialité, Conditions Générales
  • conversion-signals/sport-home.jsondetailed.trust_signals.legal_links_count = 2, contact_links_count = 0, contact_email_visible = false, contact_phone_visible_in_footer = false, has_siret = false, has_vat_eu = false, has_rcs = false
  • Identique 4 routes (detailed.trust_signals.footer_text_length_chars = 1236 constant)
  • Source visuelle : - screenshots/promotions/desktop.png : bandeau bas montre uniquement "OUVRIR PIED DE PAGE" en rouge. Aucun footer visible en zone fixe.
  • 4 captures vérifient l'absence de footer visible above ou immediately below-fold.
  • Constat :

Le footer existe dans le DOM mais est replié sous une classe collapse cg-lazy + un bouton "OUVRIR PIED DE PAGE". Une fois ouvert, son contenu se résume à : un titre "AIDER", un lien "Registration", un lien "Politique de Confidentialité", un lien "Conditions Générales". Pas de section contact, pas de FAQ, pas d'informations paiements, pas de mentions sur le jeu responsable (alors que site-context.yamlforbidden_patterns cite explicitement "absence de lien visible vers jeu responsable / auto-exclusion / limites" comme dark pattern à proscrire).

  • Impact attendu :

L'utilisateur en intent "trouver le numéro de licence", "contacter le support", "comprendre les conditions de retrait", "vérifier ce site est légal en Guinée" n'a aucune réponse à l'écran ni en sous-écran. Cumulé au pattern collapsed, il faut 2 clics minimum pour obtenir une page d'infos institutionnelle (et il n'y en a que 2 : Politique de Confidentialité + Conditions Générales). Friction de confiance majeure sur un site YMYL gambling.

  • Root cause :

Template hérité d'une installation plus large (champ cg_INSTALLAZIONE = 'GUINEA', ligne 678) où le footer était volumineux. Adaptation Guinée a vidé le footer mais conservé le pattern de masquage.

F-UX-01-04 : Aucun H1 sur 4 routes, hiérarchie informationnelle absente

  • Sévérité : serious
  • Route(s) : sport-home, sport, casino, promotions
  • Source primaire :
  • raw_html_sport_home.raw.html : aucun <h1> détecté (Grep <h1 retourne 0 hit sur le fichier)
  • Idem raw_html_sport.raw.html, raw_html_casino.raw.html, raw_html_promotions.raw.html
  • Seuls <h5> (titres de modales : "Erreur identification", "Connexion") apparaissent dans le DOM
  • Cross-référence axe : [REF: DEEP-A11Y-01/F-A11Y-01-08] ("aucun H1 sur 4 routes, règle axe page-has-heading-one violée")
  • Source visuelle : - screenshots/sport-home/desktop.png : en-dessous du header, on voit directement le carrousel promo + libellés "Tournois à la une" / "Découvrir" qui sont visuellement traités comme titres mais sans markup associé
  • screenshots/casino/desktop.png : "Gains récents", "Spribe Games", "Top 10", "Evolution", "Top Providers", "Amigo Gaming" sont des étiquettes de section sans hiérarchie marquée
  • screenshots/promotions/desktop.png : aucun titre lisible au-dessus du carrousel promo, juste les libellés des cartes ("MAXI BONUS", "CASHBACK SPORT", "WELCOME SPORT")
  • Constat :

Sur les 4 routes, aucun titre de niveau 1 ne donne le sujet de la page. Le persona arrivant sur /sport-home ne lit pas "Paris sportifs Guinée" en haut de page ; il voit un bandeau cookies, un menu, un bandeau promo. Le persona sur /promotions ne lit pas "Promotions et bonus" ; il voit un visuel "MAXI BONUS" puis 3 cartes. La promesse de page est entièrement portée par le design (gros visuels) et non par la structure textuelle. Sur mobile (non audité) cette absence sera encore plus pénalisante car la promesse est ce qui rassure dans les premiers 100 px.

  • Impact attendu :

UX : le visiteur en intent ambigu (arrivé via une recherche "site paris guinée") n'a pas de validation immédiate qu'il est au bon endroit. Cas concret : l'<title> mentionne "Sport, Jeux Digitaux, Virtuel, Loto" mais l'utilisateur n'a aucun titre H1 résumant l'offre. Friction de réassurance, surtout dans un secteur où la confiance est cruciale.

  • Root cause :

Layout-driven design (l'image fait le titre), héritage d'un template plateforme qui n'expose pas de slot H1 par défaut. Voir aussi [REF: DEEP-A11Y-01/F-A11Y-01-08] pour l'angle accessibilité.

F-UX-01-06 : Navigation principale appauvrie au profit d'un sous-menu non sourçable

  • Sévérité : serious
  • Route(s) : sport-home, sport, casino, promotions
  • Source primaire :
  • raw_html_sport.raw.html lignes 599-611 : <ul class="nav nav-tabs barra-menu menu-principale"> contient 4 items uniquement : Sports, Virtuel, Promo, Casino
  • Sous-menu <nav class="sottomenu-main"><div class="sottomenu-nav ... cg-hide" id="cg-scommesse-submenu"><ul></ul></div></nav> (vide dans le HTML serveur, peuplé en JS)
  • Sur la capture screenshots/sport-home/desktop.png un sous-menu visuellement présent : PREMATCH, LIVE, MULTIBET, EVENEMENTS, MULTILIVE, CALENDRIER
  • conversion-signals/sport-home.jsondetailed.ctas[2].text = "", href = "#nascondimenu" (item nav sans label texte)
  • Source visuelle : - screenshots/sport-home/desktop.png zone y=60-80 : barre rouge en haut avec Sports (souligné rouge actif), Virtuel, Promo, Casino. Juste en-dessous (y=88-110), seconde barre grise avec PREMATCH, LIVE, MULTIBET, EVENEMENTS, MULTILIVE, CALENDRIER
  • screenshots/sport/desktop.png : on voit le sous-menu peuplé (PREMATCH actif rouge)
  • screenshots/casino/desktop.png : le sous-menu n'apparaît pas (route Casino donc le sous-menu Sport est masqué)
  • Constat :

Le menu de premier niveau ne propose que 4 items génériques (les 4 verticales), tandis que le sous-menu (PREMATCH, LIVE, MULTIBET, etc.) qui contient les actions réelles d'un parieur est rendu uniquement après hydratation JS et n'apparaît qu'en mode Sport. Cela crée 2 problèmes : (1) un utilisateur qui veut accéder directement à "LIVE" depuis la home doit cliquer "Sports" d'abord puis "LIVE" (2 clics au lieu d'1 ; le sous-menu est conditionnel à la verticale active), (2) les libellés PREMATCH, MULTIBET, EVENEMENTS, MULTILIVE sont du jargon parieur non explicité. Pour le persona "intéressé par le football en priorité", le chemin attendu "voir les matchs de foot ce soir" n'est pas une étape de la nav, c'est une page d'atterrissage qu'il faut deviner (sport-home ?).

  • Impact attendu :

UX : friction d'orientation. Un nouvel utilisateur (cible du persona) doit deviner que "Live" est un sous-onglet de "Sports" et pas un onglet de premier niveau. Conversion : le parcours "voir un match live > parier" demande au moins 3 clics depuis la home, sans repère textuel intermédiaire.

  • Root cause :

Architecture nav héritée du template plateforme : menu principal = verticales, sous-menu = mode de consommation. Choix d'IA acceptable mais non décliné pour le persona local (qui veut un raccourci football direct).

F-UX-01-07 : Page Promotions de 108 mots, CTAs "EN SAVOIR PLUS" sans destination explicite

  • Sévérité : serious
  • Route(s) : promotions
  • Source primaire :
  • index.jsonpages[3].word_count = 108, title = "www.bet224.gn Guinee | Jouez en Ligne | Sport, Jeux Digitaux, Virtuel, Loto"
  • conversion-signals/promotions.jsonsummary.ctas_total = 3, primary_cta_text = "OUVRIR PIED DE PAGE"
  • Seulement 3 CTAs détectés total : 1 toggle menu sans texte, 1 sélecteur FR, 1 "OUVRIR PIED DE PAGE". Les 3 cartes promo + leurs CTAs internes "EN SAVOIR PLUS" sont vraisemblablement des <a> sans rôle button distinct ou détectés sous le fold.
  • Screenshot montre 3 cards visuels : MAXI BONUS - BONUS CASHBACK BET224 + 100,000 GNF DE PROFITER ENFIN DE L'OFFRE [EN SAVOIR PLUS], CASHBACK SPORT - BONUS CASHBACK BET224 100,000 GNF DE PROFITER DE L'OFFRE [EN SAVOIR PLUS], WELCOME SPORT - BONUS 100 % SUR DÉPÔT 1,000,000 GNF DE PROFITER DE L'OFFRE [EN SAVOIR PLUS]
  • Source visuelle : - screenshots/promotions/desktop.png : header visuel jaune "MAXI BONUS, AUGMENTE TES GAINS JUSQU'À 500 %!!! - PARIEZ ICI", 3 cards alignées avec CTA vert "EN SAVOIR PLUS", bouton rouge "OUVRIR PIED DE PAGE"
  • Constat :

La page Promotions est presque entièrement composée d'images (visuels Photoshop). Le texte HTML utile pour comprendre les conditions est quasi-inexistant (108 mots seulement, dont la majorité dans le header et le menu). Les CTAs "EN SAVOIR PLUS" sur chaque card ne précisent ni la cible de la redirection, ni les conditions de mise (wagering). Pour le persona, il est impossible de comparer 2 bonus sans cliquer "EN SAVOIR PLUS" 2 fois (perte de contexte). Le wording du visuel principal "AUGMENTE TES GAINS JUSQU'À 500 %" est problématique vs site-context.yamlvoice_and_tone.avoid qui interdit "promesse ou suggestion de gain" et forbidden qui liste explicitement "Gagnez a coup sur" et synonymes.

  • Impact attendu :

UX : friction de découverte. Le persona indécis doit faire 3 clics pour comparer 3 offres alors qu'un tableau / accordion les afficherait toutes. Conversion : impossible de juger de la pertinence d'un bonus sans cliquer ; abandon probable. Réglementaire : promesse de gain en visuel principal à cadrer Legal-check (forbidden_pattern probable selon le cadre GN à sourcer).

  • Root cause :

Page produite par juxtaposition de visuels marketing, sans contenu rédactionnel structuré. Pas d'investissement copywriting.

F-UX-01-08 : Casino, surcharge de 23 CTAs above-fold sans hiérarchie d'action claire

  • Sévérité : serious
  • Route(s) : casino
  • Source primaire :
  • conversion-signals/casino.jsonsummary.ctas_above_fold = 23, ctas_total = 43, aggregate.ctas_above_fold_ratio = 0.633 (moyenne 4 routes)
  • conversion-signals/casino.jsondetailed.ctas[4..10] : 7 boutons "JOUER" identiques (text = "JOUER", background_color = "rgb(14, 102, 52)" vert, bbox.y = 577 même rangée) au-dessus du fold
  • Boutons carrousel sans label : conversion-signals/casino.json → 8 boutons componenteGioco__navigatore__tasto avec text = "" (cf [REF: DEEP-A11Y-01/F-A11Y-01-03])
  • Premier carrousel "Gains récents" expose 4 montants type 1,803,313 GNF (Most Wanted, Alexander's Fortune, Aviator, AVIAJET) - signaux d'incitation jeu basés sur des gains supposés affichés en gros
  • Source visuelle : - screenshots/casino/desktop.png y=70-200 : 4 cards "Gains récents" affichant des montants en GNF + nom du jeu (potentiel "loss disguised as social proof", cf forbidden_patterns)
  • y=200-340 : carrousel "Spribe Games" avec icônes des 7 jeux instantanés (Aviator, Dice, Goal, Plinko, Mines, Mini Roulette, Hilo)
  • y=340-470 : "Top 10" avec rangs visuels 1-2-3-4-5 (Hot to Burn, Queen of God, Shining Hot, Book of Tut, Buster Bob)
  • y=470-580 : "Evolution" rangée Blackjack
  • Constat :

La page Casino expose 23 CTAs cliquables dans le seul above-fold (à 900px), avec 7 boutons "JOUER" identiques au pixel près (même libellé, même couleur, même taille), 8 flèches de carrousel sans label (cf A11Y), 4 cards "Gains récents" qui simulent une preuve sociale. Aucun chemin guidé : le visiteur subit la densité. Pour le persona, l'absence de hiérarchie ("jeu vedette", "nouveau", "guide débutant") rend la navigation chaotique. La sur-représentation du jeu "Aviator" (3 occurrences détectables dans le top-fold) et sa promotion via les "gains récents" est un pattern classique en gambling à risquer.

  • Impact attendu :

UX : surcharge cognitive, abandon probable pour l'utilisateur non-initié. Pour un utilisateur déjà engagé : risque de jeu impulsif aggravé par la mise en scène des gains supposés. Réglementaire : "Gains récents" sans contexte (gains nets vs bruts, fenêtre temporelle, vérifiabilité) à cadrer Legal-check car peut tomber sous "promesse de gain" du site-context.yaml.

  • Root cause :

Template casino dense par défaut, hérité d'une logique d'offre maximale visible. Pas d'arbitrage UX par hiérarchie (gros jeu vedette + sections collapsées).

F-UX-01-03 : Bandeau cookies persistant en haut de page, occupant le fold sans choix granulaire

  • Sévérité : moderate
  • Route(s) : sport-home, sport, casino, promotions
  • Source primaire :
  • raw_html_sport_home lignes 349-353 : <div id="cg-barra-cookies" class="row inline-flex flex-row justify-content-center cg-hide"><div>Ce site utilise des cookies, y compris des cookies de profilage tiers. Si vous souhaitez en savoir plus ou désactiver certains ou tous les cookies, lisez les informations. En poursuivant votre navigation, vous acceptez l'utilisation de tous les cookies.</div><a class="cg-cookies-ok" onclick="cg_acceptsCookies()">OK</a><a class="cg-cookies-more-info" href="/external_cms/pdf/Cookies_Policy.pdf" target="_blank">Plus d'informations</a></div>
  • Identique 4 routes (script inclus dans le template global, déclenché côté client)
  • Source visuelle : - screenshots/sport-home/desktop.png zone y=0-25 : bandeau gris en haut affichant "Ce site utilise des cookies, y compris des cookies de profilage tiers. ..." + bouton "OK" vert + lien "Plus d'informations"
  • Visible sur les 4 captures
  • Constat :

Le bandeau cookies (1) consomme environ 25-30 pixels du fold à 900px de hauteur (~3 % du viewport), (2) ne propose que "OK" et "Plus d'informations" (lien vers un PDF, pas une page web). Aucun bouton "Refuser tout", aucun choix granulaire (essentiels / mesure / profilage). Le wording présume le consentement ("En poursuivant votre navigation, vous acceptez l'utilisation de tous les cookies"), c'est-à-dire le pattern "consentement par poursuite de navigation" qui n'a aucune validité dans la plupart des cadres modernes de protection des données.

  • Impact attendu :

UX : bandeau persistant tant que pas cliqué (jamais accepté en POC = visible sur 4 captures), réduit l'espace utile. Pour l'utilisateur soucieux de sa vie privée, aucune option de refus présentée immédiatement, friction d'usage. Pour le projet : risque réglementaire à instruire (le cadre data Guinée n'est pas sourcé en session, cf site-context.yamlfacts.to_confirm : "Cadre data / cookies de profilage applicable en Guinée + politique de confidentialite"). À cadrer en Legal-check.

  • Root cause :

Bandeau hérité d'une implémentation pré-RGPD style "cookielaw" italien. Adaptation guinéenne n'a pas refait le composant.

F-UX-01-05 : Fuite contextuelle dans le markup, résidus "Sportcash.com" et "Ivory Coast"

  • Sévérité : moderate
  • Route(s) : sport-home, sport, casino, promotions
  • Source primaire :
  • raw_html_sport.raw.html ligne 25 : <meta name="description" content="Sportcash.com : sûr et fiable, les meilleures cotes de paris sportifs, le Loto et des jeux divertissants vous attendent!" />
  • raw_html_sport.raw.html ligne 28 : <meta name="keywords" content="Sportcash.com,Paris Sportifs en Ivory Coast,Ivory Coast Football,Meilleures cotes en Ivory Coast,Pronostics sport,Gagner aux paris,Jeux Arcades,Jeux Virtuels,Loterie Ivory Coast,Site pari sportif confiance Ivory Coast,Site pari sportif sécurisé Ivory Coast,Loto Ivory Coast,"
  • index.jsonpages[0].description = "Sportcash.com : sûr et fiable..." (sport-home), pages[1].description = idem (sport), pages[2].description = "Retrouvez des centaines de jeux sur Sportcash.com. Les meilleurs jeux au monde !" (casino), pages[3].description = "Sportcash.com vous offre des Promotions et des Bonus exclusifs pour vos paris..." (promotions)
  • HTML observé (raw_html_sport_home ligne 389) : <img src="https://www.bet224.gn/external_css/GUINEA/img/ARSJPA.png"> (logo régulateur affiché en header, point positif mais sans alt ni lien explicatif)
  • Toast en anglais visible (raw_html_sport_home ligne 875) : Click <span>HERE</span> to get started or <span>HERE</span> to never show this again
  • Source visuelle : - screenshots/sport-home/desktop.png : l'onglet du navigateur (titre) n'est pas visible mais le persona attentif voit la <title> dans son onglet ; le toast EN apparaît si auto-déclenché.
  • Constat :

Le site est techniquement de marque Bet224 mais conserve dans son markup des éléments d'une plateforme d'origine ("Sportcash.com" : marque ivoirienne pour cousins déployées sur le même backend) et d'un marché initial (Côte d'Ivoire vs Guinée). Le keyword "Loterie Ivory Coast" est particulièrement gênant compte tenu du cadre site-context.yamllegal_naming_restrictions.forbidden_terms qui interdit explicitement de "suggerer un lien avec la loterie nationale guineenne sauf preuve". L'utilisateur ne voit pas ces meta directement mais : (a) elles polluent le SEO, (b) elles trahissent un manque de soin éditorial qui résonne sur la confiance, (c) un journaliste / régulateur peut s'en saisir.

  • Impact attendu :

UX (perception) : un utilisateur averti qui inspecte l'onglet ou copie un lien voit "Sportcash.com" dans la description. Conversion : tag de qualité dégradé. Risque réglementaire et concurrentiel : keywords visibles mentionnant un autre pays et la loterie nationale (à cadrer Legal-check).

  • Root cause :

Template plateforme partagé entre plusieurs marques (Sportcash, Bet224, etc.) sur le même backend external_cms/GUINEA/. Les meta ont été oubliés à la spécialisation. Le toast EN est probablement un texte par défaut non traduit.

F-UX-01-09 : Sport, sidebar Betbuilder mise en avant sans explication ni preuve de valeur

  • Sévérité : moderate
  • Route(s) : sport
  • Source primaire :
  • conversion-signals/sport.jsondetailed.ctas[2].text = "BETBUILDER", bbox = {x:0, y:364, width:244, height:35}, background_color = "rgb(72, 72, 71)" gris foncé, color = "rgb(0, 0, 0)" (contraste insuffisant, cf [REF: DEEP-A11Y-01] pour le détail)
  • conversion-signals/sport.jsondetailed.ctas[3].text = "Cotes favoris" juste en-dessous
  • Aucun texte explicatif Betbuilder dans index.jsonpages[1].word_count = 605 (605 mots au total dont l'essentiel = libellés de compétitions et cotes)
  • Source visuelle : - screenshots/sport/desktop.png zone x=0-244, y=364-420 : barre grise contenant le texte "BETBUILDER" en majuscules, en haut de la sidebar gauche. Aucune icône d'explication, aucun tooltip visible, aucun lien "Comment ça marche". Juste en-dessous : "Cotes favoris" (autre fonctionnalité opaque pour novice).
  • Constat :

La sidebar Sport propose 2 fonctionnalités avancées (Betbuilder = construction d'un pari combiné multi-marchés sur un même match ; Cotes favoris = sauvegarde de cotes préférées) sans aucune mini-définition, sans aucun tutoriel intégré, sans onboarding contextuel. Le persona novice ignore ce qu'est un Betbuilder ; il voit un bandeau gris peu lisible qui ne s'explique pas. Le persona expert peut s'en passer, donc la mise en avant ne sert finalement personne sans contenu pédagogique.

  • Impact attendu :

UX : feature gâchée par défaut d'explication, taux d'utilisation probablement bas, ROI design négatif. Pour la confiance générale : impression que le site parle "à des initiés" et ne facilite pas l'entrée du novice (qui est pourtant le persona Guinée, marché jeune en growth).

  • Root cause :

Design pris tel quel sans wrapping pédagogique. La feature Betbuilder est une marque-produit (Betradar / Sportradar) souvent livrée comme widget tiers sans intro UX.

F-UX-01-10 : Inconsistance vocabulaire et langue dans l'interface

  • Sévérité : moderate
  • Route(s) : sport-home, sport, casino, promotions
  • Source primaire :
  • Wording maladroit : OUVRIR PIED DE PAGE (traduction littérale italienne aprire piè di pagina, devrait être "Voir le pied de page" ou simplement "Mentions légales", cf conversion-signals/casino.jsondetailed.primary_cta.text = "OUVRIR PIED DE PAGE")
  • Mélange FR / EN : raw_html_sport_home ligne 764 : <a class="cg-ext-link pointer" onclick="cg_newAccount(true)">Registration</a> (lien EN dans un footer FR)
  • Toast EN visible (raw_html_sport_home ligne 875) : Click HERE to get started or HERE to never show this again
  • Boutons mixtes : Login (EN) à côté de Inscription (FR) dans le header (raw_html_sport_home ligne 408-410 : <a onclick="cg_login()" class="bottone bottone-login">Login</a> ... <span class="bottone bottone-registrazione">Inscription</span>)
  • Italien résiduel dans le markup : nascondimenu, nascondifooter (id IT pour "cacher menu"/"cacher footer"), componenteGioco, barra-cookies, consulta-footer
  • Source visuelle : - screenshots/sport-home/desktop.png zone y=40-65 : "Login" + "Inscription" côte-à-côte
  • 4 captures : "OUVRIR PIED DE PAGE" visible en bas-droite
  • Constat :

Le site mélange français standard, français maladroit (calque italien), anglais (mots-clés cTA, libellé toast), et italien (classes / IDs CSS, classes BEM). Pour le persona guinéen francophone (langue de scolarisation principale en Guinée), le mélange est lisible mais évoque une plateforme bricolée. Le terme "OUVRIR PIED DE PAGE" en particulier est faux français (pied de page = composant technique, pas un mot qu'on adresse à un utilisateur final). "Login" / "Registration" en anglais cohabitent avec "Inscription" en français = duplication conceptuelle.

  • Impact attendu :

UX : friction de confiance ("ce site n'est pas fait pour moi"), perception de qualité dégradée. Plus subtil : risque d'incohérence pour le persona ayant un niveau de français modeste qui voit "Login" sans connaître le mot, alors que "Connexion" serait universellement compris.

  • Root cause :

Template plateforme italien (probablement Microgame / SISAL ou équivalent) traduit partiellement en français, partiellement laissé en italien (classes), partiellement laissé en anglais (libellés par défaut). Pas d'audit terminologique complet à la spécialisation Guinée.

Cross-angle dependencies

  • A11Y : F-UX-01-04 (absence de H1) recoupe [REF: DEEP-A11Y-01/F-A11Y-01-08] (axe page-has-heading-one violée sur 4 routes). Les recos R-UX-01-02 (réinjecter H1 + intro) et R-A11Y-01-12 (ajouter H1 unique) doivent être fusionnées par assemble_audit.py : même action technique, même portée, copy-ready compatibles. Préférer le copy-ready de R-UX-01-02 (inclut une intro qui sert aussi le SEO), garder la validation axe de R-A11Y-01-12.
  • A11Y : F-UX-01-08 (boutons carrousel casino sans nom accessible) référence directement [REF: DEEP-A11Y-01/F-A11Y-01-03] (8 boutons componenteGioco__navigatore__tasto sans aria-label). La reco R-UX-01-07 (réduire densité casino) ne suffit pas si les boutons restants restent muets : reco A11Y a11y-01-03 reste critique en parallèle.
  • CONV (à venir, DEEP-CONV-01) : F-UX-01-01 (CTA primary = "OUVRIR PIED DE PAGE") est un finding partagé fort, voire central pour CONV (la mécanique de conversion est cassée à la racine). La reco R-UX-01-01 résout simultanément un objectif UX (footer visible) et un objectif CONV (libérer un CTA primary pertinent type "Inscription" ou "Déposer"). À fusionner.
  • CONV (à venir, DEEP-CONV-01) : F-UX-01-07 (page Promotions sous-documentée) et la pratique "EN SAVOIR PLUS" génériques sont un finding partagé CONV (libellés peu actionables) + UX (friction de comparaison). À fusionner.
  • TRUST (à venir, DEEP-TRUST-01) : F-UX-01-02 (footer collapsed + 3 liens) et F-UX-01-11 (jeu responsable absent) sont les findings centraux d'angle TRUST. La reco R-UX-01-01 (footer visible permanent) et R-UX-01-08 (jeu responsable + page dédiée) seront probablement les recos principales du DEEP-TRUST-01 ; à fusionner.
  • TRUST (à venir, DEEP-TRUST-01) : F-UX-01-05 (résidus "Sportcash" / "Ivory Coast") est une friction de confiance / réputation. À cross-référencer avec un éventuel finding TRUST sur la cohérence brand.
  • UI (à venir, DEEP-UI-01) : F-UX-01-08 (densité casino) dépend du design-system : la prolifération de boutons "JOUER" identiques pose aussi une question de hiérarchie visuelle (taille, couleur unique vs gradation). À cross-référencer avec design-system/index.json pour vérifier si une variation visuelle (jeu premium vs standard) est prévue dans la palette.
  • MOBILE (à venir, DEEP-MOBILE-01) : aucune dépendance critique identifiée puisque mobile non capturé. À noter pour DEEP-MOBILE-01 : le bouton fixed "OUVRIR PIED DE PAGE" en bottom-right couvre probablement encore plus de surface sur mobile (priorité visuelle aggravée), à instrumenter.
  • SEO (à venir, DEEP-SEO-01) : F-UX-01-04 (absence H1) et F-UX-01-05 (meta résiduels Sportcash / Ivory Coast) sont des findings SEO majeurs. R-UX-01-02 et R-UX-01-03 doivent être fusionnées avec leurs équivalents SEO.
  • cross-angle-conflict potentiel : R-UX-01-07 (refonte casino above-fold) pourrait conflicter avec une éventuelle reco UI conservant le pattern visuel actuel ou avec une reco CONV qui voudrait maximiser le nombre de CTAs visibles. Escalader au red team UX-check si le DEEP-CONV-01 propose une direction divergente.

Limites

  • Mobile non audité : screenshots/<slug>/mobile.png absent pour les 4 routes (POC desktop only, cf crawl/screenshots/<slug>/ ne contient que desktop.png). Conséquence : la qualité du responsive, les touch targets, la position du bouton "OUVRIR PIED DE PAGE" en mobile, l'utilisabilité réelle pour le persona primary (mobile-first) ne sont pas évalués. Or le persona est explicitement mobile-majoritaire (site-context.yaml). Recommandation : étendre le crawl mobile avant livraison FULL.
  • absent ou non parsable : build_page_signals.py n'a pas tourné côté product-audit (bug crawl, raw_html_path pointe vers seo-audit). Conséquence : headings.outline, nav.structure, link_graph.in_degree, link_graph.out_degree, landmarks[] consolidés ne sont pas disponibles. J'ai compensé en lisant directement les raw.html (côté seo-audit) mais sans agrégation cross-route. Recommandation : faire tourner build_page_signals.py sur le crawl product-audit, ou symlinker les signals.json déjà produits côté seo-audit.
  • link_graph.json absent : pas de mesure des in_degree / out_degree des pages, donc l'analyse "navigation transverse" repose sur observation du menu HTML uniquement, pas sur les liens internes effectifs. Conséquence : impossible de quantifier l'orphelinat ou la profondeur de la navigation.
  • Parcours d'inscription / dépôt / pari non audités : les routes auditées (sport-home, sport, casino, promotions) ne couvrent pas /signup, /recoverPsw, /deposit, le ticket de pari après ajout d'une cote, la page d'un événement live. Or ce sont les étapes critiques du funnel site-context.yamlparcours_conversion (à inférer puisque non explicité dans yaml mais évident : inscription -> dépôt -> pari). Recommandation : étendre le scope pour FULL.
  • États de page non capturés : pas de capture de 404, de 500, de "panier vide", de "résultat de recherche vide", de "session expirée", de "compte verrouillé", de "dépôt refusé". Pour un site YMYL gambling, ces états sont critiques car ils gèrent les frustrations utilisateur. Recommandation : extension Playwright pour capturer artificiellement ces états.
  • Pas d'observation après login : le crawl est anonyme, donc l'expérience utilisateur connecté (ticket de pari, historique, dépôt) n'est pas évaluée. Pour un site YMYL gambling où l'engagement post-inscription est l'enjeu principal, c'est une limite forte. Recommandation : audit séparé sur un compte de test fourni par le client.
  • Tests utilisateurs réels : non effectués. Les findings reposent sur observation expert + données automatiques (axe, conversion-signals). Un test à 5 utilisateurs représentatifs du persona Guinée révélerait probablement des frictions linguistiques, culturelles et liées au niveau de connexion (3G/4G) non capturées ici.
  • Mesures performance ressenties : crux.json et pagespeed/<hash>.json non produits côté product-audit. L'UX perçue dépend fortement de LCP / INP réels en contexte Guinée (réseau probablement variable). Cross-référence à instruire en DEEP-PERF-01 quand les données seront disponibles.
  • Cadre légal de la communication promotionnelle en Guinée non sourcé : conséquences directes sur F-UX-01-07 (visuel "AUGMENTE TES GAINS JUSQU'À 500 %") et F-UX-01-11 (jeu responsable). Les recos copy-ready sont conçues pour être "safe" en attendant le cadre, mais le wording final dépend de Legal-check.