Hero Background
DESIGN - UX - INDUSTRIALISATION

Comment transformer
le design d’une application R Shiny

Lors du déploiement d’une application R Shiny, APPLITICS est intervenu pour améliorer le design visuel, optimiser l’expérience utilisateur et mettre en place un système d’authentification et de contrôle d’accès.

Objectif : renforcer l’engagement des utilisateurs et accélérer l’adoption de l’outil lors de son déploiement à grande échelle.

Before - Original R Shiny Dashboard
Avant
After - Transformed R Shiny Dashboard
Après

Introduction

DIGITAL FUEL CAPITAL, société d’investissement spécialisée dans l’e-commerce, a développé en interne un outil de Business Intelligence (BI). Cet outil permet aux entreprises leaders du secteur d’analyser finement leurs performances et d’identifier de nouvelles opportunités de croissance et d’optimisation.

Cette initiative reflète l’engagement de l’entreprise à apporter à ses partenaires bien plus qu’un soutien financier : des ressources stratégiques et opérationnelles pour les aider à se développer sur leur marché.

L’équipe souhaitait industrialiser cet outil pour ses partenaires. Mais un élément clé restait à construire : une interface capable de susciter l’adhésion des utilisateurs et de leur donner envie de partager leur expérience. Il était également essentiel de créer un dashboard parfaitement aligné avec l’identité visuelle de l’entreprise.

Dans cette étude de cas, nous montrons comment APPLITICS a accompagné DIGITAL FUEL CAPITAL autour de deux objectifs clés :

  • arrow
    Assurer une industrialisation fluide
  • arrow
    Transformer les utilisateurs en ambassadeurs de l’outil
Timeline connection

Améliorer l’UI/UX d’une application R Shiny pensée pour l’industrialisation

Notre équipe s’est concentrée sur la création d’une interface utilisateur intuitive et moderne, capable d’améliorer nettement l’expérience utilisateur. La refonte s’est appuyée sur une recherche utilisateur approfondie, plusieurs itérations de design et une attention particulière portée à l’accessibilité et à l’utilisabilité.

Sales Pulse – Digital Fuel Capital - Testimonial
arrow
Objectif : renforcer l’engagement des utilisateurs et accélérer l’adoption de l’outil lors de son déploiement à grande échelle
arrow
Secteur : Services financiers / Business Intelligence
arrow
Client : Digital Fuel Capital
I

Le point de départ de l’application

L’interface de l’application, initialement développée par Jeffrey Coughlin, reposait sur Shinydashboard et comprenait principalement :

  • arrow
    Une barre latérale avec des onglets et des sous-onglets
  • arrow
    Un panneau latéral dédié aux filtres
  • arrow
    Une série de graphiques mis à jour dynamiquement selon les filtres sélectionnés.

Cependant, avec son layout Shinydashboard classique, l’interface n’était pas encore adaptée à une utilisation à grande échelle.

Côté backend, des modèles analytiques avancés étaient déjà en place pour calculer les KPI clés et générer des rapports détaillés à partir des données des boutiques en ligne sélectionnées.

Interface de l’application
II

Les défis rencontrés

Jeff faisait face à deux défis principaux :

1. Mettre en place un système d’authentification

  • arrow
    Dans la première version de l’application, les données de tous les partenaires étaient stockées dans des sous-dossiers du dossier principal data . Pour lancer l’outil sur les données d’une boutique en ligne spécifique, l’équipe devait spécifier manuellement le sous-dossier correspondant dans le code.
  • arrow
    Avec des dizaines de partenaires à gérer, cette approche était loin d’être pratique.
  • arrow
    Pour éviter ce hard-coding, Jeff était convaincu qu’un système d’authentification reliant chaque utilisateur à son propre dossier de données était indispensable.

2. Améliorer le design

  • arrow
    Dans sa version initiale, l’application était visuellement acceptable… du moins pour un usage interne.
  • arrow
    Mais comme elle était destinée aux partenaires stratégiques de l’entreprise, elle devait être agréable à utiliser et refléter l’identité visuelle de DIGITAL FUEL CAPITAL.
  • arrow
    C’est pourquoi Jeff a souhaité faire appel à des experts.
III

Mettre en place un système d’authentification pour une application R Shiny

Pour sécuriser une application web Shiny, plusieurs technologies peuvent être envisagées. Notamment :

  • Shinymanager : un package R développé par Datastorm. En plus d’ajouter une couche d’authentification, il propose une interface d’administration pour suivre l’utilisation de l’application par chaque utilisateur, ce qui peut être très utile dans certains cas.
  • Shinyauth : un autre package R apprécié pour sa flexibilité dans la création de systèmes de connexion basés sur des bases d’utilisateurs personnalisées, avec une gestion simple des utilisateurs et des rôles.
  • Shinyproxy : une solution de déploiement standard. En utilisant Docker, chaque application est isolée dans son propre conteneur, ce qui renforce la sécurité et simplifie la gestion des ressources.

Il est évident que toutes ces technologies permettent d’obtenir des résultats relativement proches.

Avec Jeff, le choix s’est rapidement porté sur Auth0, que l’équipe DFC connaissait déjà.

L’implémentation du package d’authentification reste assez simple. Plusieurs ressources en ligne permettent de démarrer rapidement. Ce guide de curso-r constitue un bon point de départ.

Une fois le package auth0 implémenté et les utilisateurs créés, l’étape suivante consistait à associer chaque utilisateur à son propre répertoire de données. Pour cela, il suffit d’utiliser la variable de session : session$userData$auth0_info . Une fois l’utilisateur authentifié, cette variable contient différentes informations le concernant.

Voici un exemple simple pour illustrer ce cas d’usage :

library(shiny)

ui <- fluidPage()

server <- function(input, output, session) {
  # Initialize user-specific reactive data
  user_data <- reactiveValues()
  
  # Retrieve the user name from the session variable
  # session$userData$auth0_info
  observe({
    auth_info <- session$userData$auth0_info
    if (!is.null(auth_info)) {
      user_data$username <- auth_info$nickname
      # Define the user's data folder
      user_data$data_folder <- file.path("data", user_data$username)
    }
    print(user_data$folder) # displays "data/username_1"
  })
}

auth0::shinyAppAuth0(ui, server)

La variable réactive user_data$data_folder est ensuite utilisée dans l’application pour charger les données depuis le bon répertoire, selon l’utilisateur connecté.

Nous avons maintenant un système d’authentification qui associe chaque utilisateur à son propre répertoire de données.

L’étape suivante suit naturellement lorsque l’on observe la page d’authentification par défaut fournie par auth0 :

Interface Auth0 par défaut

Interface Auth0 par défaut

C’est déjà solide, mais l’expérience serait encore plus cohérente si l’identité visuelle de DIGITAL FUEL CAPITAL apparaissait dès la page de connexion.

Pour cela, nous nous connectons au dashboard Auth0 , puis nous accédons à Branding et Universal Login. Plusieurs niveaux de personnalisation sont disponibles. Pour aller plus loin, les options avancées permettent de personnaliser directement le style dans le code.

Le résultat de cette page de connexion améliorée est présenté dans la section suivante.

IV

Préparation d’une maquette graphique

Le design se compose de deux parties : l’interface utilisateur (UI) et l’expérience utilisateur (UX).

Ces deux éléments sont essentiels pour l’industrialisation d’un outil.

L’UI désigne la conception de l’interface, avec un focus particulier sur son apparence visuelle.

L’UX couvre la manière dont l’utilisateur interagit avec l’application, de la navigation à la compréhension des informations affichées.

En termes simples, l’objectif est de créer un produit à la fois attractif et fonctionnel. C’est ce qui donne envie aux utilisateurs de l’adopter.

L’UI et l’UX sont des expertises à part entière.

Pour avancer sur cette étape, APPLITICS a fait appel à Sundas, experte en design d’interface.

L’application lui a été présentée, avec son fonctionnement et les objectifs définis par Jeff.

À ce stade, le rendu final de l’application restait encore à imaginer.

Dès la découverte de la maquette, le constat était clair : c’était exactement ce qu’il fallait !

L’identité visuelle de DIGITAL FUEL CAPITAL est immédiatement reconnaissable.

Maquette graphique de la nouvelle UI

Image de maquette 1

Le site web de DIGITAL FUEL CAPITAL peut servir de point de comparaison : lien

À ce stade... il ne restait plus qu’à intégrer l’ensemble dans R Shiny.

Et puis...

Une question clé s’est posée : fallait-il continuer avec Shinydashboard ?

À première vue, l’option pouvait sembler pertinente : le package propose une barre latérale claire, déjà structurée, avec une gestion hiérarchique des onglets.

Cependant, dans ce cas précis, le projet exigeait un haut niveau de personnalisation. L’expertise web d’APPLITICS permettait d’y répondre plus efficacement.

Ainsi, repartir de zéro et construire les éléments avec HTML et CSS s’est avéré être la solution la plus simple.

V

Construction du squelette HTML d’une application Shiny

Créer la structure HTML est assez simple.

Shiny utilise Bootstrap par défaut, ce qui évite de repartir entièrement de zéro.

Bootstrap offre de nombreux outils, notamment la possibilité de créer une grille de colonnes avec les fonctions fluidRow() et column().

Voici un exemple de structure de dashboard :

fluidPage(
  fluidRow(
    id = "header",
    # Contenu de l'en-tête
  ),
  fluidRow(
    id = "body_content",
    column(
      id = "sidebar_content",
      width = 3,
      div(
        # Contenu de la barre latérale
      )
    ),
    column(
      id = "main_content",
      width = 9,
      div(
        # Contenu du corps principal
      )
    )
  )
)

Une fois cette structure en place, il ne reste plus qu’à ajouter le contenu.

L’argument id est utilisé pour identifier les différents éléments d’interface.

Ces id serviront ensuite dans le CSS pour cibler les éléments et personnaliser leur apparence.

Par défaut, le rendu reste en effet très limité visuellement.

L’étape suivante consiste donc à coder la partie visuelle avec du CSS.

VI

Styliser une application R Shiny avec Sass

Pour structurer la partie design, APPLITICS s’est appuyé sur Sass, une extension de CSS.

Son rôle principal est d’organiser le code CSS pour le rendre plus lisible et, surtout, plus simple à écrire.

Par exemple :

#main_content {
  padding: 50px 7%;
  .introduction {
    position: relative;
    background-color: white;
    padding: 10px 25px 30px 25px;
    margin-bottom: 20px;
    h3 {
      font-size: 20px;
      color: $red;
      text-transform: uppercase;
    }
  }
}

En CSS, cela se traduit par :

#main_contents {
  padding: 50px 7%;
}

#main_content .introduction {
  position: relative;
  background-color: white;
  padding: 10px 25px 30px 25px;
  margin-bottom: 20px;
}

#main_content .introduction h3 {
  font-size: 20px;
  color: $red;
  text-transform: uppercase;
}

La différence peut sembler mineure à première vue. Mais le fichier CSS manque de structure, et les sélecteurs deviennent beaucoup plus longs.

Sur un petit exemple, cela reste gérable. Mais avec plusieurs centaines de lignes de code, l’intérêt de structurer et d’organiser les sélecteurs devient évident.

Pour utiliser un fichier .scss dans une application Shiny, deux méthodes sont possibles :

La méthode traditionnelle consiste à installer l’outil Sass sur votre système, puis à compiler le fichier .scss avec la commande :

sass styles/style.scss www/style.css

Ou, encore plus simple, vous pouvez utiliser le package {{sass}} développé par Posit (anciennement RStudio). Il se charge de la compilation pour vous.

La mise en page est désormais intégrée.

Reste toutefois à traiter certains composants UI spécifiques : les visualisations et les inputs...

VII

Comment créer des visualisations attrayantes dans Shiny

Jeff a initialement utilisé la bibliothèque ggplot2 pour les visualisations du dashboard.

L’objectif était de faire évoluer ces visualisations pour les rendre plus soignées, conformément à la maquette graphique, et plus interactives afin d’améliorer l’expérience utilisateur.

1. Choix du package de visualisation : Highcharter

Après une brève analyse, deux options ont été retenues :

  • Conserver ggplot2, en renforçant la personnalisation et en ajoutant des info-bulles interactives avec le package {ggiraph} .
  • Reconstruire les visualisations avec un autre package : Highcharter
  • D’un côté, ggplot2 est le package de visualisation de référence pour les utilisateurs de R. Sa popularité lui assure une documentation abondante et une communauté solide.
  • De son côté, Highcharter, développé par Joshua Kunst, est un wrapper R pour la bibliothèque JavaScript Highcharts largement utilisée sur le web. Il offre un niveau de personnalisation très avancé grâce à une API riche qui permet un contrôle fin sur l’ensemble du graphique.
  • Comme l’explique le développeur du package R : “No default arguments. All arguments need to be named.”
  • Autrement dit, Highcharter offre une grande flexibilité pour exploiter depuis R l’ensemble des fonctionnalités du package Highcharts JS.
  • Highcharter permet d’utiliser efficacement la syntaxe JSON à travers des listes R pour définir et personnaliser les graphiques. Cette approche fonctionne particulièrement bien grâce à la similitude entre les listes R et les objets JSON utilisés par Highcharts en JavaScript.
  • Prenons par exemple ce graphique en JS :
  • Highcharts.chart('container', {
      chart: {
        type: 'line',
        backgroundColor: '#f0f0f0'
      },
      title: {
        text: 'Customized Chart'
      },
      xAxis: {
        categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun']
      },
      yAxis: {
        title: {
          text: 'values'
        },
        plotBands: [ // Highlighted range on the Y-axis
          {
            from: 5,
            to: 10,
            color: 'rgba(68, 170, 213, 0.1)',
            label: {
              text: 'Safe Range',
              style: {
                color: '#606060'
              }
            }
          }
        ]
      },
      tooltip: {
        shared: true,
        valueSuffix: ' units'
      },
      series: [{
        name: 'Serie 1',
        data: [7, 6, 9, 14, 18, 21],
        color: '#FF5733'
      }, {
        name: 'Serie 2',
        data: [3, 4, 5, 8, 11, 15],
        color: '#33FF57'
      }]
    });

    ... devient en R :

    library(highcharter)
    
    highchart() %>%
      hc_chart(type = "line", backgroundColor = "#f4f4f4") %>%
      hc_title(text = "Customized Chart") %>%
      hc_xAxis(categories = c("Jan", "Feb", "Mar", "Apr", "May", "Jun")) %>%
      hc_yAxis(
        title = list(text = "values"),
        plotBands = list(list(
          from = 5,
          to = 10,
          color = "rgba(68, 170, 213, 0.1)",
          label = list(text = "Safe Range", style = list(color = "#606060"))
        ))
      ) %>%
      hc_tooltip(shared = TRUE, valueSuffix = " units") %>%
      hc_series(
        list(
          name = "serie 1",
          data = c(7, 6, 9, 14, 18, 21),
          color = "#FF5733"
        ),
        list(
          name = "serie 2",
          data = c(3, 4, 5, 8, 11, 15),
          color = "#33FF57"
        )
              )
  • Cependant, au-delà des visualisations statiques montrées plus tôt dans cette étude de cas, Jeff voulait également implémenter une fonctionnalité plus élaborée : de petits graphiques complémentaires affichant en temps réel l’évolution de certaines métriques pré-calculées, actualisées chaque seconde.
  • Pour cette fonctionnalité, Highcharter s’est clairement imposé comme la meilleure option pour le projet, grâce à ses animations particulièrement fluides pour les mises à jour de graphiques en temps réel.
  • De plus, comme le projet ne comportait pas de contrainte de licence, le passage à Highcharts est devenu un choix évident.

2. Créer un graphique mis à jour en temps réel avec ‘highcharter’

  • Les KPI pré-calculés étant confidentiels pour DIGITAL FUEL CAPITAL, nous avons créé un exemple avec des données fictives, toujours dans le contexte de l’e-commerce.
  • Supposons que nous voulions afficher des données montrant l’évolution du trafic web, avec une précision seconde par seconde , provenant d’une API serveur.
  • Voici un exemple illustrant cela :
  • Évolution des données en temps réel du trafic web avec Highcharter

  • Dans notre exemple, les appels API sont simulés à l’aide de la variable auto_invalidate , qui se réinitialise automatiquement toutes les deux secondes grâce à la fonction reactiveTimer() . Dans Shiny, ce mécanisme correspond à l’invalidation automatique.
  • Dans notre exemple fictif, à chaque réinitialisation, des données aléatoires sont générées puis ajoutées aux données historiques.
  • Ensuite, l’ajout d’un nouveau point est géré directement par les fonctions proxy hcpxy_add_point() et hcpxy_set_data() en précisant l’ID de la série.
  • Vous pouvez consulter le code source ici.
  • Vous pouvez également consulter l’exemple interactif ici.
VIII

Créez votre propre widget dans Shiny

Dans un contexte d’industrialisation d’une application web, les inputs standards de Shiny ne suffisent pas toujours sur le plan visuel, notamment lorsqu’il faut respecter la charte graphique de l’entreprise.

Voici les deux versions à comparer :

Select Input personnalisé

entrée de sélection personnalisée

Sans surprise, l’input conçu dans la maquette s’intègre mieux à l’univers visuel de DIGITAL FUEL CAPITAL.

Pour modifier l’apparence d’un input dans une application Shiny, deux approches sont possibles :

1. La méthode rapide (quick & dirty) : surcharger directement le style par défaut d’un input Shiny standard. Elle est utile pour appliquer rapidement quelques ajustements mineurs.

2. La méthode professionnelle : développer un widget personnalisé à partir de zéro. Elle est plus complexe, mais permet une personnalisation complète et bien intégrée.

Un bon point de départ pour la méthode rapide consiste à utiliser l’inspecteur de code afin d’ajuster temporairement le style visuel jusqu’à obtenir le rendu souhaité. Il suffit ensuite d’ajouter ces styles dans le header de votre application Shiny.

La méthode professionnelle, en revanche, demande un peu plus de travail. Elle consiste à créer un widget Shiny entièrement personnalisé à partir de briques HTML, CSS et JavaScript. Elle offre un contrôle complet sur le comportement et l’apparence du widget, tout en améliorant sa réutilisabilité et sa maintenabilité.

Pour aller plus loin, voici quelques ressources utiles :

Dans notre exemple, voici le code complet : lien

Le code R : contient les balises HTML du widget. Ici, il s’agit simplement d’une balise input.

Le code CSS : permet de respecter la charte graphique.

Le code JavaScript : ajoute la logique nécessaire pour transformer l’input en widget Shiny.

IX

OBJECTIF ATTEINT !

Dès sa mise en production, l’application a été accueillie avec enthousiasme par l’ensemble des partenaires de l’entreprise, avec un taux de satisfaction de 100 %.

Le lancement a été un vrai succès. Les responsables de boutiques en ligne, utilisateurs directs de l’outil, lui font désormais davantage confiance. Ils le perçoivent comme une solution robuste et professionnelle pour leur activité, et non comme un simple dashboard développé dans l’urgence. Ils reconnaissent la qualité et la fiabilité de l’outil, ce qui renforce leur engagement et leur satisfaction.

Aujourd’hui, l’outil est pleinement opérationnel et entre dans une phase d’amélioration continue. L’objectif est désormais d’optimiser l’expérience utilisateur à partir des retours utilisateurs. Nous travaillons par exemple sur l’intégration d’une fonctionnalité de benchmarking, afin de comparer de manière précise et structurée les analyses menées par différents partenaires sur un même segment. Cette évolution facilitera la prise de décision stratégique à partir de données comparatives fiables.