How events work
- Web
- Android
- iOS
Primer Checkout components dispatch
CustomEvent objects. Every Primer event is created with bubbles: true and composed: true, which means events propagate up through shadow DOM boundaries and can be caught at any ancestor element, including document. This design gives you two choices for where to listen, covered in the next section.Choosing where to listen
Each platform has its own mechanism for receiving SDK events and state changes.- Web
- Android
- iOS
- Component Level
- Document Level
Attach listeners directly to the Choose this when:
<primer-checkout> element. Each listener is scoped to a single checkout instance.- You want to co-locate event logic with the component that owns it, such as inside a framework component’s lifecycle hook.
- You need to tear down listeners cleanly when a checkout is removed from the DOM.
Ensuring the component exists
When using component-level listeners, make sure the element is in the DOM before attaching them. If your checkout renders dynamically (through a router transition, a conditional template, or lazy loading), the element may not exist at script-execution time.useEffect, Vue’s onMounted, etc.), prefer that over DOMContentLoaded.Phase 1: Initialization
Every Primer Checkout integration begins with initialization. The SDK must fully initialize before you can pre-fill form fields or call SDK methods.- Web
- Android
- iOS
The
primer:ready event fires once after the SDK has fully initialized. It delivers the PrimerJS instance as event.detail.Phase 2: Payment method discovery
Shortly after initialization, the SDK provides information about available payment methods for the current session.- Web
- Android
- iOS
The SDK dispatches If you’re building a fully custom payment method layout (headless), you’ll also iterate over the methods to create
primer:methods-update with the list of payment methods available for the current session. This event fires once on load and may fire again if the session changes (e.g. after calling primer.refreshSession() in response to a cart update).You should use this event when you want to build a custom payment method selector, conditionally render UI based on what’s available, or route users to a specific method.<primer-payment-method> elements dynamically. The Headless Vault Guide covers that pattern in detail.Phase 3: User interaction
As the user fills in payment details, the SDK provides real-time feedback.Showing the Card Network
- Web
- Android
- iOS
primer:bin-data-available fires as the user types their card number. It provides the detected card network, co-badged network alternatives, and additional BIN data such as issuer information when available. Use it to display the correct card brand logo, show a co-badge network picker, or adjust UI based on card attributes.primer:bin-data-loading-change:
primer:bin-data-available replaces the older primer:card-network-change event with a richer payload that includes issuer details and card attributes. See the Events Reference for the full payload shape.Triggering Submission from a Custom Button
- Web
- Android
- iOS
If you’re using your own “Pay” button instead of the built-in one, dispatch For vault payment submission from a custom button, dispatch
primer:card-submit to tell the SDK to validate and submit the card form.primer:vault-submit in the same way. See the Events Reference and Triggerable Events for the full list of events you can dispatch.Phase 4: Payment processing and outcome
Once the user submits, the SDK moves through a processing to outcome sequence.- Web
- Android
- iOS
The
primer:state-change event fires at every step, giving you a single stream to drive your UI state.State change vs. outcome events
primer:state-change fires multiple times during a single payment. The outcome events (primer:payment-success, primer:payment-failure) fire exactly once at the end. Use primer:state-change for continuous UI updates (spinners, button states, progress indicators). Use the outcome events for final actions (redirects, confirmations, server notifications).
Event timing
Events may fire multiple times during a single checkout session (for example, if the user retries after a failure).- Web
- Android
- iOS
primer:state-changefires at every step — use it for continuous UI updates (spinners, button states)primer:payment-successandprimer:payment-failurefire exactly once at the end — use them for final actions
Dismissal and session refresh
- Web
- Android
- iOS
Call
primer.refreshSession() to sync the client-side SDK with your server session after a cart change. The SDK will re-dispatch primer:methods-update with the updated method list.Intercepting payments with primer:payment-start
Sometimes you need to run a check after the user clicks “Pay” but before the payment is created — for example, confirming terms-of-service acceptance, validating inventory, or applying a last-second promotion code.- Web
- Android
- iOS
The
primer:payment-start event gives you that interception point.continuePaymentCreation accepts an optional { idempotencyKey } parameter. When provided, this key is sent with the payment request to prevent duplicate payments from being created. See the Events Reference for the full type definition.
Working with Vaulted Payment Methods
If your integration supports saved (vaulted) payment methods, additional events become relevant.- Web
- Android
- iOS
primer:vault-methods-update— fires when vaulted payment methods are loaded or when the vault state changes. Use it to render saved cards, show a “Pay with saved card” section, or determine whether CVV re-entry is required.primer:vault-selection-change— fires when the user selects or deselects a saved method. Use it to enable or disable your submit button, or to toggle between “pay with saved card” and “pay with new card” views.
primer.vault.createCvvInput(), primer.vault.startPayment(), and primer.vault.delete() see the Headless Vault Guide.Event flow overview
The following diagram shows the typical sequence of events in a successful card payment, from initialization through confirmation.Debugging tips
- Web
- Android
- iOS
- Events not firing? Confirm the
<primer-checkout>element is in the DOM before you add listeners. In SPAs, race conditions between route rendering and listener attachment are the most common cause. - Shadow DOM boundary issues? Triggerable events (
primer:card-submit,primer:vault-submit) must be dispatched withbubbles: trueandcomposed: trueor they won’t reach the internal form component. - Stale data after a cart change? Call
primer.refreshSession()to sync the client-side SDK with your server session. The SDK will re-dispatchprimer:methods-updatewith the updated method list.
See also
Web events reference
Every Web event name, payload type, callback signature, and instance method
Android SDK reference
Android SDK API documentation
Recipes
Use-case driven examples for common integration scenarios
Error handling
Deep dive into error handling, retries, and failure recovery