ENbext.dev
DocumentationFonctionnalités

Traduction automatique depuis l’anglais. Consulter l’original.

Sur cette page

Expérimentation / Tests A/B

La fonctionnalité d'expérimentation répond aux trois questions sur lesquelles tout backend de test A/B s'accorde :

  1. Quelle variante de l'expérience X l'utilisateur U devrait-il consulter dès maintenant ? (affectation déterministe par utilisateur)
  2. Enregistrez que nous avons montré la variante V à l'utilisateur U au moment T. (suivi de l'exposition - le dénominateur dans les statistiques finales)
  3. Enregistrez que l'utilisateur U a effectué la métrique M avec la valeur V au moment T. (suivi des résultats – le numérateur dans les statistiques finales)

Le trait est indépendant du fournisseur. Les backends de hachage local, GrowthBook, Statsig, PostHog et Optimizely se connectent tous aux trois mêmes méthodes.

Indicateurs de fonctionnalités et expériences#

Capacité But
FeatureFlag Choisissez le code qui exécute (déploiement, kill switch, ciblage).
Experiment Mesurez quelle variante est la plus performante (exposition + résultats).

Certaines plateformes commerciales regroupent les deux, et il est tentant de les fusionner en une seule fonctionnalité. bext les maintient séparés car les surfaces diffèrent : les indicateurs de fonctionnalités renvoient les variantes bool / String et n'émettent jamais d'analyses ; les expériences renvoient un Variant plus une exposition de demande et des écritures de résultats. Un projet utilisant GrowthBook pour les deux peut toujours installer un plugin qui expose les deux caractéristiques : elles restent simplement distinctes sur le site d'appel.

Le trait#

rust
pub trait ExperimentPlugin: Send + Sync {
    fn name(&self) -> &str;

    fn assign(
        &self,
        experiment: &str,
        ctx: &ExperimentContext,
    ) -> Result<Variant, ExperimentError>;

    fn record_exposure(
        &self,
        exposure: ExposureRecord,
    ) -> Result<(), ExperimentError>;

    fn record_outcome(
        &self,
        outcome: OutcomeRecord,
    ) -> Result<(), ExperimentError>;
}

assign est pur. L'appeler mille fois avec le même contexte renvoie la même variante et n'affecte rien. L'exposition est l'effet secondaire qui fait bouger les statistiques. Les garder séparés permet aux appelants d'attribuer, de répondre à une autre condition, et ensuite seulement d'exposer - le modèle standard rendu par le serveur.

Types de clés#

Taper But
ExperimentContext user_id?, session_id?, attributes: HashMap<String, String>.
Variant experiment, variant_id, is_control: bool.
ExposureRecord experiment, variant_id, user_id?, timestamp.
OutcomeValue Bool(bool), Numeric(f64), Count(i64).
OutcomeRecord experiment, metric, value, user_id?, timestamp.
ExperimentError ExperimentNotFound (404), InvalidContext (400), Backend (500).

user_id est facultatif partout. Les utilisateurs anonymes participent toujours - ils utilisent par défaut la variante de contrôle et la clé d'enregistrement d'exposition/résultat sur session_id à l'intérieur de attributes si le backend le prend en charge.

Formes de valeur de résultat#

Variante Utiliser pour
Bool Conversion binaire (inscrit, cliqué sur CTA, extrait).
Numeric Métrique continue (revenus, temps passé sur la page, profondeur de défilement).
Count Compteur entier (articles ajoutés au panier, pages visitées).

Implémentation de référence : @bext/experiment-hash#

@bext/experiment-hash est un backend** local et déterministe **qui ne nécessite aucun réseau. L'affectation est un hachage FNV-1a de experiment_id + ":" + user_id:

  • Le hachage est réduit à une valeur dans [0, 1).
  • Cette valeur sélectionne une variante en fonction de la répartition configurée.
  • Les utilisateurs anonymes (pas de user_id ) obtiennent toujours la variante de contrôle.

Déterministe signifie que la même paire (experiment, user_id) atterrit sur la même variante pendant toute la durée de vie de l'expérience, ce qui est essentiel pour une UX cohérente entre les requêtes.

toml
[[plugins]]
name = "experiment-hash"
source = "@bext/experiment-hash"

[[plugins.experiments]]
id = "checkout_button_color"
variants = [
    { id = "control",   weight = 50, is_control = true },
    { id = "treatment", weight = 50, is_control = false },
]

Exemple : attribuer, exposer, enregistrer le résultat#

rust
use bext_plugin_api::experiment::*;
use chrono::Utc;

let plugin: &dyn ExperimentPlugin = /* @bext/experiment-hash */;

// 1. Deterministic assignment (pure, no side effects).
let ctx = ExperimentContext::for_user("alice")
    .with_attribute("country", "FR")
    .with_attribute("plan", "pro");
let variant = plugin.assign("checkout_button_color", &ctx)?;

// 2. Render the page and tell the backend the user saw this variant.
let html = render_with_variant(&variant);
plugin.record_exposure(ExposureRecord {
    experiment: "checkout_button_color".into(),
    variant_id: variant.variant_id.clone(),
    user_id: ctx.user_id.clone(),
    timestamp: Utc::now(),
})?;

// 3. Later — the user converts. Record the outcome.
plugin.record_outcome(OutcomeRecord {
    experiment: "checkout_button_color".into(),
    metric: "signup".into(),
    value: OutcomeValue::Bool(true),
    user_id: ctx.user_id,
    timestamp: Utc::now(),
})?;

Exposition avant le résultat, toujours#

L'invariant attendu par chaque backend d'expérimentation : enregistrer l'exposition avant les résultats de. L'exposition est ce qui fait que l'utilisateur participe à l'expérience ; les résultats attribués à un utilisateur qui n’a jamais été exposé sont rejetés par le moteur d’analyse. bext n'applique pas l'ordre au niveau des traits - cela dépend de l'appelant - mais l'ordre est important pour que les nombres aient un sens.

Attention

assign est une fonction pure - son appel fait que et non enregistrent une exposition. Vous devez appeler explicitement record_exposure après le rendu. Ignorer cette étape signifie que les utilisateurs sont attribués à des variantes mais ne sont jamais comptés dans le dénominateur du test, ce qui rend les résultats invalides.

Indicateur de fonctionnalité#

Aucun. Le trait et les types d'expérience se trouvent dans bext-plugin-api et sont toujours disponibles ; aucune fonction de chargement ne les bloque.

Voir aussi#

  • @bext/experiment-hash — backend déterministe local.
  • Indicateur de fonctionnalité — sélection du chemin de code (déploiement, kill switch) distincte de la mesure expérimentale.
  • Session — d'où vient généralement le user_id stable pour le regroupement déterministe.
  • Traceur — corrèle les affectations de variantes d'expérience avec les traces distribuées.
  • Aperçu des capacités — la liste complète des fonctionnalités enfichables.
Modifier cette page ↗Besoin d’aide ? ↗
Rechercher dans la documentation

Saisissez un sujet, une commande ou une question.