Code Examples

Complete Kotlin and Java examples for all SDK methods

Complete, copy-pasteable examples for every public method of the Convert Android SDK. Kotlin is shown first; see Java Interop for the Java equivalents. All examples assume a single ConvertSDK instance built once in Application.onCreate() (see Initialization).

Build the SDK

import com.convert.sdk.android.ConvertSDK
import com.convert.sdk.core.model.LogLevel

val sdk = ConvertSDK.builder(applicationContext)
    .sdkKey("YOUR_SDK_KEY")
    .environment("prod")
    .logLevel(LogLevel.INFO)
    .build()

Wait for readiness

sdk.onReady {
    // Decisions are available from here on.
}

Create a visitor context

// Auto-persisted UUID visitor.
val ctx = sdk.createContext()

// Explicit visitor id.
val ctx = sdk.createContext("visitor-42")

// Explicit visitor id with initial attributes.
val ctx = sdk.createContext(
    visitorId = "visitor-42",
    attributes = mapOf("plan" to "premium", "accountAgeDays" to 120),
)

Run a single experience

val variation = ctx.runExperience("homepage-redesign")
when (variation?.key) {
    "control" -> renderControl()
    "treatment" -> renderTreatment()
    null -> renderControl() // SDK not ready, visitor not bucketed, or experience absent
}

Run all experiences for the visitor

val variations = ctx.runExperiences()
variations.forEach { applyVariation(it) }

runExperiences() returns only the experiences the visitor is bucketed into; it filters out ones that failed audience/location rules.

Suppress the tracking event for a call

// Evaluate but do not report (e.g. consent-denied flow).
val variation = ctx.runExperience("homepage-redesign", enableTracking = false)
ctx.runExperiences(enableTracking = false)

Bucketing, sticky persistence, audience rules, and the internal bucketing event still fire — only the outbound network event is skipped. See Tracking Control.

Evaluate a feature flag

val feature = ctx.runFeature("checkout-v2")
if (feature?.enabled == true) {
    enableCheckoutV2()
}

Read feature variables

import com.convert.sdk.android.getString
import com.convert.sdk.android.getInt
import com.convert.sdk.android.getDouble
import com.convert.sdk.android.getBoolean

val feature = ctx.runFeature("checkout-v2")
val color = feature?.getString("ctaColor") ?: "#0066ff"
val limit = feature?.getInt("maxItems") ?: 20
val price = feature?.getDouble("price") ?: 9.99
val experimental = feature?.getBoolean("experimental") == true

Run all features

val all = ctx.runFeatures() // every declared feature, evaluated for this visitor

Track a conversion

import com.convert.sdk.core.model.GoalData
import com.convert.sdk.core.model.GoalDataKey
import kotlinx.serialization.json.JsonPrimitive

// Bare goal.
ctx.trackConversion("signup-completed")

// With transactional goal data.
ctx.trackConversion(
    goalKey = "purchase-completed",
    goalData = listOf(
        GoalData(GoalDataKey.AMOUNT, JsonPrimitive(49.99)),
        GoalData(GoalDataKey.PRODUCTS_COUNT, JsonPrimitive(3)),
        GoalData(GoalDataKey.TRANSACTION_ID, JsonPrimitive("tx-42")),
    ),
)

Force a repeat transaction (bypass dedup)

By default the same goal records only once per visitor. For renewals or repeat purchases, bypass dedup:

ctx.trackConversion(
    goalKey = "purchase-completed",
    goalData = listOf(GoalData(GoalDataKey.AMOUNT, JsonPrimitive(49.99))),
    conversionSetting = mapOf("forceMultipleTransactions" to true),
)

On the repeat call the bare conversion is skipped (already recorded), the transaction payload is sent, and the conversion event fires. See Tracking Conversions.

Check whether a goal exists

if (ctx.hasGoal("purchase-completed")) {
    // The goal key is declared in the current config.
}

Set attributes (targeting input)

ctx.setAttributes(mapOf("plan" to "premium"))

Attributes feed the audience/location rule engine and do not flow into outbound tracking events. setAttributes replaces, it does not merge — merge yourself with ctx.setAttributes(old + new) if needed.

Set location properties

ctx.setLocationProperties(mapOf("path" to "/checkout", "country" to "US"))

Set segments (reported with events)

// Default segments — string values.
ctx.setDefaultSegments(mapOf("plan" to "premium", "country" to "US"))

// Custom segments — any JSON value.
ctx.setCustomSegments(mapOf(
    "lifetimeValue" to 1250.75,
    "isBetaTester" to true,
))

Segments flow into outbound tracking events and feed audience rules. Both setters replace (not merge). Pass emptyMap() to clear on sign-out. See Segments.

Subscribe to and unsubscribe from events

import com.convert.sdk.android.EventCallback
import com.convert.sdk.core.event.SystemEvents

val token = sdk.on(SystemEvents.CONVERSION, EventCallback { data ->
    // handle the conversion payload
})

sdk.off(SystemEvents.CONVERSION, token)

Toggle tracking at runtime

sdk.setTrackingEnabled(false) // e.g. on consent withdrawal
sdk.setTrackingEnabled(true)  // e.g. on consent re-grant
val enabled = sdk.isTrackingEnabled()

See Tracking Control for the full consent matrix.

Next steps