Sign In

A/B Testing SDK

Run experiments directly in your plugin code. Assign players to variants, show different experiences, and track which performs best.

Quick Start

import net.analyse.api.Analyse;
// Get the player's assigned variant
String variant = Analyse.getVariant(player.getUniqueId(), "welcome-rewards");
// Show the appropriate experience
switch (variant) {
case "control":
give(player, new ItemStack(Material.BREAD, 16));
break;
case "diamonds":
give(player, new ItemStack(Material.DIAMOND, 5));
break;
case "tools":
giveStarterTools(player);
break;
}
// Track when they convert
Analyse.trackConversion(
player.getUniqueId(),
player.getName(),
"welcome-rewards",
"played_one_hour"
);

Creating Experiments

Before using the SDK, create your experiment in the dashboard:

  1. Go to A/B Tests in your project
  2. Click "New Experiment"
  3. Configure:
    • Name: "Welcome Rewards"
    • Key: welcome-rewards (use this in your code)
    • Variants: control (50%), diamonds (25%), tools (25%)
    • Primary Metric: played_one_hour
  4. Click "Create" and activate when ready

Getting Variants

Basic Usage

String variant = Analyse.getVariant(player.getUniqueId(), "experiment-key");

Returns:

  • The variant key (e.g., "control", "variant-a")
  • null if the test doesn't exist or isn't active

Deterministic Assignment

The same player always gets the same variant:

// First call
String variant1 = Analyse.getVariant(uuid, "my-test"); // "control"
// Second call (same player, any time later)
String variant2 = Analyse.getVariant(uuid, "my-test"); // "control"
// Always the same!
assert variant1.equals(variant2);

With Fallback

Handle cases where the test isn't active:

String variant = Analyse.getVariant(player.getUniqueId(), "spawn-location");
if (variant == null) {
variant = "default"; // Fallback
}
switch (variant) {
case "spawn-a":
teleport(player, spawnA);
break;
case "spawn-b":
teleport(player, spawnB);
break;
default:
teleport(player, defaultSpawn);
}

Tracking Conversions

Track when a player completes your experiment's goal:

Analyse.trackConversion(
player.getUniqueId(),
player.getName(),
"experiment-key",
"conversion-event-name"
);

Example: First Purchase

// In your purchase handler
@EventHandler
public void onPurchase(PlayerPurchaseEvent event) {
Player player = event.getPlayer();
// Track conversion for active experiments
Analyse.trackConversion(
player.getUniqueId(),
player.getName(),
"welcome-rewards",
"first_purchase"
);
}

Example: Retention

// When player reaches 1 hour playtime
public void onOneHourPlayed(Player player) {
Analyse.trackConversion(
player.getUniqueId(),
player.getName(),
"onboarding-flow",
"played_one_hour"
);
}

Checking Test Status

Is Test Active?

if (Analyse.isTestActive("my-experiment")) {
// Apply experiment logic
} else {
// Use default behavior
}

Get Test Details

ABTest test = Analyse.getTest("welcome-rewards");
if (test != null) {
System.out.println("Test: " + test.getName());
System.out.println("Status: " + test.getStatus());
System.out.println("Variants: " + test.getVariants().size());
}

List All Active Tests

List<? extends ABTest> activeTests = Analyse.getActiveTests();
for (ABTest test : activeTests) {
System.out.println(test.getKey() + " - " + test.getName());
}

Complete Example

public class WelcomeListener implements Listener {
@EventHandler
public void onPlayerJoin(PlayerJoinEvent event) {
Player player = event.getPlayer();
// Skip if not a new player
if (player.hasPlayedBefore()) {
return;
}
// Get variant assignment
String variant = Analyse.getVariant(player.getUniqueId(), "new-player-kit");
if (variant == null) {
variant = "basic"; // Default if test inactive
}
// Apply the variant
switch (variant) {
case "basic":
giveBasicKit(player);
player.sendMessage("Welcome! Here's a starter kit.");
break;
case "premium":
givePremiumKit(player);
player.sendMessage("Welcome! Enjoy this premium starter kit!");
break;
case "guided":
giveBasicKit(player);
startTutorial(player);
player.sendMessage("Welcome! Let me show you around.");
break;
}
}
// Track conversion when player reaches level 10
@EventHandler
public void onLevelUp(PlayerLevelUpEvent event) {
if (event.getNewLevel() == 10) {
Player player = event.getPlayer();
Analyse.trackConversion(
player.getUniqueId(),
player.getName(),
"new-player-kit",
"reached_level_10"
);
}
}
}

ABTestManager

For advanced usage, access the manager directly:

ABTestManager manager = Analyse.abTests();
// Get all active tests
List<? extends ABTest> tests = manager.getActiveTests();
// Get specific test
ABTest test = manager.getTest("my-test");
// Get variant for player
String variant = manager.getVariant(uuid, "my-test");
// Track conversion
manager.trackConversion(uuid, username, "my-test", "purchased");

Test Triggers

Experiments can have different triggers configured in the dashboard:

TriggerWhen Applied
FIRST_JOINOnly on player's first join
EVERY_JOINOn every join
ON_COMMANDWhen player runs a command
ON_EVENTWhen a specific event fires

Check trigger in code:

ABTest test = Analyse.getTest("my-test");
if (test.matchesTrigger(ABTest.Trigger.FIRST_JOIN)) {
// Only apply on first join
}

Best Practices

1. Always Handle Null Variants

String variant = Analyse.getVariant(uuid, "test");
if (variant == null) {
// Test not active - use default behavior
return;
}

2. Keep Variants Simple

Test one thing at a time for clear results:

// ✅ Good - one variable
String color = Analyse.getVariant(uuid, "button-color");
// "red", "blue", or "green"
// ❌ Bad - multiple variables in one test
String combo = Analyse.getVariant(uuid, "ui-changes");
// "red-large-animated" - hard to know what's working

3. Track Meaningful Conversions

// ✅ Good - clear business value
Analyse.trackConversion(uuid, name, "onboarding", "made_purchase");
Analyse.trackConversion(uuid, name, "onboarding", "returned_day_2");
// ❌ Bad - vanity metric
Analyse.trackConversion(uuid, name, "onboarding", "clicked_button");

4. Don't Change Mid-Session

Apply variant once, store the result:

// ✅ Good - store variant
String variant = Analyse.getVariant(uuid, "shop-layout");
playerData.setShopVariant(variant);
// Later, use stored value
openShop(player, playerData.getShopVariant());

Next Steps