Skip to content

Developer API

The plugin exposes a small Java API so your own plugins can send custom events without talking to the HTTP API directly. The API handles batching, retries, authentication state, and player identity.

Add the API as a compile-only dependency and declare the plugin as a soft dependency:

repositories {
maven { url 'https://repo.shardanalytics.com/releases' }
}
dependencies {
compileOnly 'com.shardanalytics:api:1.0.0'
}
plugin.yml
softdepend: [ShardAnalytics]

Use softdepend so your plugin still loads when ShardAnalytics is absent, and always check isReady() before sending. If the artifact version has moved, use the coordinates shown with the current connector release.

import com.shardanalytics.api.client.AnalyticsClient;
import com.shardanalytics.api.client.AnalyticsProvider;
AnalyticsClient client = AnalyticsProvider.get();
if (client == null || !client.isReady()) {
return; // ShardAnalytics is not installed, not authenticated, or collection is disabled
}
MethodPurpose
AnalyticsProvider.get()Returns the client, or null when the plugin is unavailable.
AnalyticsProvider.require()Returns the client or throws when it is not initialised.
AnalyticsProvider.isAvailable()Whether a client has been registered.
client.isReady()Authenticated and collection running.
client.isEnabled()Whether event collection is enabled by configuration.

The fluent builder is the recommended path. Custom events are automatically prefixed with custom:.

import com.shardanalytics.api.events.EventBuilder;
import java.util.Map;
client.track(EventBuilder.custom("minigame.win")
.player(player.getUniqueId())
.location(player.getWorld().getName(),
player.getLocation().getBlockX(),
player.getLocation().getBlockY(),
player.getLocation().getBlockZ())
.data("arena", "SkyWars-1")
.data("duration_seconds", 312)
.build());

Or send a raw custom event:

client.trackCustom(
"quest.complete",
player.getUniqueId(),
Map.of("quest_id", "tutorial-03", "xp_rewarded", 250)
);

trackCustom and EventBuilder.custom both register the event under custom:<name>. Payloads must be flat scalars or flat arrays; nested objects are not supported.

All track and trackCustom overloads return CompletableFuture<Void>. You can ignore the future for fire-and-forget events, but handle failures when the event matters:

client.trackCustom("purchase.attempt", player.getUniqueId(), data)
.exceptionally(error -> {
getLogger().warning("Failed to send analytics event: " + error.getMessage());
return null;
});

The future completes when the event has been accepted into the local pipeline, not when the API has stored it. Delivery is asynchronous, batched, and at-least-once.

  • playerId must be a UUID. Passing null fails; skip the call when there is no player.
  • Event names should be stable. Renaming an event splits its history.
  • Keep payload keys snake_case so they read consistently next to built-in events.
  • Do not send secrets, passwords, or private chat content.

Custom events show up in the dashboard after collection. They can be selected as steps in Funnels or charted in Custom Dashboards. See Built-in & Custom Events for the payload contract.