Plugin Messaging
Send analytics events from backend servers through your proxy. This allows Paper/Spigot servers to track events without configuring API keys on each server.
Architecture
1
Your Plugin calls AnalyseMessaging.event(...)
2
Message sent via player.sendPluginMessage()
3
Proxy receives on "analyse:events" channel
4
Analyse plugin forwards to API
5
Event appears in your dashboard
When to Use
Use plugin messaging when:
- Your proxy has the Analyse plugin with API key configured
- Backend servers don't have (or need) their own API keys
- You want centralized event routing through the proxy
Setup
1. Add the SDK to Your Backend Plugin
<dependency><groupId>net.analyse</groupId><artifactId>analyse-api</artifactId><version>0.4.0</version><scope>provided</scope></dependency>
2. Register the Channel
Register the plugin messaging channel on your backend server:
import net.analyse.api.messaging.AnalyseMessaging;@Overridepublic void onEnable() {// Register the outgoing channelgetServer().getMessenger().registerOutgoingPluginChannel(this,AnalyseMessaging.CHANNEL);}@Overridepublic void onDisable() {// Unregister on disablegetServer().getMessenger().unregisterOutgoingPluginChannel(this);}
Sending Events
Basic Event
import net.analyse.api.messaging.AnalyseMessaging;public void trackCrateOpen(Player player, String crateType) {try {byte[] message = AnalyseMessaging.createEventMessage("crate_opened",player.getUniqueId(),player.getName(),Map.of("crate_type", crateType),null // no numeric value);player.sendPluginMessage(plugin, AnalyseMessaging.CHANNEL, message);} catch (IOException e) {plugin.getLogger().warning("Failed to send event: " + e.getMessage());}}
Using the Builder
import net.analyse.api.messaging.AnalyseMessaging;public void trackPurchase(Player player, String item, double price) {try {byte[] message = AnalyseMessaging.event("shop_purchase").withPlayer(player.getUniqueId(), player.getName()).withData("item", item).withData("category", "weapons").withValue(price).build();player.sendPluginMessage(plugin, AnalyseMessaging.CHANNEL, message);} catch (IOException e) {plugin.getLogger().warning("Failed to send event: " + e.getMessage());}}
Tracking Conversions
Send A/B test conversion events:
import net.analyse.api.messaging.AnalyseMessaging;public void trackConversion(Player player, String testKey, String event) {try {byte[] message = AnalyseMessaging.createConversionMessage(player.getUniqueId(),player.getName(),testKey,event);player.sendPluginMessage(plugin, AnalyseMessaging.CHANNEL, message);} catch (IOException e) {plugin.getLogger().warning("Failed to send conversion: " + e.getMessage());}}
Complete Example
public class MyPlugin extends JavaPlugin {@Overridepublic void onEnable() {// Register the channelgetServer().getMessenger().registerOutgoingPluginChannel(this,AnalyseMessaging.CHANNEL);// Register listenersgetServer().getPluginManager().registerEvents(new GameListener(this), this);}@Overridepublic void onDisable() {getServer().getMessenger().unregisterOutgoingPluginChannel(this);}/*** Send an event through the proxy*/public void sendEvent(Player player, String eventName, Map<String, Object> data) {try {byte[] message = AnalyseMessaging.event(eventName).withPlayer(player.getUniqueId(), player.getName()).withData(data).build();player.sendPluginMessage(this, AnalyseMessaging.CHANNEL, message);} catch (IOException e) {getLogger().warning("Failed to send event: " + e.getMessage());}}}public class GameListener implements Listener {private final MyPlugin plugin;public GameListener(MyPlugin plugin) {this.plugin = plugin;}@EventHandlerpublic void onQuestComplete(QuestCompleteEvent event) {Player player = event.getPlayer();Quest quest = event.getQuest();plugin.sendEvent(player, "quest_completed", Map.of("quest_id", quest.getId(),"quest_name", quest.getName(),"difficulty", quest.getDifficulty().name(),"time_minutes", event.getCompletionTimeMinutes()));}}
API Reference
AnalyseMessaging
| Method | Description |
|---|---|
CHANNEL | The channel name: analyse:events |
createEventMessage(...) | Create an event message |
createConversionMessage(...) | Create a conversion message |
event(name) | Start building an event message |
EventMessageBuilder
| Method | Description |
|---|---|
withPlayer(uuid, username) | Set the player |
withData(key, value) | Add a data field |
withValue(double) | Set numeric value |
build() | Build the message bytes |
How It Works
- Your backend plugin creates a message using
AnalyseMessaging - Message is sent via
player.sendPluginMessage() - Proxy receives on
analyse:eventschannel - Proxy parses and forwards to Analyse API
- Event appears in your dashboard
The proxy automatically adds _source_server to event data so you can see which backend server sent each event.
Requirements
- Analyse plugin installed on your proxy (Velocity or BungeeCord)
- API key configured on the proxy
- Backend servers do not need their own API key
Troubleshooting
Events not appearing
- Check proxy console for debug messages (enable
debug: true) - Verify the channel is registered on your backend plugin
- Ensure a player is online (plugin messages require a player connection)
IOException when building message
- Ensure all required fields are set (player UUID is required)
- Check that data values are serializable (primitives, strings, maps, lists)