Plainflow Java Client

Our Java library lets you record analytics data from your Java code.

This library is open-source, so you can check it out on Github.

All of our server-side libraries are built for high-performance, so you can use them in your web server controller code. This library uses an internal queue to make all calls non-blocking and fast. It also batches messages and flushes asynchronously to our servers.

Install the library

The recommended way to install the library for Java is with a build system like Gradle or Maven. This makes it dead simple to upgrade and swap out destinations. The library is distributed via Maven Central as a jar dependency.

Here’s what it would look like with Maven:

Add to pom.xml:


or if you’re using Gradle:

compile ''

Initialize the SDK

Before you can send us events, you need to initialize an instance of the Analytics class. To do so, you must use the Analytics.Builder class.

Analytics analytics = Analytics.builder(secretKey).build();

Of course, you’ll want to replace secretKey with your actual Secret Key which you can find in Plainflow in the Settings > API Keys page.

The Builder can also be used to customize behaviour of the Analytics instance.

Note: There is an internal AnalyticsClient class. Do not confuse this class with the public Analytics class and do not use this class directly.

The Analytics class has a method called enqueue that takes a MessageBuilder. Each message class has a corresponding builder that is used to construct instances of a message.

Although not enforced at compile time, make sure you provide either of userId or anonymousId for each message. Failing to do so will raise an exception at runtime.

The following examples use Guava’s immutable maps, but feel free to use plain old Java maps instead.


identify lets you tie a user to their actions and record traits about them. It includes a unique User ID and any optional traits you know about them.

We recommend calling identify a single time when the user’s account is first created, and only identifying again later when their traits change.

Example identify call:

        .put("name", "Mark Twain")
        .put("email", "")

This call is identifying Michael by his unique User ID (the one you know him by in your database) and labeling him with name and email traits.

The identify call has the following fields:

user_id StringThe ID for this user in your database.
traits Traits, optionalA dictionary of traits you know about the user. Things like:email, name or friends.

Note: The enqueue method takes a MessageBuilder instance and not a Message instance directly. This is to allow you to use a MessageTransformer that applies to all incoming messages and transform or add data. Read more in our transformer reference section.

Find details on the identify method payload in our Identify Documentation.


track lets you record the actions your users perform. Every action triggers what we call an “event”, which can also have associated properties.

You’ll want to track events that you’re interested in, such as Signed Up, Item Purchased or Article Bookmarked.

To get started, we recommend tracking just a few important events. You can always add more later!

Example track call:

analytics.enqueue(TrackMessage.builder("Item Purchased")
        .put("item_id", "T-Shirt")
        .put("revenue", 42.24)
        .put("color", "black")

This example track call tells us that your user just triggered the Item Purchased event with a revenue of $42.24 and chose a black T-Shirt.

track event properties can be anything you want to record. In this case, item_id, revenue, and color.

The track call has the following fields:

userId StringThe ID for this user in your database.
event StringThe name of the event you’re tracking. We recommend human-readable names like Video Played or Status Updated.
properties Properties, optionalA dictionary of properties for the event. If the event was Product Added, it might have properties like price or product.

Find details on best practices in event naming as well as the track method payload in our Track Documentation.


The screen method lets you record whenever a user sees a screen of your mobile app, along with optional extra information about the page being viewed.

You’ll want to record a screen event an event whenever the user opens a screen in your app. This could be a view, fragment, dialog or activity depending on your app.

Example screen call:

        .put("category", "Sports")
        .put("path", "/sports/schedule")

The screen call has the following fields:

user_id StringThe ID for this user in your database.
name StringThe webpage name you’re tracking. We recommend human-readable names like Login or Register.
properties Properties, optionalA dictionary of properties for the webpage visit. If the event was Login, it might have properties like path or title.

Find details on the screen payload in our Screen Documentation.

The group call has the following fields:

userId StringThe ID for this user in your database.
groupId StringThe ID for this group in your database.
traits Traits, optionalA dictionary of traits you know about the group. Things like: name or website.

Find more details about group, including the group payload, in our Group Documentation.


alias is how you associate one identity with another. This advanced method is used to associate an anonymous user with an identified user once they sign up.

Example alias call:


Here’s a full example of how we might use the alias call:

// the anonymous user does actions ...
track("anonymous_user", "Anonymous Event");
// the anonymous user signs up and is aliased
alias("anonymous_user", "");
// the signed up user is identified
identify("", new Traits("plan", "Free"));
// the identified user does actions ...
track("", "Identified Action");

For more details about alias, including the alias call payload, check out our Identify Documentation.

Historical Import

You can import historical data by adding the timestamp argument to any of your method calls. This can be helpful if you’ve just switched to Plainflow.

Note: If you’re tracking things that are happening right now, leave out the timestamp and our servers will timestamp the requests for you.

Date historicalDate = ...;
analytics.enqueue(TrackMessage.builder("Button Clicked")


If you’re running a web server, you might want to send context variables such as user_agent or ip with your page or screen calls. You can do so by setting the Context.

analytics.enqueue(TrackMessage.builder("Button Clicked")
        .put("ip", "")
        .put("language", "en-us")


Our libraries are built to support high performance environments. That means it is safe to use analytics-java on a web server that’s serving hundreds of requests per second.

Every method you calldoes notresult in an HTTP request, but is queued in memory instead. Messages are flushed in batch in the background, which allows for much faster operation.

There is a maximum of 500kb per batch request and 15kb per call.

How do I flush right now?

You can also flush on demand. For example, at the end of your program, you’ll want to flush to make sure there’s nothing left in the queue. Just call the flush method:


Calling this method will notify the client to upload any events in the queue.

Multiple Clients

Different parts of your app may require different types of batching. In that case, you can initialize different Analytics instances. Simply use the builder method (you can reuse it with different parameters) to create different instances.

Analytics.Builder builder = Analytics.builder(secretKey);
Analytics first =;
Analytics second = builder.flushInterval(2, TimeUnit.SECONDS).build();


You can enable verbose logging to see what data is being sent over HTTP when debugging issues. You can enable logging by initializing the library like this:

Analytics analytics = Analytics.builder("<secretKey>")


To add a snapshot dependency to your builds, make sure you add the snapshot repository so your build system can look up the dependency.

Maven users can add the following to their pom.xml:

    <name>Sonatype Snapshot Repository</name>

Gradle users should declare this in their repositories block:

repositories {
  maven { url '' }


If you’re having trouble we have a few tips that help common problems.

No events in my debugger

  1. Double check that you’ve followed all the steps in the Quickstart.
  2. Make sure that you’re calling one of our API methods once the library is successfully installed.

Not using Plainflow yet? Get your free account here. 👈