Към документацията

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:

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

След това декларирайте зависимостта в модула на приложението:

kotlin
// 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), за да променяте версията само на едно място.

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
}

Вариант B — реекспортиране през api(...). Декларацията е само една, но публичният ABI на библиотечния модул вече включва типовете на Kixo — всяка промяна на версията води до преизграждане на всички зависими модули. Използвайте това само ако библиотеката използва типове на Kixo и в собствените си публични сигнатури, например връща 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
}

Внимание

Ако по време на компилация виждате Unresolved reference: Kixo в даден модул, на този модул му липсва собствена зависимост към SDK — добавете реда за implementation по-горе или използвайте Вариант B.

Инициализиране

Конфигурирайте Kixo в свой наследник на ApplicationonCreate се изпълнява преди която и да е activity, така че всеки екран, докосване и събитие от жизнения цикъл се засича още от първия кадър. Регистрирайте Application в manifest-а чрез 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",
        )
    }
}

За по-фини настройки — флагове за автоматично проследяване, честота на flush, семплиране на replay и собствен API хост — създайте 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)

Забележка

Идемпотентно. Второ извикване на configure от същия процес е no-op, записан като WARN — SDK запазва първата конфигурация. Събитията, които auth singleton-ът ви постави в опашка преди преди и преди configure да е налично, се буферират (до 50) и се изпращат, щом SDK бъде инициализиран, така че можете да извикате Kixo.identify(...) от глобален обект, преди Application.onCreate да е завършило.

Проследяване на събития

Три основни примитива покриват по-голямата част от инструментализацията ви: track за събития, markGoal за сигнали за конверсия и addBreadcrumb за контекст извън събитията.

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

Съвет

Целите са степенувани. Отбелязаните цели захранват activation funnel-ите в Kixo и ежедневния cron за засичане на промени — цел, чийто обем спадне със 70% спрямо предходната седмица, се показва в аналитичното табло с етикет Изисква преглед. Използвайте markGoal за шепата наистина важни моменти; track за всичко останало.

Стандартни събития

Удобна обвивка над Kixo.track за събитията, които Kixo разпознава по име — точните низови ключове, които разпознавателят на стандартни събития в бекенда съпоставя. Получавате проверка на формата на свойствата още при компилация и едно източниково място за имената.

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)

Идентифициране на потребители

Свържете следващите събития със стабилен потребителски идентификатор и набор от traits. Свързването от анонимен към познат потребител става в Kixo — събитията, засечени преди identify, се приписват със задна дата на същия потребител.

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. Стандартните ключове за идентичност са с префикс $ ($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.

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

Свойствата се пазят чрез 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низПълен идентификатор на локал.

Жизнен цикъл

Кога сме го видели.

КлючТипОписание
$createdISO8601Моментът на регистрация или създаване на акаунт.
$last_seenISO8601Последно взаимодействие.

Абонамент

Задайте, ако продуктът ви предлага планове.

КлючТипОписание
$planнизSlug на ниво — free, pro, enterprise.
$subscription_statusнизactive / trial / cancelled / past_due.
$trial_endsISO8601Кога изтича текущият пробен период.
$mrrчислоМесечен повтаряем приход във валутата на акаунта.
$subscription_startedISO8601Кога е започнал текущият абонамент.

Електронна търговия

Задайте, ако продавате продукти.

КлючТипОписание
$lifetime_ordersчислоБрой завършени поръчки.
$lifetime_revenueчислоОбщ разход.
$aovчислоСредна стойност на поръчка.
$last_purchaseISO8601Последна успешна покупка.
$first_purchaseISO8601Първа успешна покупка.
$cart_abandoned_countчислоОбщ брой изоставени колички.

Медии

Задайте, ако публикувате съдържание.

КлючТипОписание
$content_tierнизfree / premium / paid.
$subscribed_categoriesCSV низ или масивКатегории, които потребителят следи.
$watch_time_totalчислоОбщо време на гледане в секунди.
$last_playedISO8601Последно стартирано възпроизвеждане.

Маркетплейс

Задайте, ако продуктът ви е двустранна платформа.

КлючТипОписание
$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.

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 известия

Има два начина за интеграция. Изберете A, ако сте на FCM и искате най-кратката работеща настройка; изберете B, ако вече имате собствен FirebaseMessagingService, който не можете да преструктурирате, или искате изричен контрол върху това кои FCM доставки да вижда Kixo.

Вариант A — наследете KixoFirebaseMessagingService (автоматично проследяване)

Наследете KixoFirebaseMessagingService и извикайте super.onMessageReceived(...) в override-а си — Kixo автоматично изпраща push_received (с видимо съдържание) или push_silent (само данни). Базовият клас обработва и регистрацията на onNewToken, ако не я override-нете. Регистрацията на AndroidManifest.xml е същата като при обикновена FCM service.

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

Забележка

Kixo компилира този незадължителен клас срещу Firebase Messaging, но не добавя Firebase транзитивно към приложението ви. SDK декларира Firebase като compileOnly; приложение, което избере този вариант, трябва вече да има зависимост към firebase-messaging, както при всеки FCM receiver.

Вариант B — извиквайте ръчния API от собствената си FCM service

Регистрирайте своя FCM token в Kixo чрез FirebaseMessagingService.onNewToken, след което записвайте изрично всяка доставка. Използвайте този вариант, ако искате Kixo да вижда само част от FCM доставките. Засега проследяването на доставки в Android поддържа само 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 не предоставя универсална lifecycle hook за отваряне на известия, затваряне или бутони за действие. Подайте тези сигнали от notification intent-ите или receiver-ите, които приложението ви създава:

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

Възпроизвеждане на сесии

Възпроизведете реална визуална реконструкция на това, което е видял потребителят. При всяко заснемане SDK кодира компресиран кадър на екрана (JPEG изображение) заедно със структурна снимка на йерархията на изгледите и качва и двете — така плейърът в аналитичното табло може да показва възпроизвеждане с точност до пиксел редом с хронологията на взаимодействията. Настройте replay за проекта в Табло → Настройки → Запис на сесии. SDK автоматично прочита и опреснява тази проектна политика, включително маскиране, режими на заснемане и разрешение за качване през мобилна мрежа.

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)

Когато качването през мобилна мрежа е изключено, чакащият replay изчаква разрешена мрежа.

Съвет

Маскирайте преди качване. Kixo заснема пиксели, затова маскирането се прилага преди, преди каквото и да било да напусне устройството. Полетата за парола и e-mail се разпознават автоматично и се редактират; текстът в структурните снимки минава през PII филтър; а всеки изглед, който маркирате с setKixoMask(true), се растеризира като непрозрачен правоъгълник в кадъра преди кодирането в JPEG — пикселите му никога не напускат устройството. Екраните в Jetpack Compose по подразбиране се маскират изцяло (извикайте setKixoMask(false) върху най-външния ComposeView, за да включите екран, който вече сте прегледали). Операторите преглеждат replay плейъра редом с хронологията на събитията в аналитичното табло.

Събиране на данни

SDK събира данните, които са включени в проекта ви, както и събитията и свойствата, които приложението ви изпраща.

Отстраняване на проблеми

Kixo.diagnostics() връща snapshot само за четене на състоянието на SDK — полезно в скрит екран за диагностика или smoke тест. Отговаря на въпроса „защо събитията ми не се изпращат?“ без debugger.

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

Принудете flush от тестовия си harness — блокира до timeoutMs в очакване на мрежов 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

Маршрутите на Activity / Fragment веднага създават screen_viewevents и структурирани записи screen_visit с метаданни за престой и поток, без допълнителна настройка. При Jetpack Compose Navigation извиквайте Kixo.screen от LaunchedEffect, вързан към route — така SDK вижда по едно събитие за всяка дестинация, независимо колко пъти се прекомпозира.

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 агенти за програмиране

Публичният интерфейс на SDK е малък и подреден за code completion — всеки метод е върху singleton-а Kixo, всеки Kotlin пример в това ръководство започва с import io.kixo.sdk.Kixo, а нашият README включва блок „AI agent quick reference“, който инструменти като Claude Code, Cursor и Codex могат директно да поставят в контекста си. Ако агентът ви заседне, каноничната отправна точка е:

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

Забележка

Всеки раздел по-горе е написан с мисъл за този начин на работа — import-ите винаги са изрични, типовете винаги са изписани, а singleton-ът на SDK никога не е с псевдоним. Дайте тази страница на агента си и го оставете да я следва.