Busabase
Busabase is an open-source (MIT) database and workspace for AI agents — data, docs, skills, and apps in one place. Run it locally, self-host it inside your network, or use Busabase Cloud, and turn age
翻訳待ち
See who is in your app and on its website right now, where visitors come from, how they use features, whether the new release helped, and what goes with revenue. One project for both, one ready-made p
翻訳待ち
データKotlinGitHub @tapllオンライン所有者未確認
Have you tried it? One tap is enough. No sign-in needed.
Tapll Android SDK (Kotlin, Jetpack Compose) and Gradle plugin for R8 mapping upload.
翻訳待ち
Loading the full README.
Read the full README ↗Product analytics and crash reporting for Android apps: live sessions, screens, features, releases, crashes, ANRs. Kotlin, minSdk 24, no third-party dependencies beyond AndroidX lifecycle and kotlinx-coroutines, no advertising ID.
| Artifact | What it is |
|---|---|
com.tapll:tapll | the SDK |
com.tapll:tapll-compose | TrackScreen("Name") for Jetpack Compose |
Gradle plugin com.tapll | build id + R8 mapping upload, so crash stacks are readable |
// app/build.gradle.kts
plugins {
id("com.android.application")
id("com.tapll") version "0.2.0" // optional, see "Readable crash stacks"
}
dependencies {
implementation("com.tapll:tapll:0.2.0")
implementation("com.tapll:tapll-compose:0.2.0") // only if you use Compose
}
The SDK declares android.permission.INTERNET in its own manifest (a normal permission, no prompt).
Integrating with a coding agent (Claude Code, Cursor, Codex)? Copy the setup prompt from the Tapll panel, Settings -> SDK setup: it is filled in with your project's write key, privacy mode and connected integrations. A generic version is at tapll.com/llms.txt.
dev.useunion:union 0.1.x)0.2.0 is the Union to Tapll rename. It is a new set of coordinates and a new package, so the upgrade is a one-time edit:
| Before | Now |
|---|---|
dev.useunion:union | com.tapll:tapll |
dev.useunion:union-compose | com.tapll:tapll-compose |
Gradle plugin dev.useunion.union, extension union { } | Gradle plugin com.tapll, extension tapll { } |
import dev.useunion.*, Union.configure(...) | import com.tapll.*, Tapll.configure(...) |
UNION_SERVER_KEY, -Punion.enabled | TAPLL_SERVER_KEY, -Ptapll.enabled (the old names still work as a fallback) |
default endpoint https://in.useunion.dev | https://in.tapll.com |
RevenueCat attribute union_install_id | tapll_install_id |
com.tapll.Union remains as a deprecated typealias of Tapll for one or two minor releases (Kotlin only), so Union.track(...) keeps compiling with a warning. Apps already in the field keep working: the first launch on 0.2.0 moves the on-device state (noBackupFilesDir/Union to noBackupFilesDir/Tapll: install id, offline queue, pending crash reports) to the new location, so the install id and anything unsent from the previous launch survive. Builds made with the old Gradle plugin still get their build id read from assets/union-build-id.txt.
class MyApp : Application() {
override fun onCreate() {
super.onCreate()
Tapll.configure(this, writeKey = "av_...", privacyMode = PrivacyMode.ProductAnalytics)
}
}
Register MyApp in the manifest (android:name=".MyApp"). That already sends $first_open, $app_install / $app_update, $session_start / $session_end, $foreground / $background and device context (app version + build, Android version, device model, locale, timezone). The panel's Live view shows the first session within seconds.
Tapll.screen("WorkoutDetail") // or TrackScreen("WorkoutDetail") in Compose
Tapll.track("workout_started", mapOf("plan" to "strength", "minutes" to 30), role = FeatureRole.Start)
Tapll.track("workout_finished", role = FeatureRole.Success)
Tapll.identify("user_123") // after login (ProductAnalytics only)
Tapll.identify("user_123", mapOf("email" to "[email protected]", "name" to "Ada")) // named in the panel
Tapll.reset() // on logout
Tapll.handleDeepLink(intent) // onCreate / onNewIntent; or handleDeepLink(uri)
Traits describe the person, so the panel can head a profile with a name instead of an id. Up to 8 keys, values up to 256 characters, merged key by key across calls; reset() forgets them with the user id. They are stored as sent: an app that puts an email or a name here is collecting that data and must declare it in its own Play Data safety form, which the SDK cannot do on its behalf.
Event names: lowercase snake_case, max 64 characters. Properties: up to 32 keys; values are String (up to 256 characters), finite numbers or Boolean. Anything invalid is logged and dropped. The SDK never throws into your app.
@Composable
fun CheckoutScreen() {
TrackScreen("Checkout", feature = "checkout") // one $screen_view per entry into the composition
...
}
TrackScreen fires when the composable enters the composition, not on every recomposition; it fires again when name or feature change, or when it leaves and comes back. For view-based apps, set Options.automaticScreenTracking = true: every Activity.onResume becomes a $screen_view named with the activity's simple name (a rotation is the same screen and is not counted twice). Single-activity apps with fragments or custom navigation call Tapll.screen("Name").
Declare a feature where its events are sent, and the funnel builds itself:
val checkout = Tapll.feature("checkout")
checkout.screen("Checkout") // discovery: saw it exists
checkout.start("checkout_started") // start: tried; the funnel's denominator
checkout.use("shipping_selected") // use: working inside it, not a step
checkout.success("order_placed", mapOf("total" to 49.9)) // success: got what they came for
checkout.failure("payment_failed") // failure: the user's attempt failed
This is the beginning of the README. Read the rest at the original. Read the full README ↗