Skip to main content

Kotlin SDK

The Kotlin SDK provides the analytics runtime for JVM and Android applications.

Modules

ModuleMaven coordinatesPurpose
apiio.event-spec:api-kotlinCore runtime — Client, Provider interface, Hook system, context
provider-amplitudeio.event-spec:kotlin-provider-amplitudeAmplitude HTTP API adapter

Installation

Add the GitHub Packages repository and declare dependencies in your libs.versions.toml:

gradle/libs.versions.toml
[versions]
event-spec = "0.1.0"

[libraries]
event-spec-api = { module = "io.event-spec:api-kotlin", version.ref = "event-spec" }
event-spec-provider-amplitude = { module = "io.event-spec:kotlin-provider-amplitude", version.ref = "event-spec" }
build.gradle.kts
repositories {
maven {
url = uri("https://maven.pkg.github.com/dejanradmanovic/event-spec")
credentials {
username = System.getenv("GITHUB_ACTOR")
password = System.getenv("GITHUB_TOKEN")
}
}
}

dependencies {
implementation(libs.event.spec.api)
implementation(libs.event.spec.provider.amplitude)
}

Setup

import io.eventspec.analytics.Client
import io.eventspec.analytics.ClientOptions
import io.eventspec.analytics.amplitude.AmplitudeConfig
import io.eventspec.analytics.amplitude.AmplitudeProvider

val amp = AmplitudeProvider(
AmplitudeConfig(apiKey = System.getenv("AMPLITUDE_API_KEY")!!)
)

val client = Client(ClientOptions(providers = listOf(amp)))

Tracking events

client.track(Event(
name = "Product Viewed",
properties = mapOf(
"product_id" to "SKU-123",
"category" to "electronics",
),
))

Per-provider outcomes

track throws on pre-dispatch failures. Use trackDetailed for per-provider results:

val result = client.trackDetailed(event)
// result.success — providers that succeeded
// result.failed — providers that failed permanently
// result.partialSuccess — at least one succeeded

Identify

client.identify("user-123", mapOf(
"email" to "alice@example.com",
"plan" to "pro",
))

Group

client.group("user-123", "org-456", mapOf(
"name" to "Acme Corp",
"plan" to "enterprise",
))

Page

client.page("user-123", "Checkout", mapOf("url" to "/checkout"))

Alias

client.alias("user-123", "anon-abc")

Context propagation

Set startup metadata once globally:

import io.eventspec.analytics.setGlobalContext
import io.eventspec.analytics.AnalyticsContext

setGlobalContext(AnalyticsContext(
attributes = mapOf(
"locale" to "en-US",
"app" to mapOf("name" to "my-app", "version" to "2.1.0"),
),
))

Per-request identity via withTransaction:

val reqClient = client.withTransaction(AnalyticsContext(
userId = "user-123",
anonymousId = sessionId,
))
reqClient.track(Event(name = "Checkout Started"))

Using generated wrappers

import analytics.EventSpec
import analytics.ProductViewedProperties
import analytics.ProductViewedCategory

val es = EventSpec(client)

es.productViewed(ProductViewedProperties(
category = ProductViewedCategory.ELECTRONICS,
productId = "SKU-123",
))

Built-in hooks

import io.eventspec.analytics.SamplingHook
import io.eventspec.analytics.SamplingStrategy
import io.eventspec.analytics.SamplingPolicy
import io.eventspec.analytics.ValidationHook

val samplingHook = SamplingHook { eventName ->
SamplingPolicy(strategy = SamplingStrategy.USER_ID_HASH, rate = 0.1)
}

val validationHook = ValidationHook { eventName, properties ->
// return an error string, or null if valid
null
}

val client = Client(ClientOptions(
providers = listOf(amp),
hooks = listOf(validationHook, samplingHook),
))

Coroutines

All dispatch methods (track, identify, group, page, alias) are suspend functions. Call them from a coroutine scope:

import kotlinx.coroutines.runBlocking

runBlocking {
client.track(Event(name = "App Started"))
}

Shutdown

client.shutdown()