Saasy

Exemple complet

Page HTML de test avec le widget Saasy et des éléments ciblés pour configurer tes flows d'onboarding.

Exemple complet

Cette page fournit une application HTML de test que tu peux héberger localement ou sur CodePen. Elle charge le vrai widget Saasy et expose des éléments ciblés avec des sélecteurs CSS précis. Tu configures ensuite tes flows dans le Canvas Builder du dashboard en pointant sur ces sélecteurs.

Comment utiliser cet exemple

  1. Copie le code HTML ci-dessous dans un fichier index.html ou dans CodePen
  2. Remplace app_ton_app_key par ta clé d'intégration (disponible dans Onboarding > Paramètres)
  3. Lance ton API Saasy en local (npm run dev) ou pointe vers ton instance de production
  4. Ouvre la page dans ton navigateur
  5. Dans le dashboard Saasy, crée un flow et utilise les sélecteurs CSS du tableau ci-dessous pour ancrer tes tooltips, modales, etc.

Sélecteurs CSS disponibles

Voici les éléments ciblés disponibles dans la page d'exemple. Utilise ces sélecteurs dans le Canvas Builder pour ancrer tes composants :

Sélecteur CSSÉlémentCas d'usage
#create-project-btnBouton "Créer un projet"Tooltip pour guider la création
#user-avatarAvatar utilisateur (header)Tooltip profil
#nav-dashboardLien nav "Dashboard"Tooltip navigation
#nav-projectsLien nav "Projets"Tooltip navigation
#nav-analyticsLien nav "Analytiques"Tooltip navigation
#nav-settingsLien nav "Paramètres"Tooltip navigation
#stat-usersCarte stat "Utilisateurs"Tooltip métriques
#stat-revenueCarte stat "Revenus"Tooltip métriques
#stat-conversionCarte stat "Conversion"Tooltip métriques
#welcome-cardCarte de bienvenueTooltip ou spotlight
#feature-analyticsFeature "Analytiques"Tooltip fonctionnalités
#feature-integrationsFeature "Intégrations"Tooltip fonctionnalités
#feature-teamFeature "Équipe"Tooltip fonctionnalités
#feature-exportFeature "Export"Tooltip fonctionnalités
#search-inputChamp de rechercheTooltip recherche
#upgrade-btnBouton "Passer en Pro"Tooltip upgrade
[data-onb="sidebar"]Sidebar complèteZone pour slideout
[data-onb="main-content"]Zone de contenu principalZone pour modale/bannière

Code HTML

<!DOCTYPE html>
<html lang="fr">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Mon App - Page de test Saasy Onboarding</title>
  <style>
    *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
    body {
      font-family: Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
      background: #f8fafc;
      color: #1e293b;
      min-height: 100vh;
      display: flex;
    }

    /* ── Sidebar ────────────────────────────────────────────── */
    .sidebar {
      width: 240px;
      background: #0f172a;
      color: #94a3b8;
      display: flex;
      flex-direction: column;
      min-height: 100vh;
      position: fixed;
      left: 0;
      top: 0;
      bottom: 0;
    }
    .sidebar .logo {
      padding: 20px 20px 24px;
      font-size: 18px;
      font-weight: 700;
      color: #fff;
      letter-spacing: -0.02em;
    }
    .sidebar nav { flex: 1; padding: 0 12px; }
    .sidebar nav a {
      display: flex;
      align-items: center;
      gap: 10px;
      padding: 10px 12px;
      border-radius: 8px;
      font-size: 14px;
      color: #94a3b8;
      text-decoration: none;
      transition: all 0.15s;
      margin-bottom: 2px;
    }
    .sidebar nav a:hover { background: #1e293b; color: #e2e8f0; }
    .sidebar nav a.active { background: #1e293b; color: #fff; }
    .sidebar nav a .icon { font-size: 18px; width: 24px; text-align: center; }
    .sidebar .sidebar-footer {
      padding: 16px 20px;
      border-top: 1px solid #1e293b;
    }
    .sidebar .sidebar-footer .upgrade-btn {
      display: block;
      width: 100%;
      padding: 10px;
      background: #2563eb;
      color: #fff;
      border: none;
      border-radius: 8px;
      font-size: 13px;
      font-weight: 600;
      cursor: pointer;
      text-align: center;
      transition: background 0.15s;
    }
    .sidebar .sidebar-footer .upgrade-btn:hover { background: #1d4ed8; }

    /* ── Main ───────────────────────────────────────────────── */
    .main { margin-left: 240px; flex: 1; min-height: 100vh; }

    .topbar {
      background: #fff;
      border-bottom: 1px solid #e2e8f0;
      padding: 0 24px;
      height: 64px;
      display: flex;
      align-items: center;
      justify-content: space-between;
      position: sticky;
      top: 0;
      z-index: 10;
    }
    .topbar .search {
      display: flex;
      align-items: center;
      gap: 8px;
      background: #f1f5f9;
      border: 1px solid #e2e8f0;
      border-radius: 8px;
      padding: 8px 14px;
      width: 320px;
    }
    .topbar .search input {
      border: none;
      background: none;
      outline: none;
      font-size: 14px;
      color: #334155;
      width: 100%;
      font-family: inherit;
    }
    .topbar .search input::placeholder { color: #94a3b8; }
    .topbar .search .icon { color: #94a3b8; }
    .topbar .user-area {
      display: flex;
      align-items: center;
      gap: 12px;
    }
    .topbar .notif-btn {
      position: relative;
      background: none;
      border: none;
      cursor: pointer;
      font-size: 20px;
      color: #64748b;
      padding: 6px;
      border-radius: 8px;
      transition: background 0.15s;
    }
    .topbar .notif-btn:hover { background: #f1f5f9; }
    .topbar .notif-btn .badge {
      position: absolute;
      top: 2px;
      right: 2px;
      width: 8px;
      height: 8px;
      background: #ef4444;
      border-radius: 50%;
    }
    .avatar {
      width: 36px;
      height: 36px;
      border-radius: 50%;
      background: #3b82f6;
      color: #fff;
      display: flex;
      align-items: center;
      justify-content: center;
      font-size: 14px;
      font-weight: 600;
      cursor: pointer;
    }

    /* ── Content ────────────────────────────────────────────── */
    .content { padding: 24px; max-width: 1024px; }

    .page-header {
      margin-bottom: 24px;
    }
    .page-header h1 { font-size: 22px; font-weight: 700; color: #0f172a; }
    .page-header p { font-size: 14px; color: #64748b; margin-top: 4px; }

    .stats-grid {
      display: grid;
      grid-template-columns: repeat(3, 1fr);
      gap: 16px;
      margin-bottom: 24px;
    }
    .stat-card {
      background: #fff;
      border: 1px solid #e2e8f0;
      border-radius: 12px;
      padding: 20px;
    }
    .stat-card .label {
      font-size: 12px;
      color: #94a3b8;
      text-transform: uppercase;
      letter-spacing: 0.05em;
      font-weight: 500;
    }
    .stat-card .value {
      font-size: 28px;
      font-weight: 700;
      color: #0f172a;
      margin-top: 4px;
    }
    .stat-card .change {
      font-size: 12px;
      margin-top: 4px;
      font-weight: 500;
    }
    .stat-card .change.up { color: #16a34a; }
    .stat-card .change.down { color: #dc2626; }

    .card {
      background: #fff;
      border: 1px solid #e2e8f0;
      border-radius: 12px;
      padding: 24px;
      margin-bottom: 20px;
    }
    .card h2 { font-size: 16px; font-weight: 600; margin-bottom: 8px; }
    .card p { font-size: 14px; color: #64748b; line-height: 1.6; }

    .btn {
      display: inline-flex;
      align-items: center;
      gap: 6px;
      padding: 10px 18px;
      border-radius: 8px;
      font-size: 14px;
      font-weight: 500;
      border: none;
      cursor: pointer;
      transition: all 0.15s;
      font-family: inherit;
    }
    .btn-primary { background: #2563eb; color: #fff; }
    .btn-primary:hover { background: #1d4ed8; }
    .btn-secondary { background: #f1f5f9; color: #334155; border: 1px solid #e2e8f0; }
    .btn-secondary:hover { background: #e2e8f0; }

    .feature-grid {
      display: grid;
      grid-template-columns: repeat(4, 1fr);
      gap: 16px;
    }
    .feature-item {
      background: #fff;
      padding: 20px;
      border: 1px solid #e2e8f0;
      border-radius: 12px;
      text-align: center;
      cursor: pointer;
      transition: all 0.15s;
    }
    .feature-item:hover { border-color: #3b82f6; box-shadow: 0 0 0 1px #3b82f6; }
    .feature-item .icon { font-size: 32px; margin-bottom: 10px; }
    .feature-item .name { font-size: 14px; font-weight: 600; }
    .feature-item .desc { font-size: 12px; color: #94a3b8; margin-top: 6px; line-height: 1.4; }

    .section-title {
      font-size: 15px;
      font-weight: 600;
      margin-bottom: 16px;
      color: #0f172a;
    }

    /* ── Event log ──────────────────────────────────────────── */
    .event-log {
      position: fixed;
      bottom: 0;
      left: 240px;
      right: 0;
      background: #1e293b;
      border-top: 2px solid #3b82f6;
      padding: 10px 16px;
      z-index: 100;
    }
    .event-log h4 {
      font-size: 11px;
      text-transform: uppercase;
      letter-spacing: 0.05em;
      color: #64748b;
      margin-bottom: 6px;
    }
    .event-log .log-content {
      font-family: 'SF Mono', Monaco, monospace;
      font-size: 11px;
      color: #94a3b8;
      max-height: 60px;
      overflow-y: auto;
      line-height: 1.6;
    }
    .event-log .log-content .entry { color: #22d3ee; }
  </style>
</head>
<body>

  <!-- ══════════════════════════════════════════════════════════ -->
  <!-- Sidebar                                                   -->
  <!-- ══════════════════════════════════════════════════════════ -->
  <aside class="sidebar" data-onb="sidebar">
    <div class="logo">MonApp</div>
    <nav>
      <a href="#" class="active" id="nav-dashboard">
        <span class="icon">&#9632;</span> Dashboard
      </a>
      <a href="#" id="nav-projects">
        <span class="icon">&#9776;</span> Projets
      </a>
      <a href="#" id="nav-analytics">
        <span class="icon">&#9679;</span> Analytiques
      </a>
      <a href="#" id="nav-settings">
        <span class="icon">&#9881;</span> Paramètres
      </a>
    </nav>
    <div class="sidebar-footer">
      <button class="upgrade-btn" id="upgrade-btn">Passer en Pro</button>
    </div>
  </aside>

  <!-- ══════════════════════════════════════════════════════════ -->
  <!-- Main content                                              -->
  <!-- ══════════════════════════════════════════════════════════ -->
  <div class="main">
    <header class="topbar">
      <div class="search" id="search-input">
        <span class="icon">&#128269;</span>
        <input type="text" placeholder="Rechercher..." />
      </div>
      <div class="user-area">
        <button class="notif-btn" id="notif-btn">
          &#128276;<span class="badge"></span>
        </button>
        <div class="avatar" id="user-avatar">AM</div>
      </div>
    </header>

    <div class="content" data-onb="main-content">
      <div class="page-header">
        <h1>Dashboard</h1>
        <p>Vue d'ensemble de ton activité</p>
      </div>

      <!-- Stats -->
      <div class="stats-grid">
        <div class="stat-card" id="stat-users">
          <div class="label">Utilisateurs</div>
          <div class="value">1 248</div>
          <div class="change up">+12% ce mois</div>
        </div>
        <div class="stat-card" id="stat-revenue">
          <div class="label">Revenus</div>
          <div class="value">8 420 &euro;</div>
          <div class="change up">+8% ce mois</div>
        </div>
        <div class="stat-card" id="stat-conversion">
          <div class="label">Conversion</div>
          <div class="value">3.2%</div>
          <div class="change down">-0.4% ce mois</div>
        </div>
      </div>

      <!-- Welcome card -->
      <div class="card" id="welcome-card">
        <h2>Bienvenue dans ton espace</h2>
        <p>
          Commence par créer ton premier projet pour découvrir toutes les
          fonctionnalités de la plateforme. Tu peux aussi explorer les
          sections ci-dessous.
        </p>
        <button class="btn btn-primary" id="create-project-btn" style="margin-top: 14px;">
          Créer un projet
        </button>
      </div>

      <!-- Features -->
      <div class="section-title">Fonctionnalités</div>
      <div class="feature-grid">
        <div class="feature-item" id="feature-analytics">
          <div class="icon">&#128202;</div>
          <div class="name">Analytiques</div>
          <div class="desc">Suis tes métriques en temps réel</div>
        </div>
        <div class="feature-item" id="feature-integrations">
          <div class="icon">&#128279;</div>
          <div class="name">Intégrations</div>
          <div class="desc">Connecte tes outils préférés</div>
        </div>
        <div class="feature-item" id="feature-team">
          <div class="icon">&#128101;</div>
          <div class="name">Équipe</div>
          <div class="desc">Collabore avec ton équipe</div>
        </div>
        <div class="feature-item" id="feature-export">
          <div class="icon">&#128228;</div>
          <div class="name">Export</div>
          <div class="desc">Exporte tes données facilement</div>
        </div>
      </div>
    </div>
  </div>

  <!-- ══════════════════════════════════════════════════════════ -->
  <!-- Event log (affiche les événements onboarding en live)     -->
  <!-- ══════════════════════════════════════════════════════════ -->
  <div class="event-log">
    <h4>Événements Onboarding (live)</h4>
    <div class="log-content" id="event-log">
      En attente du widget...
    </div>
  </div>

  <!-- ══════════════════════════════════════════════════════════ -->
  <!-- Saasy Widget — remplace app_ton_app_key par ta vraie clé    -->
  <!-- ══════════════════════════════════════════════════════════ -->
  <script>
    window.SaasyConfig = {
      appKey: "app_ton_app_key",
      // En local : pointe vers ton API
      // apiUrl: "http://localhost:3001",
    };
  </script>
  <script src="https://cdn.saasy.fr/widget.js" async></script>

  <script>
    // ── Identification utilisateur ─────────────────────────
    // Appel identify() pour que le ciblage fonctionne.
    // Adapte les attributs à ton modèle utilisateur.
    document.addEventListener("saasy:ready", function () {
      window.Saasy.identify({
        userId: "usr_demo_001",
        email: "alice@exemple.fr",
        name: "Alice Martin",
        plan: "free",
        createdAt: "2026-02-01",
        sessionCount: 3,
        featureUsagePercent: 20,
      });
    });

    // ── Log des événements onboarding ──────────────────────
    var logEl = document.getElementById("event-log");

    function logEvent(name) {
      return function (e) {
        var detail = e.detail ? JSON.stringify(e.detail) : "";
        var time = new Date().toLocaleTimeString();
        logEl.innerHTML +=
          '<div><span class="entry">[' + time + "] " + name + "</span> " +
          detail + "</div>";
        logEl.scrollTop = logEl.scrollHeight;
      };
    }

    // Écoute tous les événements onboarding
    var events = [
      "saasy:onb:flow:started",
      "saasy:onb:flow:completed",
      "saasy:onb:flow:dismissed",
      "saasy:onb:step:viewed",
      "saasy:onb:step:completed",
      "saasy:onb:step:dismissed",
      "saasy:onb:step:cta_clicked",
      "saasy:onb:checklist:viewed",
      "saasy:onb:checklist:item_completed",
      "saasy:onb:checklist:completed",
      "saasy:onb:checklist:dismissed",
      "saasy:onb:resource:viewed",
      "saasy:onb:resource:clicked",
    ];

    events.forEach(function (evt) {
      document.addEventListener(evt, logEvent(evt));
    });

    // ── API manuelle (optionnel) ───────────────────────────
    // Tu peux aussi déclencher un flow manuellement :
    // window.Saasy.onboarding.startFlow("ton_flow_id");
  </script>

</body>
</html>

Idées de flows à configurer

Voici des parcours que tu peux créer dans le Canvas Builder en utilisant les sélecteurs ci-dessus. Chaque exemple combine plusieurs widgets pour illustrer les possibilités.


Flow "Bienvenue" — Modale + Tooltips + Bannière

Un parcours d'accueil classique qui enchaîne modale, tooltips et bannière :

  1. Modale (layout large) — Message de bienvenue avec titre "Bienvenue sur MonApp !" et contenu présentant les 3 fonctionnalités clés. Ajoute une image ou vidéo de démo en media.
  2. Tooltip sur #stat-users (placement bottom) — "Voici tes métriques. Tu peux suivre l'évolution de tes utilisateurs en temps réel."
  3. Tooltip sur #stat-revenue (placement bottom) — "Consulte l'évolution de tes revenus ici."
  4. Tooltip sur #create-project-btn (placement right) — "Crée ton premier projet pour commencer." Active le backdrop spotlight pour focaliser l'attention.
  5. Bannière (position top, couleur #16a34a) — "Tu as terminé le tour ! Besoin d'aide ? Consulte notre centre de ressources."

Flow "Tour sidebar" — Slideout + Tooltips

Présente la navigation latérale avec un slideout puis des tooltips :

  1. Slideout (position right, largeur md) — Panneau avec titre "Découvre la navigation" et contenu expliquant la structure de la sidebar : Dashboard, Projets, Analytiques, Paramètres.
  2. Tooltip sur #nav-dashboard (placement right) — "Le dashboard est ta page d'accueil."
  3. Tooltip sur #nav-projects (placement right) — "Gère tous tes projets ici."
  4. Tooltip sur #nav-analytics (placement right) — "Analyse tes métriques."
  5. Tooltip sur #nav-settings (placement right) — "Configure ton compte et tes préférences."

Flow "Découverte features" — Modale compact + Tooltips

Un parcours centré sur les fonctionnalités :

  1. Modale (layout compact) — "Découvre nos fonctionnalités" avec un court texte d'introduction.
  2. Tooltip sur #feature-analytics (placement bottom) — "Suis tes métriques en temps réel avec des graphiques interactifs."
  3. Tooltip sur #feature-integrations (placement bottom) — "Connecte Slack, Zapier, et tes outils préférés."
  4. Tooltip sur #feature-team (placement bottom) — "Invite ton équipe et collabore en temps réel."
  5. Tooltip sur #feature-export (placement bottom) — "Exporte tes données en CSV, PDF ou via API."

Flow "Upgrade" — Bannière + Slideout + Tooltip

Un parcours de conversion pour les utilisateurs gratuits :

  1. Bannière (position top, couleur #7c3aed) — "Profite de -20% sur le plan Pro cette semaine !"
  2. Délai — Attendre 10 secondes avant de continuer (laisse l'utilisateur lire la bannière).
  3. Slideout (position right, largeur lg) — Panneau "Passe en Pro" avec un comparatif des fonctionnalités Free vs Pro. Ajoute un bouton CTA "Découvrir le plan Pro" de type link.
  4. Tooltip sur #upgrade-btn (placement top) — "Clique ici pour activer ton plan Pro." Active le backdrop spotlight.

Utilise un segment "Plan gratuit" (condition : plan égal à free) pour cibler uniquement les utilisateurs qui n'ont pas encore fait l'upgrade.


Flow "Onboarding conditionnel" — Condition + Modale + Bannière

Un parcours qui s'adapte au profil de l'utilisateur :

  1. Condition — Attribut sessionCount, opérateur "Supérieur à", valeur 10.
    • Branche vraie : l'utilisateur est expérimenté, on passe à l'étape 2.
    • Branche fausse : l'utilisateur est nouveau, on passe à l'étape 3.
  2. Bannière (position bottom) — "Tu maîtrises MonApp ! Découvre nos fonctionnalités avancées."
  3. Modale (layout large) — "Bienvenue ! On va t'aider à prendre en main MonApp en quelques étapes."

Les branches conditionnelles se configurent dans le Canvas Builder en connectant les sorties "Vrai" et "Faux" du noeud Condition vers des noeuds différents.


Flow "Rappel après délai" — Délai + Bannière

Rappelle une action importante après un délai :

  1. Délai — Attendre 1 jour (l'utilisateur revient le lendemain).
  2. Modale (layout compact) — "Content de te revoir ! Tu n'as pas encore créé de projet. C'est le moment de commencer."
  3. Tooltip sur #create-project-btn (placement right) — "Crée ton premier projet maintenant." Active le backdrop spotlight.

Flow "Bottom sheet mobile" — Modale bottom-sheet + Tooltip

Un parcours optimisé pour les utilisateurs mobiles :

  1. Modale (layout bottom-sheet) — "Bienvenue sur MonApp !" avec un texte court et un bouton "C'est parti". Le bottom-sheet s'affiche depuis le bas de l'écran, idéal pour le mobile.
  2. Tooltip sur #search-input (placement bottom) — "Utilise la recherche pour trouver rapidement ce que tu cherches."
  3. Bannière (position bottom, couleur #0ea5e9) — "Astuce : tu peux utiliser le raccourci Cmd+K pour ouvrir la recherche."

Checklist "Pour bien démarrer"

Crée une checklist avec le mode d'affichage flottant (ou sidebar pour la garder toujours visible) :

ItemDescriptionType CTACible
Configurer ton profilComplète tes informationslink#user-avatar
Créer un projetLance ton premier projetlink#create-project-btn
Explorer les analytiquesDécouvre tes métriqueslink#nav-analytics
Inviter un coéquipierCollabore avec ton équipelink#feature-team
Passer en ProDébloque toutes les fonctionnalitéslink#upgrade-btn

Active la barre de progression et rends la checklist dismissible.


Checklist "Setup technique"

Un exemple de checklist en mode sidebar pour les développeurs :

ItemDescriptionType CTACible
Ajouter le widgetIntègre le script dans ton applinkURL vers la doc d'installation
Configurer l'API keyGénère ta clé dans les paramètreslink#nav-settings
Identifier les utilisateursAppelle Saasy.identify()eventopen-docs
Créer ton premier flowLance le Canvas BuilderflowID du flow de bienvenue

Le type CTA flow permet de déclencher un autre flow d'onboarding directement depuis un item de la checklist. Utilise-le pour chaîner des parcours.

Attributs utilisateur pour le ciblage

L'appel Saasy.identify() dans l'exemple envoie ces attributs que tu peux utiliser dans les segments :

AttributValeurUtilisation
plan"free"Segment "Plan gratuit"
createdAt"2026-02-01"Segment "Nouveaux utilisateurs"
sessionCount3Segment "Utilisateurs débutants" (< 5 sessions)
featureUsagePercent20Segment "Découverte features" (< 50%)

Change ces valeurs pour tester différents segments.