Concepts fondamentaux
Presage repose sur un petit ensemble de primitives composables. Comprendre ces concepts vous aidera à concevoir des interfaces adaptatives efficaces.
UserContext
Section intitulée « UserContext »Le UserContext est la source de vérité unique sur l’identité de l’utilisateur et son comportement. Il combine trois dimensions :
interface UserContext { traits: UserTraits // Static data you set (role, plan, company) signals: BehavioralSignals // Auto-computed from tracked events maturity: Maturity // Automatic segment: 'new' | 'onboarding' | 'active' | 'power' | 'dormant'}UserTraits
Section intitulée « UserTraits »Les traits sont des attributs statiques que vous définissez explicitement, typiquement depuis votre système d’authentification ou le profil utilisateur.
interface UserTraits { userId?: string role?: string plan?: string signupDate?: string company?: string companySize?: number locale?: string [key: string]: unknown // Extensible with any custom field}Définissez les traits avec client.identify() ou client.updateTraits().
BehavioralSignals
Section intitulée « BehavioralSignals »Les signaux comportementaux sont calculés automatiquement à partir des événements suivis. Vous ne les définissez jamais directement.
interface BehavioralSignals { sessionCount: number totalEvents: number featureUsage: Record<string, number> lastSeenAt: string firstSeenAt: string currentSessionDuration: number daysSinceSignup: number clickMap: Record<string, number> customSignals: Record<string, number>}Par exemple, après avoir suivi client.track('feature_used', { featureId: 'export' }) trois fois, signals.featureUsage.export vaudra 3.
Maturity
Section intitulée « Maturity »La maturité est un segment calculé dérivé des signaux comportementaux. Elle classe les utilisateurs en cinq niveaux :
| Segment | Signification |
|---|---|
new | Peu de sessions (par défaut : 3 ou moins) |
onboarding | En phase d’apprentissage (par défaut : 4-10 sessions) |
active | Utilisateur régulier ayant dépassé la phase d’intégration |
power | Utilise de nombreuses fonctionnalités (par défaut : 5+ fonctionnalités distinctes) |
dormant | Inactif depuis trop longtemps (par défaut : 14+ jours) |
Les seuils sont configurables via MaturityConfig.
Points d’adaptation
Section intitulée « Points d’adaptation »Un point d’adaptation est un endroit de votre interface où différentes variantes peuvent être affichées. Il est défini par :
interface AdaptationPoint { id: string // Unique identifier (e.g. 'onboarding') variants: readonly string[] // Available variant IDs defaultVariant: string // Fallback when no rule matches strategy: Strategy // How to select (currently: { type: 'rules' })}En React, le composant <Adaptive> crée un point d’adaptation implicitement à partir de ses props et enfants.
Une règle associe un ensemble de conditions à une action. Quand les conditions correspondent au UserContext courant, l’action détermine ce qui se passe au point d’adaptation.
interface AdaptationRule { id: string // Unique identifier adaptationId: string // Which adaptation point this rule targets priority: number // Higher priority rules are evaluated first conditions: ConditionGroup // Boolean logic tree action: AdaptationAction // What to do when conditions match}Conditions
Section intitulée « Conditions »Une Condition vérifie un seul champ dans le contexte utilisateur :
interface Condition { field: string // Dot-path: 'traits.role', 'signals.sessionCount', 'maturity' operator: ConditionOperator // One of 14 operators value: unknown // Value to compare against}Groupes de conditions
Section intitulée « Groupes de conditions »Les groupes combinent les conditions avec de la logique booléenne :
interface ConditionGroup { all?: (Condition | ConditionGroup)[] // AND — all must match any?: (Condition | ConditionGroup)[] // OR — at least one must match not?: Condition | ConditionGroup // NOT — inverts the result}Les groupes peuvent être imbriqués à une profondeur arbitraire.
Une action décrit ce qui se passe quand une règle correspond :
type AdaptationAction = | { type: 'show'; variantId: string } // Show a specific variant | { type: 'hide' } // Hide the adaptation point entirely | { type: 'reorder'; order: string[] } // Reorder items (e.g. navigation) | { type: 'modify'; props: Record<string, unknown> } // Modify component propsStratégies
Section intitulée « Stratégies »Une stratégie détermine comment les variantes sont sélectionnées. Actuellement, seule l’évaluation par règles est disponible :
type Strategy = { type: 'rules' }A venir dans la v0.2 : Des stratégies de type multi-armed bandit qui optimisent automatiquement la sélection des variantes en fonction des métriques de conversion.
Le tracker enregistre les événements utilisateur et alimente le pipeline de calcul des signaux.
// Track events with optional propertiesclient.track('feature_used', { featureId: 'dashboard-export' })client.track('click', { elementId: 'nav-settings' })client.track('custom_signal', { signalId: 'engagement', value: 5 })Les noms d’événements spéciaux déclenchent des calculs de signaux spécifiques :
feature_usedavecfeatureId— incrémentesignals.featureUsage[featureId]clickavecelementId— incrémentesignals.clickMap[elementId]custom_signalavecsignalIdetvalue— incrémentesignals.customSignals[signalId]
Vous pouvez également brancher des adaptateurs d’analytique externes (Segment, PostHog, etc.) pour transférer les événements.
Persistance
Section intitulée « Persistance »La persistance conserve les traits et signaux entre les rechargements de page. Deux drivers intégrés sont fournis :
createLocalStorageDriver(prefix)— Stocke les données danslocalStoragesous une clé namespacéecreateMemoryDriver()— Stockage en mémoire pour le SSR et les tests
Quand un driver de persistance est configuré, le client lit les données en cache de manière synchrone à l’initialisation, ce qui évite un flash de contenu par défaut (anti-FOUC).
Flux de résolution
Section intitulée « Flux de résolution »Quand un composant demande une variante, voici ce qui se passe :
- Le composant déclare un
AdaptationPoint(id, variantes, défaut) - Le moteur de règles filtre les règles par
adaptationId - Les règles sont évaluées par ordre de priorité (la plus haute d’abord)
- La première règle dont les conditions correspondent renvoie son action
- L’action détermine quelle variante est rendue
- Si aucune règle ne correspond, le
defaultVariantest utilisé - Un événement
presage:impressionest automatiquement suivi
L’ensemble de ce flux est synchrone et se produit dans un seul cycle de rendu.