Android SDK
Kixo Android SDK støtter Kotlin 2.0+ og Java, krever minSdk 24 (Android 7.0) og er bygget mot compileSdk 35. Vertsappen er fortsatt ansvarlig for sin egen targetSdk. Ett kall til Kixo.configure i Application.onCreate sporer automatisk skjermer, trykk, økter, krasj og livssyklushendelser. Push-sporing krever FCM-broen beskrevet nedenfor. Automatisk sporing av nettverksforespørsler er ikke med i den nåværende Android-versjonen. SDK-en støtter også session replay, identitet og mål.
Kom i gang
Tre filer. Legg til Maven-repositoriet, legg til avhengigheten, og legg deretter inn to linjer i underklassen din av Application.
Byggekrav: compileSdk 35, minSdk 24, Kotlin 2.0+ eller Java, og Java 17-bytekode.
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
maven {
url = uri("https://raw.githubusercontent.com/kixoio/kixo-android-sdk/main/repo")
}
}
}Merknad
Da er analyseintegrasjonen på plass. Standard autosporing er slått på som standard; push krever fortsatt FCM-broen nedenfor. Overstyr enkeltflagg med KixoConfiguration.Builder(...) bare ved behov.
Legg til i appen din
Kixo sitt Maven-repositorium ligger på GitHub Pages. Legg det til sammen med google() og 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")
}
}
}Legg deretter til avhengigheten i appmodulen:
// app/build.gradle.kts
dependencies {
implementation("io.kixo:kixo-android-sdk:0.1.20")
}Tips
android.permission.INTERNET og android.permission.ACCESS_NETWORK_STATE følger med i SDK-manifestet. Varslingstillatelser håndteres fortsatt av appen din og deklareres når du tar i bruk push-funksjonene.
Flermodulprosjekter
Gradle-konfigurasjonen implementation er ikke transitiv: Hvis du deklarerer implementation("io.kixo:kixo-android-sdk:0.1.20") i en bibliotekmodul (for eksempel :core_domain), blir Kixo IKKE synlig for :app eller andre som bruker modulen. To mønstre fungerer — velg ett.
Mønster A — hver modul som kaller Kixo, deklarerer avhengigheten selv (anbefalt). holder classpathen i hver modul liten og unngår kjedereaksjoner av nye bygg. Bruk en versjonskatalog (libs.kixo.sdk), så oppdaterer du versjonen ett sted.
// :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 — reeksporter via api(...). Én deklarasjon er nok, men bibliotekmodulens offentlige ABI vil da inkludere Kixo-typer — hver versjonsendring utløser nye bygg i alle nedstrømsmoduler. Bruk dette bare når biblioteket gjenbruker Kixo-typer i egne offentlige signaturer, for eksempel ved å returnere KixoDiagnostics fra en funksjon.
// :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
}Advarsel
Hvis du ser Unresolved reference: Kixo ved kompilering i en modul, mangler modulen sin egen avhengighet til SDK — legg til implementation-linjen over, eller bruk mønster B.
Initialiser
Konfigurer Kixo i underklassen din av Application — onCreate kjører før alle activities, så hver skjermvisning, hvert trykk og alle livssyklushendelser fanges fra første frame. Registrer 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",
)
}
}Hvis du vil finstyre innstillinger som autosporingsflagg, flush-frekvens, replay-sampling og egendefinert API-vert, oppretter du en KixoConfiguration eksplisitt:
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)Merknad
Idempotent. Et nytt kall til configure fra samme prosess logges som WARN og ignoreres — SDK beholder den første konfigurasjonen. Hendelser som auth-singletonen din køer før før configure er på plass, bufres (inntil 50) og sendes på nytt når SDK er koblet opp. Du kan derfor kalle Kixo.identify(...) fra en global før Application.onCreate er ferdig.
Spor hendelser
Tre grunnprimitiver dekker det meste av instrumenteringen: track for hendelser, markGoal for konverteringssignaler og addBreadcrumb for kontekst som ikke er en hendelse.
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 graderes. Mål du markerer, brukes i Kixo sine aktiveringstrakter og i den daglige cron-jobben for endringsdeteksjon — hvis volumet på et mål faller 70 % fra uke til uke, vises det i dashbordet med en Må gjennomgås-etikett. Bruk markGoal for de få øyeblikkene som virkelig betyr noe, og track for alt annet.
Standardhendelser
Et tynt lag over Kixo.track for hendelser Kixo kjenner igjen på navn — eksakte strengnøkler som standardhendelsesdetektoren i backend matcher. Du får validering av egenskapsstrukturen ved kompilering og ett felles navnesett å forholde deg til.
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)Identifiser brukere
Knytt alle senere hendelser til en stabil bruker-ID og et sett med traits. Sammenkoblingen fra anonym til kjent bruker skjer i Kixo — hendelser som ble registrert før identify, tilordnes i etterkant til samme bruker.
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()⚠️ Kotlin-felle med dollartegn. Standardnøkler for identitet har prefikset $ ($email, $name, $first_name) — og i en Kotlin-literal må du escape dollartegnet som "\$email". Skriver du "$email", interpoleres variabelen email inn i strengen, så verdien havner stille som en egendefinert-trait og fyller aldri ut kolonnene for e-post og navn i Audience. Den enkleste løsningen er å bruke den typede overloaden (SDK 0.1.13+), som ikke kan brukes feil: Kixo.setUserProperty(StandardProperty.EMAIL, email).
Merk en bruker for segmentering
Bruk setUserProperty med en verdi av typen boolsk verdi for å gi brukeren en enkel ja/nei-tag. Taggen bevares på tvers av appstarter og brukes i segmenter, e-postkampanjer og chatspørringer — uten annet oppsett enn selve kallet til 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",
))Egenskapene lagres via SharedPreferences på tvers av appstarter og legges automatisk ved alle utgående hendelser. I chat kan du for eksempel skrive "send en velkomst-e-post til brukere der subscribe er true" — da bygger Kixo segmentet og lager et førsteutkast til mal for deg. Slettes ved Kixo.reset().
Standardkatalog for egenskaper
Reserverte egenskapsnøkler har prefikset $, så de holdes adskilt fra dine egendefinerte traits. Kixo-katalogen dekker 37 nøkler fordelt på 3 universelle pakker (identitet, geo, livssyklus) og 5 B2B-vertikalpakker (abonnement, e-handel, medier, markedsplass, lojalitet). Sett bare de som gjelder for produktet ditt — dashbordet tilpasser seg og viser bare pakkene du fyller ut.
Identitet
Alltid relevant. Angir kolonnene i profiloverskriften.
| Nøkkel | Type | Beskrivelse |
|---|---|---|
$email | streng | Primær e-postadresse, ofte brukt som flettenøkkel ved identitetssammenslåing. |
$phone | streng | Telefonnummer i E.164-format. |
$name | streng | Fullt visningsnavn. |
$first_name | streng | Fornavn. |
$last_name | streng | Etternavn. |
$avatar_url | streng | Full URL til brukerens avatarbilde. |
Geo
Geografisk kontekst.
| Nøkkel | Type | Beskrivelse |
|---|---|---|
$country | streng | Landskode etter ISO 3166. |
$city | streng | Bynavn. |
$region | streng | Delstat eller provins. |
$timezone | streng | IANA-sone som America/Los_Angeles. |
$language | streng | IETF-tag som en eller ru-RU. |
$locale | streng | Full språk- og regionidentifikator. |
Livssyklus
Når så vi dem.
| Nøkkel | Type | Beskrivelse |
|---|---|---|
$created | ISO8601 | Tidspunkt for registrering eller kontoopprettelse. |
$last_seen | ISO8601 | Tidspunkt for siste aktivitet. |
Abonnement
Brukes hvis produktet ditt har abonnementer.
| Nøkkel | Type | Beskrivelse |
|---|---|---|
$plan | streng | Slug for nivå — free, pro, enterprise. |
$subscription_status | streng | active / trial / cancelled / past_due. |
$trial_ends | ISO8601 | Når den nåværende prøveperioden utløper. |
$mrr | tall | Månedlig gjentakende inntekt i kontoens valuta. |
$subscription_started | ISO8601 | Når det nåværende abonnementet startet. |
E-handel
Brukes hvis du selger produkter.
| Nøkkel | Type | Beskrivelse |
|---|---|---|
$lifetime_orders | tall | Antall fullførte bestillinger. |
$lifetime_revenue | tall | Totalt forbruk. |
$aov | tall | Gjennomsnittlig ordreverdi. |
$last_purchase | ISO8601 | Siste vellykkede kjøp. |
$first_purchase | ISO8601 | Første vellykkede kjøp. |
$cart_abandoned_count | tall | Totalt antall forlatte handlekurver. |
Medier
Brukes hvis du publiserer innhold.
| Nøkkel | Type | Beskrivelse |
|---|---|---|
$content_tier | streng | free / premium / paid. |
$subscribed_categories | CSV-streng eller array | Kategorier brukeren følger. |
$watch_time_total | tall | Samlet seertid i sekunder. |
$last_played | ISO8601 | Siste avspillingsstart. |
Markedsplass
Brukes hvis du driver en tosidig plattform.
| Nøkkel | Type | Beskrivelse |
|---|---|---|
$seller_tier | streng | Slug for nivå på selgersiden. |
$buyer_tier | streng | Slug for kjøpers nivå. |
$listings_count | tall | Aktive oppføringer brukeren eier. |
$reviews_count | tall | Anmeldelser brukeren har mottatt. |
$verified | boolsk verdi | KYC-status. |
Lojalitet
Brukes for engasjements- og belønningsprogrammer.
| Nøkkel | Type | Beskrivelse |
|---|---|---|
$loyalty_points | tall | Gjeldende saldo for innløselige poeng. |
$vip_level | streng | Slug for VIP-nivå. |
$referral_count | tall | Vellykkede vervinger tilskrevet denne brukeren. |
Tips
Finner du ikke mønsteret ditt? Bruk enkle nøkler for egendefinerte traits. De vises i panelet Custom Traits i Dashboard uten å fylle opp profilkolonnene. De fem vertikalpakkene over er kvalifiserte forslag til de vanligste B2B-mønstrene — kundespesifikk terminologi, som shipping_plan, beholdes uten prefiks.
Superegenskaper
Nøkkel-/verdi-par per økt som automatisk legges ved alle utgående hendelser. Dette skiller seg fra identify traits, som beskriver identitet; super-properties beskriver øktkontekst — aktiv A/B-variant, build flavor og aktiverte feature flags. De bevares på tvers av appstarter og slettes ved reset(). Ved kollisjon er det alltid properties per hendelse på track som vinner.
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()Push-varsler
To integrasjonsveier. Velg A hvis du bruker FCM og vil ha kortest mulig vei til et fungerende oppsett. Velg B hvis du allerede har en egendefinert FirebaseMessagingService som du ikke kan bygge om, eller hvis du vil ha eksplisitt kontroll over hvilke FCM-leveringer Kixo skal se.
Alternativ A — utvid KixoFirebaseMessagingService (autosporing)
Arv fra KixoFirebaseMessagingService, og kall super.onMessageReceived(...) fra overstyringen — da sender Kixo automatisk push_received (synlig payload) eller push_silent (bare data). Basisklassen håndterer også registrering av onNewToken hvis du ikke overstyrer den. Registrering av AndroidManifest.xml er ellers uendret fra en vanlig FCM-tjeneste.
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
}
}Merknad
Kixo kompilerer denne valgfrie klassen mot Firebase Messaging, men legger ikke Firebase til transitivt i appen din. SDK deklarerer Firebase som compileOnly; en app som velger dette alternativet, må derfor allerede ha en avhengighet til firebase-messaging, slik alle FCM-receivere må ha.
Alternativ B — kall API-et manuelt fra din egen FCM-tjeneste
Registrer FCM-tokenet hos Kixo via FirebaseMessagingService.onNewToken, og loggfør deretter hver levering eksplisitt. Bruk denne veien når du vil at Kixo bare skal se et utvalg av FCM-leveringer. Leveringssporing på Android støtter foreløpig bare 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 tilbyr ingen universell livssykluskrok for åpning, avvisning eller handlingsknapper i varsler. Videresend disse signalene fra varsel-intentene eller receiverne appen din oppretter:
import io.kixo.sdk.Kixo
Kixo.logPushOpened(payload = pushPayload) // open
Kixo.logPushOpened(payload = pushPayload, actionId = "reply") // action-button tap
Kixo.logPushDismissed(payload = pushPayload) // swipe-awayØktopptak
Spill av en visuell rekonstruksjon av det brukeren faktisk så. Ved hvert opptak koder SDK-en et komprimert skjermbilde (et JPEG-bilde) sammen med et strukturelt øyeblikksbilde av view-hierarkiet, og laster opp begge deler. Da kan avspilleren i dashbordet vise en pikselnøyaktig avspilling side om side med interaksjonstidslinjen. Konfigurer replay for prosjektet i Oversikt → Innstillinger → Øktopptak. SDK-en henter og oppdaterer automatisk denne prosjektpolicyen, inkludert maskering, opptaksmoduser og om opplasting over mobilnett er tillatt.
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 opplasting over mobilnett er slått av, blir replay-data liggende i kø til et tillatt nettverk er tilgjengelig.
Tips
Masker før opplasting. Kixo samler inn piksler, så maskeringen skjer før noe forlater enheten. Passord- og e-postfelt oppdages automatisk og sladdes, tekst i strukturelle øyeblikksbilder går gjennom et PII-filter, og alle views du merker med setKixoMask(true), rasteriseres til et ugjennomsiktig rektangel i rammen før JPEG kodes — pikslene forlater aldri enheten. Skjermer i Jetpack Compose maskeres i sin helhet som standard (kall setKixoMask(false) på den ytterste ComposeView for å ta med en skjerm du har gjennomgått). Operatører kan granske replay-avspilleren side om side med hendelsestidslinjen i dashbordet.
Datainnsamling
SDK-en samler inn dataene som er aktivert i prosjektet ditt, samt hendelsene og egenskapene appen sender inn.
Feilsøking
Kixo.diagnostics() returnerer et skrivebeskyttet øyeblikksbilde av tilstanden i SDK-en — nyttig i en skjult debug-skjerm eller en smoke-test. Svarer på «hvorfor kommer ikke hendelsene mine frem?» uten at du trenger en 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 stateTving frem en flush fra testoppsettet ditt — blokkerer i opptil timeoutMs mens nettverksrundturen pågår:
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
Activity- og Fragment-ruter gir umiddelbare screen_view-hendelser og strukturerte screen_visit-oppføringer med metadata om oppholdstid og flyt, uten ekstra oppsett. Med Jetpack Compose Navigation utløser du Kixo.screen fra en LaunchedEffect nøstet til ruten. Da ser SDK nøyaktig én hendelse per destinasjon, uansett hvor mange recompositions som skjer.
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-kodeagenter
SDK-ens offentlige flate er liten og laget for kodefullføring: Alle metoder ligger på singletonen Kixo, hvert Kotlin-eksempel i denne guiden starter med import io.kixo.sdk.Kixo, og README leveres med en «AI agent quick reference»-blokk som verktøy som Claude Code, Cursor og Codex kan lime rett inn i konteksten. Hvis agenten står fast, er dette det kanoniske utgangspunktet:
// 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."Merknad
Alle seksjonene over er skrevet for denne arbeidsflyten — importer er alltid eksplisitte, typer er alltid navngitt, og SDK-singletonen får aldri alias. Gi denne siden til agenten din og la den gjøre jobben.