Idi na dokumentaciju

Android SDK

Kixo Android SDK podržava Kotlin 2.0+ i Javu, zahtijeva minSdk 24 (Android 7.0) i buildan je prema compileSdk 35. Vaša host aplikacija i dalje sama upravlja vlastitim targetSdk. Jedan poziv Kixo.configure u vašem Application.onCreate automatski prati ekrane, dodire, sesije, rušenja aplikacije i događaje životnog ciklusa. Za praćenje push obavijesti potreban je FCM most opisan ispod. Automatsko praćenje mrežnih zahtjeva trenutno nije dio Android izdanja. SDK podržava i session replay, identitet i ciljeve.

Brzi početak

Tri datoteke. Dodajte Maven repo, dodajte zavisnost, pa onda ubacite dvije linije u svoju podklasu Application.

Zahtjevi za build: compileSdk 35, minSdk 24, Kotlin 2.0+ ili Java, te Java 17 bytecode.

dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        mavenCentral()
        maven {
            url = uri("https://raw.githubusercontent.com/kixoio/kixo-android-sdk/main/repo")
        }
    }
}

Napomena

To je cijela integracija analitike. Standardni automatski trackeri uključeni su po zadanim postavkama; za push je i dalje potreban FCM most ispod. Pojedinačne oznake mijenjajte s KixoConfiguration.Builder(...) samo kada je potrebno.

Dodajte u aplikaciju

Kixo Maven repo hostuje se na GitHub Pages. Dodajte ga uz google() i mavenCentral() u settings.gradle.kts:

kotlin
// 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")
        }
    }
}

Zatim deklarirajte zavisnost u app modulu:

kotlin
// app/build.gradle.kts
dependencies {
    implementation("io.kixo:kixo-android-sdk:0.1.20")
}

Savjet

android.permission.INTERNET i android.permission.ACCESS_NETWORK_STATE uključeni su u SDK manifest. Dozvolama za obavijesti i dalje upravlja vaša aplikacija i deklarirate ih kada uključite push funkcije.

Projekti s više modula

Gradle konfiguracija implementation je nije tranzitivno: deklarisanje implementation("io.kixo:kixo-android-sdk:0.1.20") u bibliotečkom modulu (npr. :core_domain) NE čini Kixo vidljivim za :app niti za bilo kojeg drugog potrošača. Postoje dva ispravna obrasca — izaberite jedan.

Obrazac A — svaki modul koji poziva Kixo i deklarira ga (preporučeno). Drži classpath svakog modula što manjim i izbjegava lančane ponovne izgradnje. Koristite version catalog (libs.kixo.sdk) da verziju mijenjate na jednom mjestu.

kotlin
// :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
}

Obrazac B — ponovni izvoz kroz api(...). Jedna deklaracija, ali javni ABI bibliotečkog modula sada uključuje Kixo tipove — svako povećanje verzije pokreće ponovnu izgradnju svih downstream modula. Koristite ovo samo kada biblioteka koristi Kixo tipove i u vlastitim javnim potpisima, npr. kada funkcija vraća KixoDiagnostics.

kotlin
// :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
}

Upozorenje

Ako pri kompilaciji u nekom modulu vidite Unresolved reference: Kixo, tom modulu nedostaje vlastita zavisnost od SDK-a — dodajte gornji implementation red ili koristite obrazac B.

Inicijalizacija

Konfigurirajte Kixo iz svoje podklase ApplicationonCreate se izvršava prije bilo koje aktivnosti, pa se svaki pregled ekrana, dodir i događaj životnog ciklusa bilježi od prvog frejma. Registrirajte Application u manifestu s android:name=".MyApp".

kotlin
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",
        )
    }
}

Za preciznija podešavanja (oznake za automatsko praćenje, ritam flushanja, uzorkovanje replaya, prilagođeni API host) eksplicitno napravite KixoConfiguration:

kotlin
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)

Napomena

Idempotentno. Drugi poziv configure iz istog procesa ne radi ništa i bilježi se kao WARN — SDK zadržava prvu konfiguraciju. Događaji koje vaš auth singleton stavi u red prije nego što prije configure stigne čuvaju se u međuspremniku (do 50) i šalju se kad se SDK poveže, pa Kixo.identify(...) možete pozvati iz globalnog opsega prije nego što Application.onCreate završi.

Pratite događaje

Tri osnove nose glavninu vaše instrumentacije: track za događaje, markGoal za signale konverzije i addBreadcrumb za kontekst koji nije događaj.

kotlin
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",
)

Savjet

Ciljevi imaju težinu. Označeni ciljevi ulaze u Kixo aktivacione funnele i dnevni cron za otkrivanje promjena — cilj čiji obim padne 70% u odnosu na prethodnu sedmicu pojavit će se u vašem dashboardu s oznakom Treba pregledati. Koristite markGoal za mali broj trenutaka koji su zaista bitni; track za sve ostalo.

Standardni događaji

Praktični sloj preko Kixo.track za događaje koje Kixo prepoznaje po nazivu — doslovne string ključeve koje backend detektor standardnih događaja prepoznaje. Dobijate provjeru oblika svojstava pri kompilaciji i jedno mjesto istine za imenovanje.

kotlin
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)

Identificirajte korisnike

Povežite naredne događaje sa stabilnim ID-em korisnika i skupom traitova. Spajanje anonimnog i poznatog korisnika radi se u Kixo — događaji zabilježeni prije identify naknadno se pripisuju istom korisniku.

kotlin
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 zamka sa znakom dolara. Standardni ključevi identiteta imaju prefiks $ ($email, $name, $first_name) — a u Kotlin literalu znak dolara mora escapeovati kao "\$email". Ako napišete "$email", interpolirat ćete varijablu email, pa će vrijednost neprimjetno završiti kao trait prilagođeno i nikad neće popuniti kolone email / name u Audience. Najjednostavnije rješenje je tipizirani overload (SDK 0.1.13+), koji je praktično nemoguće pogriješiti: Kixo.setUserProperty(StandardProperty.EMAIL, email).

Označite korisnika za segmentaciju

Koristite setUserProperty s vrijednošću boolean da korisniku dodate jednostavnu da/ne oznaku. Oznaka ostaje sačuvana kroz pokretanja aplikacije i koristi se za segmente, email kampanje i upite u chatu — bez dodatnog podešavanja osim SDK poziva.

kotlin
// 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",
))

Svojstva se čuvaju putem SharedPreferences kroz ponovna pokretanja i automatski se dodaju svakom odlaznom događaju. U chatu recite nešto poput "pošalji email dobrodošlice korisnicima gdje je subscribe true" — Kixo će za vas napraviti segment i pripremiti nacrt predloška. Brišu se na Kixo.reset().

Katalog standardnih svojstava

Rezervisani ključevi svojstava nose prefiks $, kako bi bili odvojeni od vaših prilagođenih svojstava. Kixo katalog pokriva 37 ključeva u 3 univerzalna paketa (identity, geo, lifecycle) i 5 B2B vertikalnih paketa (subscription, e-commerce, media, marketplace, loyalty). Postavite samo ono što se odnosi na vaš proizvod — dashboard se prilagođava i prikazuje samo pakete koje popunite.

Identitet

Uvijek relevantno. Postavlja kolone zaglavlja profila.

KljučTipOpis
$emailstringPrimarni email, često ključ za spajanje identiteta.
$phonestringE.164 broj telefona.
$namestringPuno prikazano ime.
$first_namestringIme.
$last_namestringPrezime.
$avatar_urlstringPuni URL slike avatara korisnika.

Geo

Geografski kontekst.

KljučTipOpis
$countrystringISO 3166 kod države.
$citystringNaziv grada.
$regionstringSavezna država ili pokrajina.
$timezonestringIANA zona kao America/Los_Angeles.
$languagestringIETF oznaka kao en ili ru-RU.
$localestringPuni locale identifikator.

Životni ciklus

Kada smo ih vidjeli.

KljučTipOpis
$createdISO8601Vrijeme registracije ili kreiranja računa.
$last_seenISO8601Vrijeme posljednje interakcije.

Pretplata

Postavite ako vaš proizvod ima pakete.

KljučTipOpis
$planstringSlug nivoa — free, pro, enterprise.
$subscription_statusstringactive / trial / cancelled / past_due.
$trial_endsISO8601Kada ističe trenutni probni period.
$mrrbrojMjesečni ponavljajući prihod u valuti računa.
$subscription_startedISO8601Kada je počela trenutna pretplata.

E-commerce

Postavite ako prodajete proizvode.

KljučTipOpis
$lifetime_ordersbrojBroj završenih narudžbi.
$lifetime_revenuebrojUkupna potrošnja.
$aovbrojProsječna vrijednost narudžbe.
$last_purchaseISO8601Posljednja uspješna kupovina.
$first_purchaseISO8601Prva uspješna kupovina.
$cart_abandoned_countbrojUkupan broj napuštenih korpi.

Mediji

Postavite ako objavljujete sadržaj.

KljučTipOpis
$content_tierstringfree / premium / paid.
$subscribed_categoriesCSV string ili nizKategorije koje korisnik prati.
$watch_time_totalbrojUkupno vrijeme gledanja u sekundama.
$last_playedISO8601Posljednji početak reprodukcije.

Tržište

Postavite ako ste dvosmjerna platforma.

KljučTipOpis
$seller_tierstringSlug nivoa na strani prodavača.
$buyer_tierstringSlug nivoa na strani kupca.
$listings_countbrojAktivni oglasi u vlasništvu korisnika.
$reviews_countbrojRecenzije koje je korisnik primio.
$verifiedbooleanKYC status.

Lojalnost

Postavite ako imate programe angažmana i nagrađivanja.

KljučTipOpis
$loyalty_pointsbrojTrenutni raspoloživi saldo bodova.
$vip_levelstringVIP slug nivoa.
$referral_countbrojUspješne preporuke pripisane ovom korisniku.

Savjet

Ne vidite svoj obrazac? Za prilagođene traitove koristite obične ključeve. Pojavit će se u panelu Custom Traits na dashboardu bez zagađivanja kolona profila. Pet vertikalnih paketa iznad predstavljaju promišljene pretpostavke za najčešće B2B obrasce — terminologija specifična za kupca, npr. shipping_plan, ostaje bez prefiksa.

Super-properties

Parovi ključ/vrijednost po sesiji koji se automatski dodaju svakom odlaznom događaju. Razlikuju se od traitova identify (koji opisuju identitet); super-properties opisuju kontekst sesije — aktivnu A/B varijantu, build flavor, uključene feature flagove. Ostaju sačuvani kroz ponovna pokretanja; brišu se na reset(). Ako dođe do kolizije, per-event properties na track uvijek imaju prednost.

kotlin
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 obavijesti

Postoje dva puta integracije. Izaberite A ako koristite FCM i želite najkraće ispravno podešavanje; izaberite B ako već imate prilagođeni FirebaseMessagingService koji ne možete restrukturirati ili želite eksplicitnu kontrolu nad tim koje FCM isporuke Kixo vidi.

Opcija A — proširite KixoFirebaseMessagingService (automatsko praćenje)

Napravite podklasu KixoFirebaseMessagingService i iz svog overridea pozovite super.onMessageReceived(...) — Kixo automatski emituje push_received (vidljiv payload) ili push_silent (samo podaci). Bazna klasa obrađuje i registraciju onNewToken ako je ne overrideate. Registracija AndroidManifest.xml ostaje ista kao kod običnog FCM servisa.

kotlin
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
    }
}

Napomena

Kixo ovu opcionalnu klasu kompilira prema Firebase Messagingu, ali Firebase ne dodaje tranzitivno u vašu aplikaciju. SDK deklarira Firebase kao compileOnly; aplikacija koja bira ovu opciju već mora zavisiti od firebase-messaging, kao i svaki FCM receiver.

Opcija B — pozovite ručni API iz vlastitog FCM servisa

Registrirajte svoj FCM token u Kixo putem FirebaseMessagingService.onNewToken, a zatim svaku isporuku bilježite eksplicitno. Ovaj pristup koristite kada želite da Kixo vidi samo dio FCM isporuka. Android isporuka trenutno podržava samo FCM.

kotlin
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 ne nudi univerzalni lifecycle hook za otvaranje obavijesti, njihovo odbacivanje ni action dugmad. Te signale proslijedite iz notification intenta ili receivera koje vaša aplikacija kreira:

kotlin
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

Reprodukcija sesije

Reproducirajte stvarnu vizualnu rekonstrukciju onoga što je korisnik vidio. Pri svakom snimanju SDK kodira komprimirani frejm ekrana (JPEG sliku) zajedno sa strukturnim snimkom hijerarhije viewova i šalje oboje — tako player u dashboardu može prikazati piksel-preciznu reprodukciju uz vremensku liniju interakcija. Replay za projekat konfigurirate u Kontrolna tabla → Postavke → Reprodukcija sesije. SDK automatski čita i osvježava tu projektnu politiku, uključujući maskiranje, režime snimanja i dozvolu za slanje preko mobilne mreže.

kotlin
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)

Kada je slanje preko mobilne mreže isključeno, replay na čekanju čeka dopuštenu mrežu.

Savjet

Maskirajte prije slanja. Kixo snima piksele, zato se maskiranje izvršava prije nego što bilo šta napusti uređaj. Polja za lozinku i email prepoznaju se automatski i zacrnjuju; tekst u strukturnim snimcima prolazi kroz PII filter; a svaki view koji označite sa setKixoMask(true) pretvara se u neprozirni pravougaonik u frejmu prije se JPEG kodira — njegovi pikseli nikad ne napuštaju uređaj. Ekrani u Jetpack Compose su po zadanim postavkama maskirani u cijelosti (pozovite setKixoMask(false) na vanjskom ComposeView da uključite ekran koji ste već pregledali). Operateri u dashboardu pregledaju replay player zajedno s vremenskom linijom događaja.

Prikupljanje podataka

SDK prikuplja podatke koji su uključeni u vašem projektu te događaje i svojstva koje šalje vaša aplikacija.

Otklanjanje grešaka

Kixo.diagnostics() vraća snapshot zdravstvenog stanja SDK-a samo za čitanje — korisno u skrivenom debug ekranu ili smoke testu. Odgovara na pitanje „zašto mi događaji ne prolaze?“ bez debuggera.

kotlin
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 state

Prisilno pokrenite flush iz testnog okruženja — blokira do timeoutMs dok traje mrežni round-trip:

kotlin
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

Rute Activity / Fragment odmah proizvode screen_view događaje i strukturirane zapise screen_visit s metapodacima o zadržavanju i toku, bez dodatnog podešavanja. Za Jetpack Compose Navigation pozovite Kixo.screen iz LaunchedEffect vezanog za rutu — tada SDK vidi jedan događaj po odredištu, bez obzira na broj rekompozicija.

kotlin
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 agenti za pisanje koda

Javna površina SDK-a mala je i prilagođena code completionu — svaka metoda je na singletonu Kixo, svaki Kotlin primjer u ovom vodiču počinje sa import io.kixo.sdk.Kixo, a naš README sadrži blok „AI agent quick reference“ koji alati kao što su Claude Code, Cursor i Codex mogu direktno zalijepiti u svoj kontekst. Ako vaš agent zapne, ovo je kanonska polazna tačka:

kotlin
// 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."

Napomena

Svaki odjeljak iznad pisan je imajući taj način rada na umu — importi su uvijek eksplicitni, tipovi uvijek imenovani, a SDK singleton se nikad ne aliasira. Dajte ovu stranicu agentu i pustite ga da vodi.