Android SDK
Kixo Android SDK stöder Kotlin 2.0+ och Java, kräver minSdk 24 (Android 7.0) och är byggt mot compileSdk 35. Din app ansvarar fortfarande för sin egen targetSdk. Med ett enda anrop till Kixo.configure i din Application.onCreate spåras skärmar, tryck, sessioner, krascher och livscykelhändelser automatiskt. Push-spårning kräver FCM-bryggan som beskrivs nedan. Automatisk spårning av nätverksanrop ingår inte i den aktuella Android-versionen. SDK:t stöder också sessionsåterspelning, identitet och mål.
Snabbstart
Tre filer. Lägg till Maven-repot, lägg till beroendet och lägg sedan in två rader i din underklass av Application.
Byggkrav: compileSdk 35, minSdk 24, Kotlin 2.0+ eller Java samt Java 17-bytekod.
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
maven {
url = uri("https://raw.githubusercontent.com/kixoio/kixo-android-sdk/main/repo")
}
}
}Obs!
Det är hela analysintegrationen. Standardspårare är aktiverade som standard, men push kräver fortfarande FCM-bryggan nedan. Skriv bara över enskilda flaggor med KixoConfiguration.Builder(...) när det behövs.
Lägg till i appen
Kixo Maven-repo ligger på GitHub Pages. Lägg till det tillsammans med google() och mavenCentral() i settings.gradle.kts:
// settings.gradle.kts
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
maven {
url = uri("https://raw.githubusercontent.com/kixoio/kixo-android-sdk/main/repo")
}
}
}Deklarera sedan beroendet i appmodulen:
// app/build.gradle.kts
dependencies {
implementation("io.kixo:kixo-android-sdk:0.1.20")
}Tips
android.permission.INTERNET och android.permission.ACCESS_NETWORK_STATE ingår i SDK-manifestet. Behörigheter för notiser hanteras fortfarande av appen och deklareras när du väljer att använda pushfunktionerna.
Projekt med flera moduler
Gradles konfiguration implementation är inte transitiv: om du deklarerar implementation("io.kixo:kixo-android-sdk:0.1.20") i en biblioteksmodul, till exempel :core_domain, blir Kixo INTE synligt för :app eller någon annan konsument. Det finns två fungerande mönster — välj ett.
Mönster A — varje modul som anropar Kixo deklarerar beroendet själv (rekommenderas). Det håller klassökvägen minimal i varje modul och undviker ombyggnader som spiller över i kedjan. Använd en versionskatalog (libs.kixo.sdk) så att du bara ändrar versionen på ett ställe.
// :core_domain/build.gradle.kts
dependencies {
implementation("io.kixo:kixo-android-sdk:0.1.20") // local use only
}
// :app/build.gradle.kts
dependencies {
implementation(project(":core_domain"))
implementation("io.kixo:kixo-android-sdk:0.1.20") // declared again — fine
}Mönster B — återexportera via api(...). En enda deklaration, men biblioteksmodulens publika ABI innehåller då Kixo-typer — varje versionshöjning tvingar fram ombyggnad av alla nedströmsmoduler. Använd bara detta när biblioteket återanvänder Kixo-typer i sina egna publika signaturer, till exempel returnerar KixoDiagnostics från en funktion.
// :core_domain/build.gradle.kts
dependencies {
api("io.kixo:kixo-android-sdk:0.1.20") // re-exposed
}
// :app/build.gradle.kts
dependencies {
implementation(project(":core_domain")) // gets Kixo for free
}Varning
Om du ser Unresolved reference: Kixo vid kompilering i en modul saknar den modulen ett eget beroende på SDK:t — lägg till raden med implementation ovan eller använd mönster B.
Initiera
Konfigurera Kixo i din underklass av Application — onCreate körs före alla aktiviteter, så varje skärmvisning, tryckning och livscykelhändelse fångas från första bildrutan. Registrera Application i manifestet med android:name=".MyApp".
import android.app.Application
import io.kixo.sdk.Kixo
class MyApp : Application() {
override fun onCreate() {
super.onCreate()
Kixo.configure(
context = this,
projectId = "kx_proj_YOUR_PROJECT_ID",
apiKey = "kx_key_YOUR_API_KEY",
)
}
}För finjusteringar som flaggor för autospårning, flushintervall, replay-sampling och anpassad API-värd skapar du en KixoConfiguration explicit:
import io.kixo.sdk.Kixo
import io.kixo.sdk.KixoConfiguration
val config = KixoConfiguration.Builder(
projectId = "kx_proj_YOUR_PROJECT_ID",
apiKey = "kx_key_YOUR_API_KEY",
)
.autoTrackScreens(true)
.autoTrackTaps(true)
.autoTrackNetwork(false) // reserved; no-op in the current Android release
.autoTrackCrashes(true)
.autoTrackSessions(true)
.autoTrackPush(true)
.flushIntervalMillis(30_000)
.flushAt(20)
.maxBufferSize(200)
.build(applicationContext)
Kixo.configure(this, config)Obs!
Idempotent. Ett andra anrop till configure från samma process blir en WARN-loggad no-op — SDK:t behåller den första konfigurationen. Händelser som köas av din auth-singleton innan innan configure är på plats buffras upp till 50 stycken och spelas upp när SDK:t är inkopplat, så du kan anropa Kixo.identify(...) från en global innan Application.onCreate är klart.
Spåra händelser
Tre byggstenar står för merparten av instrumenteringen: track för händelser, markGoal för konverteringssignaler och addBreadcrumb för kontext som inte är en händelse.
import io.kixo.sdk.Kixo
Kixo.track("video_played", mapOf(
"video_id" to "vid_42",
"duration_ms" to 18_500,
"autoplay" to false,
))
// markGoal(name, value?, currency?, properties?) — pass extra context
// through the named 'properties' argument (a Map can't be the 2nd
// positional arg; that slot is the Double 'value').
Kixo.markGoal("activated", properties = mapOf(
"step" to "onboarding_completed",
))
// Revenue goals use the typed value + currency parameters:
Kixo.markGoal("purchase_completed", value = 49.99, currency = "USD")
Kixo.addBreadcrumb(
message = "user toggled dark mode",
category = "ui",
level = "info",
)Tips
Mål graderas. Markerade mål används i Kixo:s aktiveringstrattar och i det dagliga cron-jobbet för förändringsdetektering — om volymen för ett mål faller med 70 % vecka över vecka visas det i dashboarden med märkningen Behöver granskas. Använd markGoal för de få tillfällen som verkligen spelar roll, och track för allt annat.
Standardhändelser
Ett lager ovanpå Kixo.track för de händelser som Kixo känner igen på namn — exakta strängnycklar som backendens detektor för standardhändelser matchar. Ger validering av egenskapsformat vid kompilering och en enda källa för namngivningen.
import io.kixo.sdk.Kixo
import io.kixo.sdk.SubscriptionInterval
Kixo.trackPurchase(
amount = 49.99,
currency = "USD",
productId = "pro_yearly",
)
Kixo.trackSubscriptionStart(
plan = "pro",
amount = 9.99,
currency = "USD",
interval = SubscriptionInterval.MONTH,
)
Kixo.trackSignup(method = "google")
Kixo.trackTrialStart(plan = "pro", days = 14)
Kixo.trackCancel(plan = "pro", reason = "too_expensive")
Kixo.trackUpgrade(fromPlan = "free", toPlan = "pro")
Kixo.trackActivation(event = "first_post_published")
Kixo.trackShare(channel = "twitter", contentId = "post_123")
Kixo.trackInvite(channel = "email", recipientCount = 5)Identifiera användare
Knyt efterföljande händelser till ett stabilt användar-id och en uppsättning traits. Ihopkopplingen från anonym till känd användare sker i Kixo — händelser som fångas upp före identify tillskrivs i efterhand samma användare.
import io.kixo.sdk.Kixo
// Reserved standard property keys carry a $-prefix (Mixpanel
// convention) so they namespace away from your own custom traits
// and promote to the dashboard's profile columns. See
// io.kixo.sdk.StandardProperty for the typed catalogue, or the
// "Standard property catalog" section below for the full 37-key list.
Kixo.identify("user_123", mapOf(
"$email" to "jane@example.com", // identity
"$name" to "Jane Doe", // identity
"$plan" to "pro", // subscription pack
"$lifetime_orders" to 12, // e-commerce pack
"signup_source" to "twitter_ad", // custom trait
))
// Logout: clear identity, super-properties, and the persisted queue.
Kixo.reset()⚠️ Vanlig fallgrop med dollartecken i Kotlin. Standardnycklar för identitet har prefixet $ ($email, $name, $first_name) — och i en Kotlin-strängliteral måste du escap:a dollartecknet som "\$email". Skriver du "$email" interpoleras variabeln email, så värdet hamnar tyst som en anpassad-trait och fyller aldrig kolumnerna för e-post eller namn i Audience. Enklaste lösningen är att använda den typade överlagringen (SDK 0.1.13+), som inte går att få fel: Kixo.setUserProperty(StandardProperty.EMAIL, email).
Märk upp en användare för segmentering
Använd setUserProperty med ett boolesk-värde för att ge användaren en enkel ja/nej-tagg. Taggen ligger kvar mellan appstarter och används i segment, e-postkampanjer och frågor i chatten — utan någon extra konfiguration utöver anropet till SDK.
// Tag a user as subscribed — segments + campaigns can target this
Kixo.setUserProperty("subscribe", true)
// VIP membership
Kixo.setUserProperty("vip", true)
// String + numeric values work too
Kixo.setUserProperty("plan_tier", "enterprise")
Kixo.setUserProperty("lifetime_orders", 42)
// Bulk-set
Kixo.setUserProperties(mapOf(
"subscribe" to true,
"plan_tier" to "enterprise",
))Egenskaperna sparas via SharedPreferences mellan appstarter och läggs automatiskt till på varje utgående händelse. Skriv till exempel "skicka ett välkomstmejl till användare där subscribe är true" i chatten — Kixo bygger segmentet och tar fram ett utkast till mall åt dig. Rensas vid Kixo.reset().
Standardkatalog för egenskaper
Reserverade egenskapsnycklar har prefixet $, så att de hålls åtskilda från dina egna traits. Kixo har en katalog med 37 nycklar i 3 universella paket (identitet, geografi, livscykel) och 5 B2B-paket för olika produktområden (prenumeration, e-handel, media, marknadsplats, lojalitet). Ange de som passar din produkt — dashboarden anpassar sig och visar bara de paket du faktiskt fyller med data.
Identitet
Alltid relevant. Anger kolumnerna i profilhuvudet.
| Nyckel | Typ | Beskrivning |
|---|---|---|
$email | sträng | Primär e-postadress, ofta nyckeln som används för att slå ihop identiteter. |
$phone | sträng | Telefonnummer i E.164-format. |
$name | sträng | Fullständigt visningsnamn. |
$first_name | sträng | Förnamn. |
$last_name | sträng | Efternamn. |
$avatar_url | sträng | Fullständig URL till användarens avatarbild. |
Geografi
Geografisk kontext.
| Nyckel | Typ | Beskrivning |
|---|---|---|
$country | sträng | Landskod enligt ISO 3166. |
$city | sträng | Stadsnamn. |
$region | sträng | Delstat eller provins. |
$timezone | sträng | IANA-zon som America/Los_Angeles. |
$language | sträng | IETF-tagg som en eller ru-RU. |
$locale | sträng | Fullständig språkversionsidentifierare. |
Livscykel
När vi senast såg dem.
| Nyckel | Typ | Beskrivning |
|---|---|---|
$created | ISO8601 | Tidpunkt för registrering eller kontoskapande. |
$last_seen | ISO8601 | Tidpunkt för senaste aktivitet. |
Prenumeration
Ange om produkten har abonnemang.
| Nyckel | Typ | Beskrivning |
|---|---|---|
$plan | sträng | Slug för nivå — free, pro, enterprise. |
$subscription_status | sträng | active / trial / cancelled / past_due. |
$trial_ends | ISO8601 | När den nuvarande provperioden löper ut. |
$mrr | tal | Månatlig återkommande intäkt i kontots valuta. |
$subscription_started | ISO8601 | När den nuvarande prenumerationen började. |
E-handel
Ange om ni säljer produkter.
| Nyckel | Typ | Beskrivning |
|---|---|---|
$lifetime_orders | tal | Antal slutförda beställningar. |
$lifetime_revenue | tal | Total kostnad. |
$aov | tal | Genomsnittligt ordervärde. |
$last_purchase | ISO8601 | Senaste genomförda köp. |
$first_purchase | ISO8601 | Första genomförda köp. |
$cart_abandoned_count | tal | Totalt antal övergivna varukorgar. |
Media
Ange om ni publicerar innehåll.
| Nyckel | Typ | Beskrivning |
|---|---|---|
$content_tier | sträng | free / premium / paid. |
$subscribed_categories | CSV-sträng eller array | Kategorier som användaren följer. |
$watch_time_total | tal | Total visningstid i sekunder. |
$last_played | ISO8601 | Senaste uppspelningsstart. |
Marknadsplats
Ange om ni är en plattform med två sidor.
| Nyckel | Typ | Beskrivning |
|---|---|---|
$seller_tier | sträng | Slug för säljarens nivå. |
$buyer_tier | sträng | Slug för köparsidan. |
$listings_count | tal | Aktiva annonser som användaren äger. |
$reviews_count | tal | Omdömen som användaren har fått. |
$verified | boolesk | KYC-status. |
Lojalitet
Används för engagemangs- och belöningsprogram.
| Nyckel | Typ | Beskrivning |
|---|---|---|
$loyalty_points | tal | Aktuellt saldo för inlösbara poäng. |
$vip_level | sträng | Slug för VIP-nivå. |
$referral_count | tal | Lyckade rekommendationer som tillskrivits den här användaren. |
Tips
Saknas ditt mönster? Använd vanliga nycklar för anpassade egenskaper. De visas i dashboardens panel för Custom Traits utan att ta plats i profilkolumnerna. De fem vertikalpaketen ovan är genomtänkta gissningar om de vanligaste B2B-uppläggen — kundspecifik terminologi, till exempel shipping_plan, lämnas utan prefix.
Superegenskaper
Nyckel/värde-par per session som automatiskt läggs till på varje utgående händelse. Till skillnad från identify traits, som beskriver identitet, beskriver super-properties sessionens kontext — aktiv A/B-variant, build flavor och aktiverade feature flags. De sparas mellan appstarter och rensas vid reset(). Vid krock vinner alltid properties per händelse på track.
import io.kixo.sdk.Kixo
Kixo.setSuperProperty("build_flavor", "beta")
Kixo.setSuperProperties(mapOf(
"ab_variant" to "B",
"referrer_campaign" to "autumn-launch",
))
// Sugar for A/B tracking — stored as 'experiment_<id>'.
Kixo.setExperimentVariant("checkout_v2", "variant_a")
Kixo.unsetSuperProperty("build_flavor")
Kixo.clearSuperProperties()Pushnotiser
Två integrationsvägar. Välj A om du använder FCM och vill ha kortast möjliga väg till en fungerande lösning. Välj B om du redan har en anpassad FirebaseMessagingService som du inte kan bygga om, eller om du vill styra exakt vilka FCM-leveranser Kixo ska se.
Alternativ A — utöka KixoFirebaseMessagingService (automatisk spårning)
Utöka KixoFirebaseMessagingService och anropa super.onMessageReceived(...) från din override — då skickar Kixo automatiskt push_received (synlig payload) eller push_silent (endast data). Basklassen hanterar också registrering av onNewToken om du inte skriver över den. Registrering av AndroidManifest.xml fungerar i övrigt som i en vanlig FCM-tjänst.
import com.google.firebase.messaging.RemoteMessage
import io.kixo.sdk.KixoFirebaseMessagingService
class MyMessagingService : KixoFirebaseMessagingService() {
override fun onMessageReceived(remoteMessage: RemoteMessage) {
super.onMessageReceived(remoteMessage) // Kixo auto-tracks push_received
// … your own routing / notification display
}
}Obs!
Kixo kompilerar den här valfria klassen mot Firebase Messaging, men lägger inte till Firebase transitivt i din app. SDK:t deklarerar Firebase som compileOnly; en app som väljer det här alternativet måste därför redan bero på firebase-messaging, precis som för alla FCM-mottagare.
Alternativ B — anropa det manuella API:t från din egen FCM-tjänst
Registrera din FCM-token hos Kixo via FirebaseMessagingService.onNewToken och logga sedan varje leverans explicit. Välj den här vägen om du bara vill att Kixo ska se en delmängd av FCM-leveranserna. Leveransspårning på Android stöder för närvarande bara FCM.
import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage
import io.kixo.sdk.Kixo
import io.kixo.sdk.PushProvider
class MyMessagingService : FirebaseMessagingService() {
override fun onNewToken(token: String) {
Kixo.setPushToken(token, PushProvider.FCM)
}
override fun onMessageReceived(message: RemoteMessage) {
// Convert the FCM payload to a Map<String, Any?> and log it —
// Kixo correlates this with the open / dismiss it sees later.
Kixo.logPushReceived(message.data.toMap(), appState = "background")
}
}Android exponerar ingen generell livscykelkrok för öppningar, avvisningar eller åtgärdsknappar i notiser. Vidarebefordra i stället de signalerna från de notis-intent eller receivers som appen skapar:
import io.kixo.sdk.Kixo
Kixo.logPushOpened(payload = pushPayload) // open
Kixo.logPushOpened(payload = pushPayload, actionId = "reply") // action-button tap
Kixo.logPushDismissed(payload = pushPayload) // swipe-awaySessionsåterspelning
Återspela en verklig, visuell rekonstruktion av det användaren såg. Vid varje inspelning kodar SDK:t en komprimerad bildruta av skärmen (en JPEG-bild) tillsammans med en strukturell ögonblicksbild av vyhierarkin och laddar upp båda, så att spelaren i dashboarden kan återge uppspelningen med pixelprecision sida vid sida med tidslinjen för interaktioner. Konfigurera replay för projektet i Översikt → Inställningar → Sessionsrepris. SDK:t läser automatiskt in och uppdaterar projektets policy, inklusive maskering, inspelningslägen och tillåtelse för uppladdning via mobilnät.
import io.kixo.sdk.Kixo
import io.kixo.sdk.KixoConfiguration
val config = KixoConfiguration.Builder(
projectId = "kx_proj_YOUR_PROJECT_ID",
apiKey = "kx_key_YOUR_API_KEY",
)
.build(applicationContext)
Kixo.configure(this, config)När uppladdning via mobilnät är avstängd väntar köad replay tills ett tillåtet nätverk är tillgängligt.
Tips
Maskera före uppladdning. Kixo fångar pixlar, så maskeringen sker innan något lämnar enheten. Lösenords- och e-postfält upptäcks och maskeras automatiskt, text i strukturella ögonblicksbilder passerar genom ett PII-filter, och varje vy som du markerar med setKixoMask(true) rasteriseras till en ogenomskinlig rektangel i bildrutan innan JPEG-kodningen sker — dess pixlar lämnar aldrig enheten. Skärmar i Jetpack Compose maskeras i sin helhet som standard (anropa setKixoMask(false) på den yttersta ComposeView om du vill inkludera en skärm som du har granskat). Operatörer granskar återspelningen i spelaren tillsammans med händelsetidslinjen i dashboarden.
Datainsamling
SDK:t samlar in den data som är aktiverad i projektet samt de händelser och egenskaper som appen skickar.
Felsökning
Kixo.diagnostics() returnerar en skrivskyddad ögonblicksbild av SDK:ts hälsa — praktiskt i en dold felsökningsskärm eller ett smoke test. Svarar på frågan "varför kommer inga händelser fram?" utan debugger.
import io.kixo.sdk.Kixo
val diag = Kixo.diagnostics()
Log.d("Kixo", "queued=${diag.queue.bufferedEventCount}")
Log.d("Kixo", "paused=${diag.paused}") // collection paused state
Log.d("Kixo", "lifecycleState=${diag.lifecycleState}") // SDK lifecycle stateTvinga fram en flush från testhärvan — blockerar i upp till timeoutMs för en nätverksrunda:
import io.kixo.sdk.Kixo
// Async fire-and-forget — returns immediately.
Kixo.flush()
// Blocking variant for instrumentation tests. Never call on the main thread.
val landed: Boolean = Kixo.flushBlocking(timeoutMs = 5_000L)
assertTrue(landed)Compose Navigation
Rutter för Activity och Fragment ger direkt screen_view-händelser och strukturerade screen_visit-poster med metadata för vistelsetid och flöde. För Jetpack Compose Navigation skickar du Kixo.screen från en LaunchedEffect nycklad på rutten — då ser SDK:t en händelse per destination, oavsett hur många omkompositioner som sker.
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import io.kixo.sdk.Kixo
@Composable
fun AppNavHost(nav: NavHostController) {
NavHost(navController = nav, startDestination = "home") {
composable("home") {
LaunchedEffect("home") { Kixo.screen("HomeScreen") }
HomeScreen()
}
composable("settings") {
LaunchedEffect("settings") { Kixo.screen("SettingsScreen") }
SettingsScreen()
}
}
}AI-kodassistenter
SDK:ts publika yta är liten och utformad för kodkomplettering — alla metoder finns på singletonen Kixo, alla Kotlin-exempel i den här guiden börjar med import io.kixo.sdk.Kixo, och vår README innehåller ett block med "AI agent quick reference" som verktyg som Claude Code, Cursor och Codex kan klistra in direkt i sitt sammanhang. Om din agent kör fast är det här den kanoniska starten:
// Tell your AI coding agent:
// "Integrate the Kixo Android SDK using io.kixo:kixo-android-sdk
// from https://raw.githubusercontent.com/kixoio/kixo-android-sdk/main/repo.
// Call Kixo.configure(this, projectId, apiKey) in Application.onCreate.
// Then use Kixo.track / Kixo.identify / Kixo.markGoal as needed."Obs!
Alla avsnitt ovan är skrivna för det arbetsflödet — importer är alltid explicita, typer är alltid utskrivna och SDK-singletonen aliasas aldrig. Ge sidan till din agent och låt den driva arbetet.