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 dependency
Section titled “Add the dependency”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'}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.
Get a client
Section titled “Get a client”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}| Method | Purpose |
|---|---|
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. |
Track an event
Section titled “Track an event”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.
Signatures
Section titled “Signatures”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.
playerIdmust be aUUID. Passingnullfails; 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.
Where the events appear
Section titled “Where the events appear”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.