Buyer Journey API
The Buyer Journey API lets your extension intercept and validate the buyer's progress through checkout. Use this API to block checkout navigation with targeted error messages, check the current journey step, and enforce custom validation rules.
To block the buyer journey, you must declare the block_progress capability in your extension's shopify.extension.toml configuration.
To block the buyer journey, you must declare the block_progress capability in your extension's shopify.extension.toml configuration.
Anchor to Use casesUse cases
- Validate a checkout field: Intercept progress and display an error underneath a specific field, such as the shipping country.
- Block progress at the page level: Prevent the buyer from continuing and show a page-level error when a condition isn't met.
- Enforce item quantity limits: Block progress from a cart line item extension when a product exceeds its purchase limit.
Supported targets
- purchase.
checkout. actions. render-before - purchase.
checkout. block. render - purchase.
checkout. cart-line-item. render-after - purchase.
checkout. cart-line-list. render-after - purchase.
checkout. chat. render - purchase.
checkout. contact. render-after - purchase.
checkout. delivery-address. render-after - purchase.
checkout. delivery-address. render-before - purchase.
checkout. footer. render-after - purchase.
checkout. header. render-after - purchase.
checkout. payment-method-list. render-after - purchase.
checkout. payment-method-list. render-before - purchase.
checkout. pickup-location-list. render-after - purchase.
checkout. pickup-location-list. render-before - purchase.
checkout. pickup-location-option-item. render-after - purchase.
checkout. pickup-point-list. render-after - purchase.
checkout. pickup-point-list. render-before - purchase.
checkout. reductions. render-after - purchase.
checkout. reductions. render-before - purchase.
checkout. shipping-option-item. details. render - purchase.
checkout. shipping-option-item. render-after - purchase.
checkout. shipping-option-list. render-after - purchase.
checkout. shipping-option-list. render-before - purchase.
thank-you. announcement. render - purchase.
thank-you. block. render - purchase.
thank-you. cart-line-item. render-after - purchase.
thank-you. cart-line-list. render-after - purchase.
thank-you. chat. render - purchase.
thank-you. customer-information. render-after - purchase.
thank-you. footer. render-after - purchase.
thank-you. header. render-after
Supported targets
- purchase.
checkout. actions. render-before - purchase.
checkout. block. render - purchase.
checkout. cart-line-item. render-after - purchase.
checkout. cart-line-list. render-after - purchase.
checkout. chat. render - purchase.
checkout. contact. render-after - purchase.
checkout. delivery-address. render-after - purchase.
checkout. delivery-address. render-before - purchase.
checkout. footer. render-after - purchase.
checkout. header. render-after - purchase.
checkout. payment-method-list. render-after - purchase.
checkout. payment-method-list. render-before - purchase.
checkout. pickup-location-list. render-after - purchase.
checkout. pickup-location-list. render-before - purchase.
checkout. pickup-location-option-item. render-after - purchase.
checkout. pickup-point-list. render-after - purchase.
checkout. pickup-point-list. render-before - purchase.
checkout. reductions. render-after - purchase.
checkout. reductions. render-before - purchase.
checkout. shipping-option-item. details. render - purchase.
checkout. shipping-option-item. render-after - purchase.
checkout. shipping-option-list. render-after - purchase.
checkout. shipping-option-list. render-before - purchase.
thank-you. announcement. render - purchase.
thank-you. block. render - purchase.
thank-you. cart-line-item. render-after - purchase.
thank-you. cart-line-list. render-after - purchase.
thank-you. chat. render - purchase.
thank-you. customer-information. render-after - purchase.
thank-you. footer. render-after - purchase.
thank-you. header. render-after
Anchor to PropertiesProperties
The shopify global object provides buyer journey data for the current checkout. Access the following properties on shopify to read journey state and intercept navigation. Available to purchase extension targets.
- Anchor to buyerJourneybuyerJourneybuyerJourneyBuyerJourneyBuyerJourneyrequiredrequired
Provides details on the buyer's progression through the checkout and lets you intercept navigation to validate data before the buyer continues.
Refer to buyer journey examples for more information.
BuyerJourney
Provides details on the buyer's progression through the checkout.
- activeStep
The step of checkout the buyer is currently on. The value is `undefined` if the current step can't be determined.
SubscribableSignalLike<BuyerJourneyStepReference | undefined> - completed
Whether the buyer has completed submitting their order. When `true`, the buyer is on the order status page after submitting payment. When `false`, the buyer is still in the checkout flow.
SubscribableSignalLike<boolean> - intercept
Installs a function for intercepting and preventing progress on checkout. This returns a promise that resolves to a teardown function. Calling the teardown function removes the interceptor. To block checkout progress, you must set the [block_progress](/docs/api/checkout-ui-extensions/latest/configuration#block-progress) capability in your extension's configuration. If you do, then you're expected to inform the buyer why navigation was blocked, either by passing validation errors to the checkout UI or rendering the errors in your extension. If the merchant hasn't allowed your extension to block checkout progress, show a warning in the [checkout editor](/docs/apps/build/checkout/test-checkout-ui-extensions#test-the-extension-in-the-checkout-editor).
(interceptor: Interceptor) => Promise<() => void> - steps
All possible steps the buyer can take to complete checkout. These steps vary depending on whether the checkout is one-page or three-page, and on the shop's configuration.
SubscribableSignalLike<BuyerJourneyStep[]>
SubscribableSignalLike
Represents a reactive signal interface that provides both immediate value access and subscription-based updates. Enables real-time synchronization with changing data through the observer pattern. This interface extends `ReadonlySignalLike` with deprecated fields that are still supported for backwards compatibility.
- current
The current value of the signal. Equivalent to `.value`, accessing this property subscribes to changes when used in a reactive context.
T - destroy
Cleans up the subscription and releases any resources held by this signal. After calling `destroy()`, the signal stops receiving updates from the main thread.
() => Promise<void> - subscribe
Subscribes to value changes and calls the provided function whenever the value updates. Returns an unsubscribe function to clean up the subscription. Use to automatically react to changes in the signal's value.
(fn: (value: T) => void) => () => void - value
The current value of the signal. This property provides immediate access to the current value without requiring subscription setup. Use for one-time value checks or initial setup.
T
BuyerJourneyStepReference
What step of checkout the buyer is currently on.
- handle
The handle identifying which step the buyer is on, such as `'information'`, `'shipping'`, or `'payment'`. See `BuyerJourneyStepHandle` for all values.
BuyerJourneyStepHandle
BuyerJourneyStepHandle
| handle | Description | |---|---| | `cart` | The cart page. | | `checkout` | A one-page checkout, including Shop Pay. | | `information` | The contact information step of a three-page checkout. | | `shipping` | The shipping step of a three-page checkout. | | `payment` | The payment step of a three-page checkout. | | `review` | The step after payment where the buyer confirms the purchase. Not all shops are configured to have a review step. | | `thank-you` | The page displayed after the purchase, thanking the buyer. | | `unknown` | An unknown step in the buyer journey. |
'cart' | 'checkout' | 'information' | 'shipping' | 'payment' | 'review' | 'thank-you' | 'unknown'Interceptor
A function for intercepting and preventing navigation on checkout. You can block navigation by returning an object with `{behavior: 'block', reason: 'your reason here', errors?: ValidationError[]}`. If you do, then you're expected to also update some part of your UI to reflect the reason why navigation was blocked, either by targeting checkout UI fields, passing errors to the page level, or rendering the errors in your extension.
- interceptorProps
InterceptorProps
InterceptorRequest | Promise<InterceptorRequest>InterceptorProps
- canBlockProgress
Whether the interceptor can block the buyer's progress through checkout. When `true`, the merchant has granted your extension the `block_progress` capability. When `false`, you can still validate but can't prevent the buyer from continuing.
boolean
InterceptorRequest
InterceptorRequestAllow | InterceptorRequestBlockInterceptorRequestAllow
- behavior
Indicates that the interceptor allows the buyer's journey to continue.
'allow' - perform
This callback is called when all interceptors finish. We recommend setting errors or reasons for blocking at this stage, so that all the errors in the UI show up at once. Runs after all intercept results are collected. Use it for local state updates such as setting an error flag. By the time it runs, the navigation decision is final, so blocking logic belongs in the intercept handler itself, not here.
(result: InterceptorResult) => void | Promise<void>
InterceptorResult
InterceptorResultAllow | InterceptorResultBlockInterceptorResultAllow
- behavior
Indicates that the buyer was allowed to progress through checkout.
'allow'
InterceptorResultBlock
- behavior
Indicates that some part of the checkout UI intercepted and prevented the buyer's progress. The buyer typically needs to take some action to resolve this issue and to move on to the next step.
'block'
InterceptorRequestBlock
- behavior
Indicates that the interceptor blocks the buyer's journey from continuing.
'block' - errors
Used to pass errors to the checkout UI, outside your extension's UI boundaries.
ValidationError[] - perform
This callback is called when all interceptors finish. We recommend setting errors or reasons for blocking at this stage, so that all the errors in the UI show up at once. Runs after all intercept results are collected. Use it for local state updates such as setting an error flag. By the time it runs, the navigation decision is final, so blocking logic belongs in the intercept handler itself, not here.
(result: InterceptorResult) => void | Promise<void> - reason
The reason for blocking the interceptor request. This value isn't presented to the buyer, so it doesn't need to be localized. The value is used only for Shopify's own internal debugging and metrics.
string
ValidationError
A validation error object that is returned when an operation fails.
- code
A code identifier for the error.
string - issues
Field-level validation issues
{ message: string; path: string[]; }[] - message
A message describing the error.
string - type
'error'
BuyerJourneyStep
- disabled
Whether this step is disabled. When `true`, the buyer hasn't reached this step yet and can't navigate to it. When `false`, the step is accessible. For example, if the buyer hasn't reached the `shipping` step yet, then `shipping` is disabled.
boolean - handle
The handle that uniquely identifies the buyer journey step, such as `'information'`, `'shipping'`, or `'payment'`.
BuyerJourneyStepHandle - label
The localized label of the buyer journey step, suitable for rendering in navigation UI.
string - to
The URL of the buyer journey step, using the `shopify:` protocol.
string
Anchor to Available Preact hooksAvailable Preact hooks
The following Preact hooks provide a convenience wrapper that makes it easier to perform common tasks without writing your own logic.
Installs a function for intercepting and preventing progress on checkout. To block checkout progress, you must set the capability in your extension's configuration. If you do, then you're expected to inform the buyer why navigation was blocked, either by passing validation errors to the checkout UI or rendering the errors in your extension. should be called at the top level of the extension, not within an embedded or child component, to avoid errors should the child component get destroyed. It is good practice to show a warning in the checkout and accounts editor when the merchant has not given permission for your extension to block checkout progress.
- Anchor to interceptorinterceptorinterceptorInterceptorInterceptorrequiredrequired
Anchor to useBuyerJourneyIntercept-returnsReturnsvoidvoid
Anchor to Best practicesBest practices
- Always check
canBlockProgress: ThecanBlockProgressparameter passed to your intercept callback indicates whether blocking is currently allowed. Respect this flag to avoid unexpected behavior. - Target specific fields when possible: Use the
targetproperty in error objects to surface errors directly underneath the relevant field, rather than displaying a page-level error. Refer to thetargetproperty above for information on the correct path syntax. - Use page-level errors only for cart-wide issues: Omit the
targetproperty when the error applies to the entire checkout rather than a specific field, such as an unmet order minimum or a missing cart-level requirement. - Warn about misconfigured capabilities in the editor: Check
useExtensionCapability('block_progress')andshopify.extension.editorto display a warning banner when the capability isn't enabled in the checkout and accounts editor.
Anchor to LimitationsLimitations
- Validation errors are cleared automatically when the buyer retries. Your extension can't persist errors across navigation attempts.