Analytics for Clojure

The clojure library lets you record analytics data from your clojure code. The requests hit our servers, and then we route your data to any analytics service you enable on your integrations page.

The library is open-source and was contributed by the very awesome Ardoq, thanks! 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 identify and track calls non-blocking and fast. It also batches messages and flushes asynchronously to our servers.

Getting Started

If you’re using Maven add this repository definition to your pom.xml:

<repository>
  <id>clojars.org</id>
  <url>http://clojars.org/repo</url>
</repository>

Then, if you’re using Leiningen

[analytics-clj "0.3.0"]

or with Maven

<dependency>
  <groupId>analytics-clj</groupId>
  <artifactId>analytics-clj</artifactId>
  <version>0.2.1</version>
</dependency>

You only need to initialize once at the start of your program. You can then keep using the Analytics singleton anywhere in your code.

;; initialize the #{source.owner.login}/#{source.slug} source ..
ardoq.analytics-clj> (def client (initialize "YOUR_WRITE_KEY"))

The default initialization settings are production-ready.

Identify

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 are change.

Example identify call:

;; (identify client user-id traits & [{:keys [timestamp options callback]}])
ardoq.analytics-clj> (identify client "019mr8mf4r" {:email "#{ user.email }"})

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

The identify call has the following fields:

user-id StringThe ID for this user in your database.
traits Map, optionalA map of traits you know about the user. Things like: email, name or friends.
timestamp DateTime, optionalA DateTime object representing when the identify took place. If the identify just happened, leave it out blank and we’ll use the server’s time. If you’re importing data from the past, make sure you to provide a timestamp.
options Map, optionalA map of extra options.
callback Function, optionalA callback that’s fired when this identify call is flushed to the server. Note: this callback is fired on the same thread as the async event loop that made the request. You should not perform any kind of long running operation on it.

Find details on the identify method payload in our Spec.

Track

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 are indicators of success for your site, like 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:

;; (track client user-id event properties & [{:keys [timestamp options callback]}])
ardoq.analytics-clj> (track client "019mr8mf4r" "Signed Up" {:plan {:type "trial"}})

This example track call tells us that your user just triggered the Signed Up event on a “trial” plan.

track event properties can be anything you want to record. In this case, plan type.

The track call has the following fields:

user-id StringThe ID for this user in your database.
event StringThe name of the event you’re tracking. We recommend human-readable names like Song Played or Status Updated.
properties Map, optionalA map of properties for the event. If the event was Added to Cart, it might have properties like price or product.
timestamp DateTime, optionalA DateTime representing when the event took place. If the identify just happened, leave it out and we’ll use the server’s time. If you’re importing data from the past make sure you send a timestamp.
options Map, optionalA map of extra options.
callback Function, optionalA callback that’s fired when this track call is flushed to the server. Note: this callback is fired on the same thread as the async event loop that made the request. You should not perform any kind of long running operation on it.

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

Alias

alias is how you associate one identity with another. This is an advanced method, but it is required to manage user identities successfully in some of our integrations.

In Mixpanel it’s used to associate an anonymous user with an identified user once they sign up. For KISSmetrics, if your user switches IDs, you can use ‘alias’ to rename the ‘userId’.

Example alias call:

;; (make-alias client from to & [{:keys [timestamp options callback]}])
ardoq.analytics-clj> (make-alias client "user-id" "real-id")

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

;; the anonymous user does actions ...
ardoq.analytics-clj> (track client "anonymous_user" "Anonymous Event")
;; the anonymous user signs up and is aliased
ardoq.analytics-clj> (make-alias client "anonymous_user" "identified@gmail.com")
;; the identified user is identified
ardoq.analytics-clj> (identify client "identified@gmail.com" {:plan "Free"})
;; the identified user does actions ...
ardoq.analytics-clj> (track client "identified@gmail.com" "Identified Action")

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


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 Segment.

Historical imports can only be done into integrations that can accept historical timestamp’ed data. Most analytics tools like Mixpanel, Amplitude, Kissmetrics, etc. can handle that type of data just fine. One common integration that does not accept historical data is Google Analytics since their API cannot accept historical data.

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

Batching

Our libraries are built to support high performance environments. That means it is safe to use analytics-clj on a web server that’s serving hundreds of requests per second. Since the clojure library is a wrapper around the Java library, check out the java benchmark.

Every method you call does not result 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.

Our library will flush using exactly one background thread to prevent CPU or network starvation.

What happens if there are just too many messages?

If the module detects that it can’t flush faster than it’s receiving messages, it’ll simply stop accepting messages. This means your program will never crash because of a backed up analytics queue. The maxQueueSize defaults to 10000, and here’s how you can change it:

ardoq.analytics-clj> (def client (initialize "YOUR_WRITE_KEY" {:max-queue-size 10000}))

Troubleshooting

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—identify, track, etc.

No events in my end tools

  1. Double check your credentials for that integration.

  2. Make sure that the integration you are troubleshooting can accept server-side API calls. Compatibility is shown on the integration docs pages and on the sheets on your Segment source Integrations page.

  3. Check out the integration’s documentation to see if there are other requirements for using the method and integration you’re trying to get working.


If you have any questions or see anywhere we can improve our documentation, please let us know or kick off a conversation in the Segment Community!