Android SDK
Kixo Android SDK поддържа Kotlin 2.0+ и Java, изисква minSdk 24 (Android 7.0) и е изграден срещу compileSdk 35. Хост приложението ви остава отговорно за собственото си targetSdk. Едно извикване на Kixo.configure във вашия Application.onCreate автоматично проследява екрани, докосвания, сесии, сривове и събития от жизнения цикъл. Проследяването на push изисква FCM bridge-а, описан по-долу. Автоматичното проследяване на мрежови заявки не е част от текущата версия за Android. SDK поддържа също session replay, идентичност и цели.
Бърз старт
Три файла. Добавете Maven хранилището, добавете зависимостта и после поставете два реда в наследника си на Application.
Изисквания за компилация: compileSdk 35, minSdk 24, Kotlin 2.0+ или Java и bytecode за Java 17.
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
maven {
url = uri("https://raw.githubusercontent.com/kixoio/kixo-android-sdk/main/repo")
}
}
}Забележка
Това е цялата интеграция за аналитиката. Стандартните автоматични тракери са включени по подразбиране; за push все още е нужен FCM bridge-ът по-долу. Променяйте отделните флагове с KixoConfiguration.Builder(...) само при нужда.
Добавете в приложението си
Maven хранилището на Kixo се хоства в GitHub Pages. Добавете го редом с google() и mavenCentral() в 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")
}
}
}След това декларирайте зависимостта в модула на приложението:
// app/build.gradle.kts
dependencies {
implementation("io.kixo:kixo-android-sdk:0.1.20")
}Съвет
android.permission.INTERNET и android.permission.ACCESS_NETWORK_STATE са включени в manifest-а на SDK. Разрешенията за известия остават под контрола на приложението ви и се декларират, когато включите push функциите.
Проекти с много модули
Конфигурацията implementation в Gradle е не е транзитивно: ако декларирате implementation("io.kixo:kixo-android-sdk:0.1.20") в библиотечен модул (например :core_domain), Kixo НЕ става видим за :app или за който и да е друг потребител. Има два работещи подхода — изберете един.
Вариант A — всеки модул, който извиква Kixo, я декларира самостоятелно (препоръчително). Така classpath-ът на всеки модул остава минимален и се избягват верижни преизграждания. Използвайте version catalog (libs.kixo.sdk), за да променяте версията само на едно място.
// :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
}Вариант B — реекспортиране през api(...). Декларацията е само една, но публичният ABI на библиотечния модул вече включва типовете на Kixo — всяка промяна на версията води до преизграждане на всички зависими модули. Използвайте това само ако библиотеката използва типове на Kixo и в собствените си публични сигнатури, например връща KixoDiagnostics от функция.
// :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
}Внимание
Ако по време на компилация виждате Unresolved reference: Kixo в даден модул, на този модул му липсва собствена зависимост към SDK — добавете реда за implementation по-горе или използвайте Вариант B.
Инициализиране
Конфигурирайте Kixo в свой наследник на Application — onCreate се изпълнява преди която и да е activity, така че всеки екран, докосване и събитие от жизнения цикъл се засича още от първия кадър. Регистрирайте Application в manifest-а чрез 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",
)
}
}За по-фини настройки — флагове за автоматично проследяване, честота на flush, семплиране на replay и собствен API хост — създайте KixoConfiguration изрично:
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)Забележка
Идемпотентно. Второ извикване на configure от същия процес е no-op, записан като WARN — SDK запазва първата конфигурация. Събитията, които auth singleton-ът ви постави в опашка преди преди и преди configure да е налично, се буферират (до 50) и се изпращат, щом SDK бъде инициализиран, така че можете да извикате Kixo.identify(...) от глобален обект, преди Application.onCreate да е завършило.
Проследяване на събития
Три основни примитива покриват по-голямата част от инструментализацията ви: track за събития, markGoal за сигнали за конверсия и addBreadcrumb за контекст извън събитията.
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",
)Съвет
Целите са степенувани. Отбелязаните цели захранват activation funnel-ите в Kixo и ежедневния cron за засичане на промени — цел, чийто обем спадне със 70% спрямо предходната седмица, се показва в аналитичното табло с етикет Изисква преглед. Използвайте markGoal за шепата наистина важни моменти; track за всичко останало.
Стандартни събития
Удобна обвивка над Kixo.track за събитията, които Kixo разпознава по име — точните низови ключове, които разпознавателят на стандартни събития в бекенда съпоставя. Получавате проверка на формата на свойствата още при компилация и едно източниково място за имената.
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)Идентифициране на потребители
Свържете следващите събития със стабилен потребителски идентификатор и набор от traits. Свързването от анонимен към познат потребител става в Kixo — събитията, засечени преди identify, се приписват със задна дата на същия потребител.
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. Стандартните ключове за идентичност са с префикс $ ($email, $name, $first_name) — а в Kotlin низ трябва трябва да екранирате знака долар като "\$email". Ако напишете "$email", ще интерполирате променливата email, така че стойността тихо ще се запише като trait собствен и никога няма да попълни колоните за email / name в Audience. Най-лесната поправка е да използвате типизирания overload (SDK 0.1.13+), при който това не може да се обърка: Kixo.setUserProperty(StandardProperty.EMAIL, email).
Маркирайте потребител за сегментиране
Използвайте setUserProperty със стойност булева стойност, за да добавите към потребителя прост етикет да/не. Етикетът се запазва между стартиранията и се използва за сегменти, имейл кампании и chat заявки — без нищо допълнително освен извикването на 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",
))Свойствата се пазят чрез SharedPreferences между стартиранията и автоматично се добавят към всяко изходящо събитие. В chat можете да казвате неща като "изпрати приветствен имейл до потребителите, при които subscribe е true" — Kixo ще изгради сегмента и ще подготви шаблона вместо вас. Изчистват се при Kixo.reset().
Каталог на стандартните свойства
Запазените ключове за свойства са с префикс $, за да не се смесват с вашите персонализирани атрибути. Каталогът на Kixo включва 37 ключа в 3 универсални пакета (идентичност, геоданни, жизнен цикъл) и 5 B2B вертикални пакета (абонамент, електронна търговия, медии, маркетплейс, лоялност). Задайте само тези, които са приложими за продукта ви — таблото се адаптира и показва само пакетите, които попълвате.
Идентичност
Винаги е приложимо. Определя колоните в заглавната част на профила.
| Ключ | Тип | Описание |
|---|---|---|
$email | низ | Основен имейл, често използван като ключ за обединяване при свързване на идентичности. |
$phone | низ | Телефонен номер във формат E.164. |
$name | низ | Пълно показвано име. |
$first_name | низ | Собствено име. |
$last_name | низ | Фамилия. |
$avatar_url | низ | Пълен URL адрес към аватарното изображение на потребителя. |
Геоданни
Географски контекст.
| Ключ | Тип | Описание |
|---|---|---|
$country | низ | Код на държава по ISO 3166. |
$city | низ | Име на град. |
$region | низ | Щат или област. |
$timezone | низ | IANA зона като America/Los_Angeles. |
$language | низ | IETF етикет като en или ru-RU. |
$locale | низ | Пълен идентификатор на локал. |
Жизнен цикъл
Кога сме го видели.
| Ключ | Тип | Описание |
|---|---|---|
$created | ISO8601 | Моментът на регистрация или създаване на акаунт. |
$last_seen | ISO8601 | Последно взаимодействие. |
Абонамент
Задайте, ако продуктът ви предлага планове.
| Ключ | Тип | Описание |
|---|---|---|
$plan | низ | Slug на ниво — free, pro, enterprise. |
$subscription_status | низ | active / trial / cancelled / past_due. |
$trial_ends | ISO8601 | Кога изтича текущият пробен период. |
$mrr | число | Месечен повтаряем приход във валутата на акаунта. |
$subscription_started | ISO8601 | Кога е започнал текущият абонамент. |
Електронна търговия
Задайте, ако продавате продукти.
| Ключ | Тип | Описание |
|---|---|---|
$lifetime_orders | число | Брой завършени поръчки. |
$lifetime_revenue | число | Общ разход. |
$aov | число | Средна стойност на поръчка. |
$last_purchase | ISO8601 | Последна успешна покупка. |
$first_purchase | ISO8601 | Първа успешна покупка. |
$cart_abandoned_count | число | Общ брой изоставени колички. |
Медии
Задайте, ако публикувате съдържание.
| Ключ | Тип | Описание |
|---|---|---|
$content_tier | низ | free / premium / paid. |
$subscribed_categories | CSV низ или масив | Категории, които потребителят следи. |
$watch_time_total | число | Общо време на гледане в секунди. |
$last_played | ISO8601 | Последно стартирано възпроизвеждане. |
Маркетплейс
Задайте, ако продуктът ви е двустранна платформа.
| Ключ | Тип | Описание |
|---|---|---|
$seller_tier | низ | Slug на плана от страната на продавача. |
$buyer_tier | низ | Slug на плана за купувача. |
$listings_count | число | Активни обяви на потребителя. |
$reviews_count | число | Отзиви, получени от потребителя. |
$verified | булева стойност | KYC статус. |
Лоялност
Задайте, ако имате програми за ангажираност и награди.
| Ключ | Тип | Описание |
|---|---|---|
$loyalty_points | число | Текущ баланс от точки за използване. |
$vip_level | низ | Slug на VIP нивото. |
$referral_count | число | Успешни препоръки, приписани на този потребител. |
Съвет
Не виждате своя модел? Използвайте обикновени ключове за персонализирани traits. Те се показват в панела Custom Traits в dashboard-а, без да запълват колоните на профила. Петте вертикални пакета по-горе са целенасочени предположения за най-често срещаните B2B модели — специфичната за клиента терминология (например shipping_plan) остава без префикс.
Суперсвойства
Двойки ключ/стойност за сесията, които автоматично се добавят към всяко изходящо събитие. Те са различни от traits в identify (които описват идентичността); super-properties описват контекста на сесията — активен A/B вариант, build flavor, включени feature flags. Запазват се между стартиранията и се изчистват при reset(). При конфликт винаги с предимство са подадените за конкретното събитие properties в 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()Push известия
Има два начина за интеграция. Изберете A, ако сте на FCM и искате най-кратката работеща настройка; изберете B, ако вече имате собствен FirebaseMessagingService, който не можете да преструктурирате, или искате изричен контрол върху това кои FCM доставки да вижда Kixo.
Вариант A — наследете KixoFirebaseMessagingService (автоматично проследяване)
Наследете KixoFirebaseMessagingService и извикайте super.onMessageReceived(...) в override-а си — Kixo автоматично изпраща push_received (с видимо съдържание) или push_silent (само данни). Базовият клас обработва и регистрацията на onNewToken, ако не я override-нете. Регистрацията на AndroidManifest.xml е същата като при обикновена FCM service.
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
}
}Забележка
Kixo компилира този незадължителен клас срещу Firebase Messaging, но не добавя Firebase транзитивно към приложението ви. SDK декларира Firebase като compileOnly; приложение, което избере този вариант, трябва вече да има зависимост към firebase-messaging, както при всеки FCM receiver.
Вариант B — извиквайте ръчния API от собствената си FCM service
Регистрирайте своя FCM token в Kixo чрез FirebaseMessagingService.onNewToken, след което записвайте изрично всяка доставка. Използвайте този вариант, ако искате Kixo да вижда само част от FCM доставките. Засега проследяването на доставки в Android поддържа само 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 не предоставя универсална lifecycle hook за отваряне на известия, затваряне или бутони за действие. Подайте тези сигнали от notification intent-ите или receiver-ите, които приложението ви създава:
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Възпроизвеждане на сесии
Възпроизведете реална визуална реконструкция на това, което е видял потребителят. При всяко заснемане SDK кодира компресиран кадър на екрана (JPEG изображение) заедно със структурна снимка на йерархията на изгледите и качва и двете — така плейърът в аналитичното табло може да показва възпроизвеждане с точност до пиксел редом с хронологията на взаимодействията. Настройте replay за проекта в Табло → Настройки → Запис на сесии. SDK автоматично прочита и опреснява тази проектна политика, включително маскиране, режими на заснемане и разрешение за качване през мобилна мрежа.
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)Когато качването през мобилна мрежа е изключено, чакащият replay изчаква разрешена мрежа.
Съвет
Маскирайте преди качване. Kixo заснема пиксели, затова маскирането се прилага преди, преди каквото и да било да напусне устройството. Полетата за парола и e-mail се разпознават автоматично и се редактират; текстът в структурните снимки минава през PII филтър; а всеки изглед, който маркирате с setKixoMask(true), се растеризира като непрозрачен правоъгълник в кадъра преди кодирането в JPEG — пикселите му никога не напускат устройството. Екраните в Jetpack Compose по подразбиране се маскират изцяло (извикайте setKixoMask(false) върху най-външния ComposeView, за да включите екран, който вече сте прегледали). Операторите преглеждат replay плейъра редом с хронологията на събитията в аналитичното табло.
Събиране на данни
SDK събира данните, които са включени в проекта ви, както и събитията и свойствата, които приложението ви изпраща.
Отстраняване на проблеми
Kixo.diagnostics() връща snapshot само за четене на състоянието на SDK — полезно в скрит екран за диагностика или smoke тест. Отговаря на въпроса „защо събитията ми не се изпращат?“ без 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 stateПринудете flush от тестовия си harness — блокира до timeoutMs в очакване на мрежов round-trip:
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
Маршрутите на Activity / Fragment веднага създават screen_viewevents и структурирани записи screen_visit с метаданни за престой и поток, без допълнителна настройка. При Jetpack Compose Navigation извиквайте Kixo.screen от LaunchedEffect, вързан към route — така SDK вижда по едно събитие за всяка дестинация, независимо колко пъти се прекомпозира.
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 агенти за програмиране
Публичният интерфейс на SDK е малък и подреден за code completion — всеки метод е върху singleton-а Kixo, всеки Kotlin пример в това ръководство започва с import io.kixo.sdk.Kixo, а нашият README включва блок „AI agent quick reference“, който инструменти като Claude Code, Cursor и Codex могат директно да поставят в контекста си. Ако агентът ви заседне, каноничната отправна точка е:
// 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."Забележка
Всеки раздел по-горе е написан с мисъл за този начин на работа — import-ите винаги са изрични, типовете винаги са изписани, а singleton-ът на SDK никога не е с псевдоним. Дайте тази страница на агента си и го оставете да я следва.