Get actionable, trackable data instantly to drive better decisions and performance.
Analytics events are structured data objects that get automatically triggered when significant actions or states occur within components. These allow you to monitor every aspect of the payment journey.
Analytics events allow you to:
- Gain transparency with native transaction tracking in PXP reports.
- Optimise conversion rates and reduce drop-offs, thanks to actionable insights.
- Feed real-time data into your analytics and CRM systems.
Analytics events should be consumed in the PxpSdkConfig during SDK initialisation. For example:
val sdkConfig = PxpSdkConfig(
environment = Environment.TEST,
session = SessionConfig(
sessionId = "your_session_id",
sessionData = "your_session_data"
),
merchantShopperId = "123",
ownerId = "UnityGroup",
ownerType = "MerchantGroup",
transactionData = TransactionData(
currency = CurrencyType.USD,
amount = payAmount,
entryType = EntryType.Ecom,
intent = IntentType.Authorisation,
merchantTransactionId = "9af8af33-59d5-432d-bd35-96124930ec9f",
merchantTransactionDate = { Instant.now().toString() }
),
analyticsEvent = { analyticsEvent ->
when (analyticsEvent) {
is ComponentLifecycleAnalyticsEvent -> {
// Track component lifecycle (mount/unmount)
Log.d("Analytics", "Component ${analyticsEvent.eventType}: ${analyticsEvent.componentId}")
analytics.track(analyticsEvent.eventName, analyticsEvent.toMap())
}
is ErrorTracker.ComponentErrorEvent -> {
// Log component errors for debugging
Log.e("Analytics", "Component error: ${analyticsEvent.message}")
crashlytics.recordException(Exception(analyticsEvent.message))
}
is ErrorTracker.ComponentValidationEvent -> {
// Track validation events
analytics.track("component_validation", mapOf(
"component_id" to analyticsEvent.componentId,
"is_valid" to analyticsEvent.isValid,
"validation_message" to analyticsEvent.validationMessage
))
}
else -> {
// Handle other analytics events
Log.d("Analytics", "Event: ${analyticsEvent.eventName}")
analytics.track(analyticsEvent.eventName, analyticsEvent.toMap())
}
}
}
)
val pxpCheckout = PxpCheckout.builder()
.withConfig(sdkConfig)
.withContext(this)
.withDebugMode(true)
.build()The Android SDK provides several types of analytics events:
Track when components are mounted and unmounted in your application:
class ComponentLifecycleAnalyticsEvent(
val eventType: LifecycleEventType, // MOUNT or UNMOUNT
val componentId: String,
sessionId: String,
val componentType: String? = null
) : BaseAnalyticsEvent("ComponentLifecycleEvent", sessionId)Track errors that occur within components:
class ComponentErrorEvent(
val code: String,
val message: String,
val componentId: String,
sessionId: String
) : BaseAnalyticsEvent("ComponentErrorEvent", sessionId)Track validation results for components:
class ComponentValidationEvent(
val componentId: String,
val isValid: Boolean,
val validationMessage: String?,
sessionId: String
) : BaseAnalyticsEvent("ComponentValidationEvent", sessionId)Here's a comprehensive example showing how to handle the available analytics events:
class AnalyticsManager {
fun setupAnalyticsEventHandler(): (BaseAnalyticsEvent) -> Unit {
return { analyticsEvent ->
// Log all events for debugging (remove in production)
Log.d("Analytics", "Event: ${analyticsEvent.eventName} at ${analyticsEvent.timestamp}")
when (analyticsEvent) {
// Component lifecycle events
is ComponentLifecycleAnalyticsEvent -> {
when (analyticsEvent.eventType) {
LifecycleEventType.MOUNT -> {
trackComponentMount(analyticsEvent)
}
LifecycleEventType.UNMOUNT -> {
trackComponentUnmount(analyticsEvent)
}
}
}
// Error tracking
is ErrorTracker.ComponentErrorEvent -> {
trackComponentError(analyticsEvent)
// Send to crash reporting
crashlytics.recordException(Exception(analyticsEvent.message))
}
// Validation tracking
is ErrorTracker.ComponentValidationEvent -> {
trackValidationEvent(analyticsEvent)
}
else -> {
// Send all events to your analytics service
sendToAnalyticsService(analyticsEvent)
}
}
}
}
// Helper functions for tracking specific events
private fun trackComponentMount(event: ComponentLifecycleAnalyticsEvent) {
analytics.track("component_mounted", mapOf(
"component_id" to event.componentId,
"component_type" to event.componentType,
"session_id" to event.sessionId,
"timestamp" to event.timestamp
))
}
private fun trackComponentUnmount(event: ComponentLifecycleAnalyticsEvent) {
analytics.track("component_unmounted", mapOf(
"component_id" to event.componentId,
"component_type" to event.componentType,
"session_id" to event.sessionId,
"timestamp" to event.timestamp
))
}
private fun trackComponentError(event: ErrorTracker.ComponentErrorEvent) {
analytics.track("component_error", mapOf(
"component_id" to event.componentId,
"error_code" to event.code,
"error_message" to event.message,
"session_id" to event.sessionId
))
}
private fun trackValidationEvent(event: ErrorTracker.ComponentValidationEvent) {
analytics.track("component_validation", mapOf(
"component_id" to event.componentId,
"is_valid" to event.isValid,
"validation_message" to event.validationMessage,
"session_id" to event.sessionId
))
}
private fun sendToAnalyticsService(event: BaseAnalyticsEvent) {
// Send to your analytics service (Firebase, Mixpanel, etc.)
firebaseAnalytics.logEvent(event.eventName, Bundle().apply {
event.toMap().forEach { (key, value) ->
when (value) {
is String -> putString(key, value)
is Int -> putInt(key, value)
is Long -> putLong(key, value)
is Boolean -> putBoolean(key, value)
is Double -> putDouble(key, value)
else -> putString(key, value.toString())
}
}
})
}
}private fun logToFirebase(event: BaseAnalyticsEvent) {
val bundle = Bundle().apply {
event.toMap().forEach { (key, value) ->
when (value) {
is String -> putString(key, value)
is Int -> putInt(key, value)
is Long -> putLong(key, value)
is Boolean -> putBoolean(key, value)
is Double -> putDouble(key, value)
else -> putString(key, value.toString())
}
}
}
firebaseAnalytics.logEvent(event.eventName, bundle)
}private fun logToCustomService(event: BaseAnalyticsEvent) {
val payload = JSONObject().apply {
put("event_name", event.eventName)
put("session_id", event.sessionId)
put("timestamp", event.timestamp.time)
event.toMap().forEach { (key, value) ->
put(key, value)
}
}
// Send to your custom analytics endpoint
analyticsApiClient.logEvent(payload)
}- Filter events: Only track events relevant to your business needs
- Error handling: Always wrap analytics calls in try-catch blocks
- Performance: Avoid blocking the main thread with analytics calls
- Privacy: Ensure compliance with data protection regulations
// Good: Non-blocking analytics
analyticsEvent = { event ->
GlobalScope.launch(Dispatchers.IO) {
try {
handleAnalyticsEvent(event)
} catch (e: Exception) {
Log.e("Analytics", "Failed to track event", e)
}
}
}
// Good: Selective event tracking
analyticsEvent = { event ->
when (event) {
is ComponentLifecycleAnalyticsEvent -> {
// Only track lifecycle for specific components
if (event.componentType in criticalComponents) {
trackEvent(event)
}
}
is ErrorTracker.ComponentErrorEvent -> {
// Always track errors
trackEvent(event)
}
// Ignore other events
}
}- Always obtain user consent before collecting analytics data
- Anonymize sensitive information in event payloads
- Provide opt-out mechanisms for analytics tracking
- Comply with GDPR, CCPA, and other relevant regulations
// Example: Privacy-aware analytics
analyticsEvent = { event ->
if (userHasConsentedToAnalytics()) {
val sanitizedEvent = sanitizeEventData(event)
trackEvent(sanitizedEvent)
}
}
private fun sanitizeEventData(event: BaseAnalyticsEvent): BaseAnalyticsEvent {
// Remove or hash sensitive data
val sanitizedMap = event.toMap().filterKeys { key ->
key !in sensitiveDataKeys
}
return event // Return sanitized version
}