--- title: Monitor checkout lifecycle description: >- Register callbacks for checkout completion, cancellation, and failure. Subscribe to web pixel events for buyer analytics. source_url: html: >- https://shopify.dev/docs/storefronts/mobile/checkout-kit/monitor-checkout-lifecycle md: >- https://shopify.dev/docs/storefronts/mobile/checkout-kit/monitor-checkout-lifecycle.md --- # Monitor checkout lifecycle When a buyer completes, cancels, or encounters an error during checkout, your app needs to respond. Checkout Kit provides lifecycle callbacks to reset cart state, show order confirmation, handle failures, and forward analytics events to third-party providers. *** ## Requirements * [Checkout Kit](https://shopify.dev/docs/storefronts/mobile/checkout-kit) installed in your app. * A valid `checkoutUrl` from [Build a mobile storefront](https://shopify.dev/docs/storefronts/mobile/build-mobile-storefront) or a [cart permalink](https://shopify.dev/docs/apps/build/checkout/create-cart-permalinks). *** ## Register lifecycle callbacks Implement the delegate or event listener so your app can respond when checkout completes, fails, or the buyer cancels. The callbacks are where you reset cart state, dismiss the sheet, surface errors to the buyer, and forward web pixel events to your analytics tools. ## Register lifecycle callbacks ##### Swift ```swift extension MyViewController: CheckoutDelegate { func checkoutDidComplete(event: CheckoutCompletedEvent) { // The buyer completed checkout. // Use this to update UI and reset cart state. } func checkoutDidCancel() { // The buyer canceled checkout. // Use this to call `dismiss(animated:)`. } func checkoutDidFail(error: CheckoutError) { // Checkout encountered an error. switch error { // Internal error: exception within the Checkout SDK code. // Inspect and log the underlying Error and stacktrace to identify the problem. case .sdkError(let underlying): break // The checkout URL points to a misconfigured store. // The SDK only supports stores migrated to Shopify Extensions in checkout. case .configurationError(let message): break // Network or server error prevented checkout from loading. case .checkoutUnavailable(let message): break // The checkout session for this URL has expired. case .checkoutExpired(let message): break } } func checkoutDidClickLink(url: URL) { // The buyer tapped a link in checkout (mailto:, tel:, or http:). // Open the URL in the appropriate handler. } func checkoutDidEmitWebPixelEvent(event: PixelEvent) { switch event { case .standardEvent(let standardEvent): recordAnalyticsEvent(standardEvent) case .customEvent(let customEvent): recordAnalyticsEvent(customEvent) } } } ``` ##### Swift (SwiftUI) ```swift CheckoutSheet(checkout: url) .colorScheme(.automatic) .onComplete { event in print("Order ID: \(event.orderDetails.id)") CartManager.shared.resetCart() showCheckoutSheet = false } .onCancel { showCheckoutSheet = false } .onFail { error in handleCheckoutError(error) showCheckoutSheet = false } .onLinkClick { url in openURL(url) } .onPixelEvent { event in if hasPermissionToTrack { sendEventToAnalytics(event) } } ``` ##### Kotlin ```kotlin val processor = object : DefaultCheckoutEventProcessor(activity) { override fun onCheckoutCompleted(checkoutCompletedEvent: CheckoutCompletedEvent) { // The buyer completed checkout. // Use this to update UI and reset cart state. } override fun onCheckoutCanceled() { // The buyer canceled checkout. } override fun onCheckoutFailed(error: CheckoutException) { // Checkout encountered an error. } override fun onCheckoutLinkClicked(uri: Uri) { // The buyer tapped a link in checkout (mailto:, tel:, http:, or a deep link). // Open the URI in the appropriate handler. } override fun onWebPixelEvent(event: PixelEvent) { // Called when a web pixel event is emitted in checkout. // Use this to submit events to your analytics system. } } ``` ##### React Native ```javascript const shopifyCheckout = useShopifyCheckoutSheet(); useEffect(() => { const close = shopifyCheckout.addEventListener('close', () => { // Do something on checkout close }); const completed = shopifyCheckout.addEventListener( 'completed', (event) => { // Lookup order on checkout completion const orderId = event.orderDetails.id; }, ); const error = shopifyCheckout.addEventListener( 'error', (error) => { // Do something on checkout error }, ); const pixel = shopifyCheckout.addEventListener( 'pixel', (event) => { // Dispatch web pixel events to third-party services if (hasPermissionToTrack) { sendEventToAnalyticsProvider(event); } }, ); return () => { close?.remove(); completed?.remove(); error?.remove(); pixel?.remove(); }; }, [shopifyCheckout]); ``` **Note:** The cancel event fires when the buyer closes the checkout, whether or not they completed the purchase. Listen for the completed event to determine checkout success before resetting cart state. *** ## Handle file uploads, geolocation, and permissions on Android iOS and React Native handle file uploads, geolocation, and permissions automatically. On Android, you implement them through `DefaultCheckoutEventProcessor` callbacks: ## Android-specific callbacks ```kotlin override fun onShowFileChooser( webView: WebView, filePathCallback: ValueCallback>, fileChooserParams: FileChooserParams, ): Boolean { // Handle HTML file input elements in checkout. // To cancel, call filePathCallback.onReceiveValue(null) and return true. } override fun onGeolocationPermissionsShowPrompt( origin: String, callback: GeolocationPermissions.Callback ) { // Handle geolocation requests, for example "Use my location" for pickup points. } override fun onGeolocationPermissionsHidePrompt() { // Dismiss the geolocation permissions prompt. } override fun onPermissionRequest(permissionRequest: PermissionRequest) { // Handle permission requests from the checkout WebView, such as camera or microphone access. } ``` **Caution:** On Android 11+, deep links require a `queries` element in your `AndroidManifest.xml` declaring which apps your app interacts with. Without it, `onCheckoutLinkClicked` might not resolve external URLs. See the [Android queries documentation](https://developer.android.com/guide/topics/manifest/queries-element). *** ## Integrate with web pixels [Web pixels](https://shopify.dev/docs/apps/build/marketing-analytics/pixels) are Shopify's analytics event system. Checkout Kit relays [standard](https://shopify.dev/docs/api/web-pixels-api/standard-events) and [custom](https://shopify.dev/docs/api/web-pixels-api/emitting-data) web pixel events through the lifecycle callbacks. You can forward these events to your analytics provider to track checkout behavior. Forward these events only with the buyer's consent and in line with the store's privacy policy. Check Apple's [App Store Review Guidelines](https://developer.apple.com/app-store/review/guidelines/) and [Google Play's User Data policy](https://support.google.com/googleplay/android-developer/answer/10144311) for the markets you operate in: ## Integrate with web pixels ##### Swift ```swift extension MyViewController: CheckoutDelegate { func checkoutDidEmitWebPixelEvent(event: PixelEvent) { guard hasPermissionToCaptureEvents() else { return } switch event { case .standardEvent(let standardEvent): sendEventToAnalytics(event: standardEvent) case .customEvent(let customEvent): sendEventToAnalytics(event: customEvent) } } } ``` ##### Kotlin ```kotlin fun onWebPixelEvent(event: PixelEvent) { if (!hasPermissionToCaptureEvents()) { return } when (event) { is StandardPixelEvent -> processStandardEvent(event) is CustomPixelEvent -> processCustomEvent(event) } } fun processStandardEvent(event: StandardPixelEvent) { val endpoint = "https://example.com/pixel?id=${accountID}&uid=${userId}" val payload = AnalyticsPayload( eventTime = event.timestamp, action = event.name, details = event.data.checkout ) // Send events to third-party servers httpClient.post(endpoint, payload) } ``` For React Native, the `pixel` listener registered in [Register lifecycle callbacks](#register-lifecycle-callbacks) already gates forwarding behind a consent flag. Reuse that listener and route events to your analytics provider from the same callback. Checkout Kit returns the `customData` attribute of a `CustomPixelEvent` as a string because the data structure varies by web pixel implementation. Define a custom data type in your app and deserialize the `customData` string into that type. *** ## Next steps [Configure checkout branding\ \ ](https://shopify.dev/docs/storefronts/mobile/checkout-kit/configuration) [Customize the checkout color scheme and title to match your app.](https://shopify.dev/docs/storefronts/mobile/checkout-kit/configuration) [Authenticate checkouts\ \ ](https://shopify.dev/docs/storefronts/mobile/checkout-kit/authenticate-checkouts) [Sign buyers in to prefill checkout with saved addresses and payment methods.](https://shopify.dev/docs/storefronts/mobile/checkout-kit/authenticate-checkouts) [Accelerated checkouts\ \ ](https://shopify.dev/docs/storefronts/mobile/checkout-kit/accelerated-checkouts-overview) [Add Shop Pay and Apple Pay buttons for one-tap purchases on product and cart pages.](https://shopify.dev/docs/storefronts/mobile/checkout-kit/accelerated-checkouts-overview) ***