Skip to content

Analytics

Get actionable, trackable data instantly to drive better decisions and performance.

Overview

Analytics events are structured data objects automatically triggered when significant actions or states occur during a Paze payment. Configure a single handler on CheckoutConfig to monitor every stage 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.

Consume an event

Analytics events are delivered through the analyticsEvent callback on CheckoutConfig when you initialise PxpCheckout:

let checkoutConfig = CheckoutConfig(
    environment: .test,
    session: sessionData,
    transactionData: transactionData,
    merchantShopperId: "shopper-123",
    ownerId: "MERCHANT-GROUP-1",
    clientName: "Your Merchant",
    siteName: "Your Store",
    onGetShopper: { async in
        TransactionShopper(id: "shopper-123", email: "customer@example.com")
    },
    analyticsEvent: { event in
        if let clickEvent = event as? PazeButtonClickAnalyticsEvent {
            print("Paze button clicked", clickEvent.componentId, clickEvent.merchantTransactionId)
        }

        if let checkoutComplete = event as? PazeCheckoutCompletedAnalyticsEvent {
            print("Paze checkout completed", checkoutComplete.merchantTransactionId)
        }

        if let authFailed = event as? PazeAuthorisationFailedAnalyticsEvent {
            print("Paze authorisation failed", String(describing: authFailed.additionalData))
        }
    }
)

let pxpCheckout = try PxpCheckout.initialize(config: checkoutConfig)

To handle all Paze-specific events with one branch, cast to PazeAnalyticsEvent:

analyticsEvent: { event in
    if let pazeEvent = event as? PazeAnalyticsEvent {
        trackPazeEvent(
            name: pazeEvent.eventName,
            sessionId: pazeEvent.sessionId,
            componentId: pazeEvent.componentId,
            merchantTransactionId: pazeEvent.merchantTransactionId,
            additionalData: pazeEvent.additionalData
        )
    }
}

Button visibility isn't emitted as a dedicated analytics event. Instead, track presentment with onPresentmentResolved on the Paze button component:

config.onPresentmentResolved = { isVisible in
    trackMetric("paze_button_visible", properties: ["isVisible": isVisible])
}

Supported events

The following tables list events you can receive during a Paze payment. Paze-specific events extend PazeAnalyticsEvent. Shared lifecycle events use different structures, so check eventName and componentType when filtering.

Paze-specific events

Events that extend PazeAnalyticsEvent:

Event nameSwift typeStructure
PazeButtonRenderedPazeButtonRenderedAnalyticsEventeventName, timestamp, sessionId, componentId, merchantTransactionId, walletType
PazeButtonClickedPazeButtonClickAnalyticsEventeventName, timestamp, sessionId, componentId, merchantTransactionId, walletType
PazePopupLaunchedPazePopupLaunchedAnalyticsEventeventName, timestamp, sessionId, componentId, merchantTransactionId, walletType
PazeCheckoutCompletedPazeCheckoutCompletedAnalyticsEventeventName, timestamp, sessionId, componentId, merchantTransactionId, walletType
PazeCheckoutAbandonedPazeCheckoutAbandonedAnalyticsEventeventName, timestamp, sessionId, componentId, merchantTransactionId, walletType, additionalData
PazeDecryptionInitiatedPazeDecryptionInitiatedAnalyticsEventeventName, timestamp, sessionId, componentId, merchantTransactionId, walletType
PazeDecryptionCompletedPazeDecryptionCompletedAnalyticsEventeventName, timestamp, sessionId, componentId, merchantTransactionId, walletType
PazeDecryptionFailedPazeDecryptionFailedAnalyticsEventeventName, timestamp, sessionId, componentId, merchantTransactionId, walletType, additionalData
PazeAuthorisationFailedPazeAuthorisationFailedAnalyticsEventeventName, timestamp, sessionId, componentId, merchantTransactionId, walletType, additionalData
PazeSdkInitialisationFailedPazeSdkInitialisationFailedAnalyticsEventeventName, timestamp, sessionId, componentId, merchantTransactionId, walletType, additionalData
PazeCheckoutFailedPazeCheckoutFailedAnalyticsEventeventName, timestamp, sessionId, componentId, merchantTransactionId, walletType, additionalData
PazeCompleteFailedPazeCompleteFailedAnalyticsEventeventName, timestamp, sessionId, componentId, merchantTransactionId, walletType, additionalData

Shared lifecycle events during Paze payments

These events don't extend PazeAnalyticsEvent:

Event nameSwift typeStructure
PreAuthorisationPreAuthorisationAnalyticsEventeventName, timestamp, sessionId, componentType, transactionId, isRetry
PostAuthorisationPostAuthorisationAnalyticsEventeventName, timestamp, sessionId, componentType, transactionId, isRetry
PazeTransactionInitiatedPaymentLifecycleAnalyticsEventeventName, timestamp, sessionId, componentType, transactionId
PazeAuthorisationCancelledPaymentLifecycleAnalyticsEventeventName, timestamp, sessionId, componentType, transactionId
PazeTokenDecryptionCancelledPaymentLifecycleAnalyticsEventeventName, timestamp, sessionId, componentType, transactionId
ComponentErrorComponentErrorAnalyticsEventeventName, timestamp, sessionId, errorCode, errorMessage, componentId

PreAuthorisation is emitted only when you configure onPreAuthorisation and the flow proceeds (.proceed or .transactionInitData). Returning .cancel emits PazeAuthorisationCancelled instead. PostAuthorisation is emitted when you configure onPostAuthorisation and the SDK receives a MerchantSubmitResult, immediately before your callback runs. PazeAuthorisationFailed may also fire if the response reports an error state. Paze doesn't emit 3DS or tokenisation events such as PreAuthentication or PreTokenization.

Event data

All Paze analytics events extend PazeAnalyticsEvent and include:

NameDescription
eventNameThe name of the event (for example, PazeButtonClicked).
timestampThe date and time when the event occurred.
sessionIdThe session's unique identifier.
componentIdThe Paze button component's unique identifier.
merchantTransactionIdThe merchant transaction identifier from SDK initialisation.
walletTypeAlways Paze for Paze-specific events.
additionalDataPresent on all PazeAnalyticsEvent types. Populated on failure and abandonment events with error details, checkout reason, or FailedSubmitResult. Otherwise empty.

Shared lifecycle events add:

NameDescription
componentType"paze-button" for PreAuthorisation, PostAuthorisation, PazeTransactionInitiated, and cancellation events.
transactionIdThe merchant transaction identifier on lifecycle events.
isRetryWhether the lifecycle event is a retry (PreAuthorisation / PostAuthorisation only).

When each event fires

Event nameTrigger
PazeButtonRenderedPresentment validation succeeds and the button becomes visible.
PazeButtonClickedCheckout-time validation passes after the shopper taps the button, before the Paze web session opens.
PazePopupLaunchedThe Paze web checkout session opens in ASWebAuthenticationSession.
PazeCheckoutCompletedPaze checkout returns COMPLETE and merchant approves at onCheckoutComplete.
PazeCheckoutAbandonedCheckout is incomplete, the shopper cancels, or merchant validation rejects checkout.
PazeDecryptionInitiatedThe SDK begins decrypting the secured payload.
PazeDecryptionCompletedDecryption succeeds.
PazeDecryptionFailedDecryption fails.
PazeCompleteFailedThe complete API call fails.
PazeCheckoutFailedThe checkout flow fails with an error.
PazeAuthorisationFailedTransaction submission fails.
PazeSdkInitialisationFailedPresentment validation fails (button hidden).
PazeTokenDecryptionCancelledonPreDecryption returns false.
PazeAuthorisationCancelledonPreAuthorisation returns .cancel.
PazeTransactionInitiatedAuthorisation request is sent to the Unity API.
PreAuthorisationonPreAuthorisation is configured and the flow proceeds (.proceed or .transactionInitData). Returning .cancel emits PazeAuthorisationCancelled instead. componentType is "paze-button".
PostAuthorisationonPostAuthorisation is configured and the SDK receives a MerchantSubmitResult, immediately before your callback runs. componentType is "paze-button". PazeAuthorisationFailed may also fire if the response reports an error state.
ComponentErrorComponent validation fails (for example, invalid Kount risk screening data).

onPazeButtonClicked fires when the shopper taps the button. The PazeButtonClicked analytics event fires only after checkout-time validation succeeds, immediately before the Paze web session opens.

Use merchantTransactionId to correlate analytics events with server-side logs and PXP reports.

Integration examples

Firebase analytics

import FirebaseAnalytics

analyticsEvent: { event in
    if let clickEvent = event as? PazeButtonClickAnalyticsEvent {
        Analytics.logEvent("paze_button_click", parameters: [
            "component_id": clickEvent.componentId,
            "merchant_transaction_id": clickEvent.merchantTransactionId,
            "session_id": clickEvent.sessionId
        ])
    }

    if let checkoutComplete = event as? PazeCheckoutCompletedAnalyticsEvent {
        Analytics.logEvent("paze_checkout_complete", parameters: [
            "merchant_transaction_id": checkoutComplete.merchantTransactionId,
            "session_id": checkoutComplete.sessionId
        ])
    }

    if let authFailed = event as? PazeAuthorisationFailedAnalyticsEvent {
        Analytics.logEvent("paze_authorisation_failed", parameters: [
            "merchant_transaction_id": authFailed.merchantTransactionId,
            "session_id": authFailed.sessionId
        ])
    }
}

Segment

analyticsEvent: { event in
    if let clickEvent = event as? PazeButtonClickAnalyticsEvent {
        Analytics.shared().track("Paze button clicked", properties: [
            "componentId": clickEvent.componentId,
            "merchantTransactionId": clickEvent.merchantTransactionId,
            "sessionId": clickEvent.sessionId
        ])
    }

    if let checkoutComplete = event as? PazeCheckoutCompletedAnalyticsEvent {
        Analytics.shared().track("Paze checkout completed", properties: [
            "merchantTransactionId": checkoutComplete.merchantTransactionId,
            "sessionId": checkoutComplete.sessionId
        ])
    }

    if let decryptionFailed = event as? PazeDecryptionFailedAnalyticsEvent {
        Analytics.shared().track("Paze decryption failed", properties: [
            "merchantTransactionId": decryptionFailed.merchantTransactionId,
            "sessionId": decryptionFailed.sessionId
        ])
    }
}

Best practices

Conversion funnel tracking

Build a complete picture of your Paze conversion funnel by combining SDK analytics events with onPresentmentResolved:

var funnelStages: [String: Int] = [
    "buttonVisible": 0,
    "buttonRendered": 0,
    "buttonClicked": 0,
    "checkoutCompleted": 0,
    "decryptionCompleted": 0,
    "paymentAuthorised": 0
]

config.onPresentmentResolved = { isVisible in
    if isVisible { funnelStages["buttonVisible", default: 0] += 1 }
}

let checkoutConfig = CheckoutConfig(
  // ... session and transactionData
    analyticsEvent: { event in
        switch event {
        case is PazeButtonRenderedAnalyticsEvent:
            funnelStages["buttonRendered", default: 0] += 1
        case is PazeButtonClickAnalyticsEvent:
            funnelStages["buttonClicked", default: 0] += 1
        case is PazeCheckoutCompletedAnalyticsEvent:
            funnelStages["checkoutCompleted", default: 0] += 1
        case is PazeDecryptionCompletedAnalyticsEvent:
            funnelStages["decryptionCompleted", default: 0] += 1
        case let postAuth as PostAuthorisationAnalyticsEvent where postAuth.componentType == "paze-button":
            funnelStages["paymentAuthorised", default: 0] += 1
            print("Paze conversion funnel:", funnelStages)
        default:
            break
        }
    }
)

Error tracking and alerting

Track operational failures using Paze failure events and shared component errors:

let pazeButton = try pxpCheckout.create(.pazeButton, componentConfig: pazeConfig)
guard let pazeComponentId = (pazeButton as? PazeButtonComponent)?.containerId else {
    return
}

analyticsEvent: { event in
    if let componentError = event as? ComponentErrorAnalyticsEvent,
       componentError.componentId == pazeComponentId {
        trackError("paze_component_error", properties: [
            "errorCode": componentError.errorCode ?? "",
            "errorMessage": componentError.errorMessage,
            "sessionId": componentError.sessionId
        ])
    }

    switch event {
    case is PazeDecryptionFailedAnalyticsEvent,
         is PazeAuthorisationFailedAnalyticsEvent,
         is PazeSdkInitialisationFailedAnalyticsEvent,
         is PazeCheckoutFailedAnalyticsEvent,
         is PazeCompleteFailedAnalyticsEvent:
        if let pazeEvent = event as? PazeAnalyticsEvent {
            trackError("paze_flow_error", properties: [
                "eventName": pazeEvent.eventName,
                "merchantTransactionId": pazeEvent.merchantTransactionId,
                "additionalData": String(describing: pazeEvent.additionalData)
            ])
        }
    default:
        break
    }
}

PxpCheckout.create(_:componentConfig:) returns BaseComponent, which doesn't expose containerId. Cast to PazeButtonComponent, or capture componentId from the first PazeAnalyticsEvent in analyticsEvent if you prefer to avoid a cast.

The SDK also emits a generic ComponentLifecycleAnalyticsEvent with eventType: .mount for Paze when presentment validation succeeds (alongside PazeButtonRendered). Paze doesn't emit mount on first view attach if presentment hasn't completed. This is separate from PazeButtonRendered. Types such as PazeAuthorisationInitiatedAnalyticsEvent and PazeAuthorisationCompletedAnalyticsEvent exist in the SDK but aren't emitted by the Paze button component. Use PazeTransactionInitiated and PostAuthorisation instead.