Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.spotzee.com/llms.txt

Use this file to discover all available pages before exploring further.

track sends a single event to Spotzee. Events drive journey entrances, segment membership, campaign triggers, and reporting. Each event carries a name and a properties map, and optionally inline updates to the user’s profile.

Track an event

track is fire-and-forget. It returns immediately and the SDK pushes the event from a background coroutine.
import com.spotzee.android.Spotzee

MainApplication.analytics.track(
    event = "Order placed",
    properties = mapOf(
        "order_id" to "ord_2026_04_30_001",
        "total" to 129.50,
        "currency" to "AUD",
        "items" to 3,
        "sku" to listOf("SHIRT-AU-12", "BAG-AU-01"),
    )
)
The SDK attaches the persisted anonymous ID and the cached externalId (when set) on every call. You don’t pass either explicitly.

Naming and structuring events

  • Use a short, descriptive name in the past tense. Order placed, Account upgraded, Subscription cancelled. Consistent verb tense pays off when you build segments.
  • Match the name across surfaces. A track("Order placed") from Android and one from your backend should be the same event so journeys fire once per order, not twice with different names.
  • Properties are flat key-value pairs. Strings, numbers, booleans, lists of strings or numbers, and shallow maps serialise cleanly. Deeper nesting works but is harder to segment on.
  • Property names use snake_case in the source map. The SDK does not transform top-level keys inside Map<String, Any> properties.
Read Send events from your backend for the broader event model.

Update user traits inline with the event

Set or refresh traits on the user record without a separate identify call:
import com.spotzee.android.TrackUser

MainApplication.analytics.track(
    event = "Profile updated",
    properties = mapOf("source" to "self-serve"),
    user = TrackUser(
        timezone = "Australia/Melbourne",
        locale = "en-AU",
        data = mapOf(
            "plan" to "professional",
            "seats_allocated" to 5,
        )
    )
)
TrackUser accepts email, phone, timezone, locale, and a nested data map for arbitrary traits. Use this when the trait change is the natural side effect of the event (a Plan upgraded event upserting the new plan value), not for routine updates.

Anonymous events

Track works without an identify. Events fire against the SDK’s persisted anonymous ID and join back to the known user the first time you call identify.
// Anonymous browse
MainApplication.analytics.track(
    event = "Product viewed",
    properties = mapOf("sku" to "SHIRT-AU-12")
)

// Sign-up. Anonymous events are aliased to u_42.
lifecycleScope.launch {
    MainApplication.analytics.identify(
        id = "u_42",
        email = "sam@example.com"
    )
}

Built-in retry

Each track schedules a POST and retries up to three times on failure. The SDK does not block your code on the result; calls return immediately and run on the process-wide lifecycleScope. For events you cannot afford to lose (Order placed, Payment processed), still send a backend duplicate via event ingestion. The SDK’s retry covers transient blips; a force-stop before the network call lands does not.

Push notification analytics

Bridge inbound FCM payloads to track so you can build segments on push receipt and engagement:
class MyFirebaseService : FirebaseMessagingService() {
    override fun onMessageReceived(remoteMessage: RemoteMessage) {
        super.onMessageReceived(remoteMessage)
        val title = remoteMessage.data["title"]
        val body = remoteMessage.data["content"]
        MainApplication.analytics.track(
            event = "Push Notification Received",
            properties = mapOf(
                "campaign" to mapOf(
                    "medium" to "Push",
                    "source" to "FCM",
                    "name" to title,
                    "content" to body,
                )
            )
        )
    }
}
Read Push notifications for the full FCM wiring.

Throughput and batching

Each track is one HTTP request. The SDK does not batch. For high-frequency events (animation analytics, gameplay metrics), buffer in your app and send larger windows from your backend rather than one POST per event from the device.

Next steps

Trigger a journey from an event

Wire an event to a journey entrance.

Build a segment from events

Use event-frequency rules in segment definitions.