Analyse
SDKCustom events

SDK

Custom events

Send any custom event from your plugin with properties you care about.

Custom events are how you teach Analyse about the things that make your server unique. The SDK has a small fluent builder for them.

Quick example

java
import net.analyse.api.Analyse;
public class QuestListener implements Listener {
@EventHandler
public void onQuestComplete(QuestCompleteEvent event) {
Player player = event.getPlayer();
Analyse.trackEvent("quest_completed")
.withPlayer(player.getUniqueId(), player.getName())
.withData("quest_id", event.getQuestId())
.withData("difficulty", event.getDifficulty())
.withValue(event.getRewardValue())
.send();
}
}

That's it. Every time a quest completes, Analyse gets an event with the quest ID, difficulty, and reward value, linked to the player.

The builder

java
Analyse.trackEvent(String name)
.withPlayer(UUID uuid, String username)
.withData(String key, Object value)
.withData(Map<String, Object> values)
.withValue(double value)
.send();
  • name is the event name. Lowercase with underscores: quest_completed, first_kill, crate_opened.
  • withPlayer links the event to a player. Optional but almost always useful.
  • withData adds a property. Call it as many times as you want.
  • withValue is a numeric "main metric" for the event (reward amount, damage dealt, price paid). Used for sum/average widgets in Dashboards.
  • send fires the event. Fire-and-forget.

Rules

  • Name stability matters. Don't rename events. If you have to, treat it as a new event and keep the old name for a while.
  • Limit properties. 10 or fewer per event is the sweet spot. Overdoing it makes filtering confusing.
  • Primitive values only. Numbers, booleans, strings. Objects are stringified which is rarely what you want.
  • Don't send PII. No email, no IP, no real names. Minecraft username and UUID are fine.
  • Run off-thread if your event handler is performance-sensitive. send() is non-blocking but event bodies can be large.

Checking availability

If your plugin should also work when Analyse is missing, wrap the calls:

java
if (Analyse.isAvailable()) {
Analyse.trackEvent("quest_completed")
.withPlayer(player.getUniqueId(), player.getName())
.send();
}

Or if you want to silently skip when the API is not ready:

java
try {
Analyse.trackEvent("quest_completed")
.withPlayer(player.getUniqueId(), player.getName())
.send();
} catch (IllegalStateException ignored) {
// Analyse not initialized yet, that's fine
}

Good events to add first

  • tutorial_finished with duration_seconds, skipped_steps
  • first_kill with weapon, target_type
  • rank_activated with rank_name, price
  • store_viewed with source (what triggered the open)
  • match_finished with result, duration_seconds

See Custom events for the product-side view and Funnels for using them as steps.

Events from a backend (with a proxy)

If you run Velocity or BungeeCord in front of your backends, and you want a backend to send events through the proxy, use AnalyseMessaging. See Plugin messaging.