Checkout lifecycle

Events: checkout.*, user.*, address.* and payment.selected, with the order's order.created and order.paid and the gateway's payment.redirected and payment.failed.

Checkout lifecycle On each checkout page. idle: the shopper fills the form; checkout.started comes once per checkout, when the cart has lines. On a multi-step form, a step whose checks fail sends checkout.invalid; one that passes sends checkout.continued and loads the next step page. A submit, or an express button, moves to placing: the cart is frozen, the form, the cart and the card are checked, then checkout.submitted is sent and the order is created. A check that fails (checkout.invalid), an order not created (sdk.error, checkout.failed) or a declined card (payment.failed) go back to idle. A created order (order.created) is placed and the page redirects: paid at once (order.paid, checkout.completed), to the next page, which loads the order; else (payment.redirected) to the gateway. A checkout page loaded after an unpaid return from the gateway sends payment.failed. a checkout page loads: the first page, a step, a reload, or back from the gateway back from the gateway unpaid payment.failed a step fails checkout.invalid a step passes checkout.continued the next step page submit, or an express button a check fails checkout.invalid order not placed sdk.error checkout.failed card declined payment.failed the order is created order.created to a gateway payment.redirected the gateway payment lifecycle paid at once order.paid checkout.completed the next page loads the order idle the shopper fills the form checkout.started once per checkout placing the cart is frozen checkout.submitted once the checks pass placed the page redirects

The lifecycle is one checkout page's. Every checkout page starts at idle: the first page, a later step, a reload, or a return from the gateway. The debug panel shows the state.

StateMeans
idleThe shopper fills in the form, and fixes what a submit pointed out
placingThe SDK checks the form, the cart and the card, then sends the order; the cart is frozen
placedThe order is created; the page redirects to the next page, or to the gateway
FromWhat happensToEvents, in order
noneA checkout page loads and binds its formidlepayment.failed when back from the gateway unpaid (payment_failed=true in the URL); else none
idleThe cart has lines, at once or when the first lines arriveidlecheckout.started, once per checkout: a step, a reload or a return from the gateway sends nothing; when lines arrive, after that change's own events
idleThe shopper fills in the formidlein any order: user.created, user.updated, address.autofilled, address.entered, address.updated, payment.selected
idleOn a step of a multi-step form (data-next-checkout-step), a submit passes the step's checksidle, on the next step's pagecheckout.continued
idleA step's submit does not pass its checksidlecheckout.invalid (with the errors)
idleOn the last page, the shopper submits, or uses an express buttonplacingnone; the cart freezes
placingA check fails: a field, an empty cart, or the cardidlecheckout.invalid (with the errors)
placingThe checks pass and the card is tokenizedplacingcheckout.submitted, then the order is sent
placingThe order is not created: refused, or the request failsidlesdk.error (order.create), checkout.failed (with error)
placingThe card is declinedidlepayment.failed (code: 'declined'); the form shows payment.errors.<decline_code>, see the payment lifecycle
placingThe order is created without a payment_complete_url: it is paid at onceplacedorder.created (paid: true), order.paid, checkout.completed; then the page redirects to the next page, which loads the order
placingThe order is created with a payment_complete_urlplacedorder.created (paid: false), payment.redirected; then the page redirects to the gateway. See the payment lifecycle

Once per checkout

  • checkout.started comes once, and the Checkout's id names the checkout: its steps, reloads and a return from a gateway keep the same id. A paid order ends it; the next checkout gets a new one.
  • The 0.4.x checkout:started still comes on each checkout page.
  • Every form event comes after checkout.started: details entered before the cart has lines are checked once the checkout starts.
  • The method the form starts with is the Checkout's payment_method; payment.selected comes only when the shopper changes it.

Express buttons

An express button (Apple Pay, Google Pay, PayPal, … in data-next-express-checkout) pays with the wallet's details:

  • The form is not checked, only that the cart has lines.
  • PayPal, Apple Pay or Google Pay picked as the payment method in the form gets the checks the 0.4.x nextConfig.paymentConfig.expressCheckout.requireValidation asks for, or the full checks when it is unset. Klarna and the other methods get the full checks, like a card.

The cart

  • Frozen while placing; unfreezes when a check fails or the order is not created.
  • A paid order empties it without cart events; checkout.completed ends the checkout.
  • While the shopper is at a gateway it is kept until the paid order loads, so a shopper whose payment fails comes back to the same cart.
  • shipping.selected is in the cart lifecycle.

The next page

  • next-success-url, with the order's ref_id.
  • Without it, an order paid at once goes to the store's order status page, where the SDK does not run: no order.loaded there, and the checkout page logs an error when its form is bound. After a gateway, the shopper goes to /success on the site.
  • After a failed payment, param.payment_failed is 'true' on the checkout, for data-next-show.

What each event carries

  • checkout.*: the Checkout, with the Cart as cart, the user, the addresses, billing_same_as_shipping and payment_method; errors on checkout.invalid, error on checkout.failed and the order's ref_id on checkout.completed.
  • user.*: the User.
  • address.*: the Address with its type; address.autofilled only the fields it filled.
  • payment.selected: the Payment.

User

User lifecycle Lead capture, once the checkout has started. There is no user until the shopper has entered what data-next-lead asks for, checked each time the shopper leaves a field they changed: by default a first and last name of at least two characters each and a valid email. Then the checkout saves them with an Open Cart and sends user.created, once per checkout. If saving fails it sends sdk.error and tries again on the next field change. After that, a change that is still valid sends user.updated and an invalid one sends nothing; the Open Cart keeps the first details, the order takes the latest. With data-next-lead off it never saves. a name and a valid email are in once the checkout has started saved save fails next change changes, still valid user.updated no user yet details not complete saving creating the Open Cart created user.created not saved sdk.error

The lifecycle is the lead's: one shopper on one checkout, saved with an Open Cart. The Checkout's user is the User from user.created on.

StateMeans
no user yetThe checkout has not started, or what data-next-lead asks for is not in
savingThe Open Cart is being created
not savedThe Open Cart was not created; the details are kept
createdThe Open Cart exists; the Checkout has the user
FromWhat happensToEvents, in order
no user yetWhat data-next-lead asks for is in: when the checkout starts, or when the shopper then leaves a field they changedsavingnone; the Open Cart is sent
savingThe store creates the Open Cartcreateduser.created
savingThe Open Cart is not created: refused, or the request failsnot savedsdk.error (user.save)
not savedThe shopper leaves the next field they changed, with the details still insavingnone; the Open Cart is sent again
createdThe details change and are still what data-next-lead asks forcreateduser.updated
createdThe details change and are notcreatednone; the Checkout keeps the last valid user
  • What data-next-lead asks for: by default a first and last name of at least two characters each and a valid email; see data-next-lead. With off, nothing is saved and no user.* comes.
  • Checked each time the shopper leaves a field they changed, or picks an option. Once per checkout: a step, a reload or a return from the gateway keeps the saved user; a paid order starts over.
  • The details are first_name, last_name, email when valid, phone once the address service read it, and accepts_marketing. The Open Cart keeps the first ones; the order takes the latest.
  • language, ip and user_agent are what the store recorded with the Open Cart, else the campaign's language and the browser's user agent, with no ip; the same on every user.updated.

Address

Address lifecycle For each type, shipping and billing while it is separate from shipping. When the form is bound the country list and the chosen country's rules load (sdk.error if they cannot: the campaign's countries, a built-in layout and simpler checks). A country change loads its rules again. With addressConfig.enableAutocomplete, two words in line 1 show suggestions; picking one sends address.autofilled and fills the fields. Fields are checked when the shopper leaves one they changed. Once the checkout is open, an address whose every required field is valid, and each optional field filled, sends address.entered, once per type per checkout. A later valid change, the name and the phone included, sends address.updated; an invalid change sends nothing and the last valid address is kept. the form is bound rules in or sdk.error: simpler checks the country changes line 1 typed picked: fields filled address.autofilled every field is valid once the checkout is open changes, still valid address.updated loading rules the countries and their fields incomplete a field is missing or wrong entered address.entered suggesting a list under line 1

The lifecycle is one address type's on one checkout: shipping, and billing while it is separate from shipping. The Checkout's shipping_address and billing_address are the Address from address.entered on.

StateMeans
loading rulesThe country list, then the country's fields, are loading; a data-next-address shows nothing
incompleteA field the country requires is missing, or a filled field fails its check
suggestingA list of addresses is open under line 1
enteredEvery field passes its check; the Checkout has the Address
FromWhat happensToEvents, in order
noneThe form is boundloading rulesnone
loading rulesThe country list and the country's rules loadincompletenone
loading rulesThe country list, or the country's rules, cannot loadincompletesdk.error (address.load_rules); the campaign's countries for the list, a built-in layout and simpler checks for the fields
incompleteThe shopper picks another countryloading rulesnone; the state is emptied and the phone read again, then the address is checked again
incompleteTwo words are in line 1, with addressConfig.enableAutocompletesuggestingnone; sdk.error (address.suggest) and no list when the lookup fails
suggestingThe list closes: Escape, a click elsewhere, or line 1 back under two wordsincompletenone
suggestingThe shopper picks a suggestionincompleteaddress.autofilled with the fields it fills; then line 1, the city, the postcode, the country and the state change
incompleteThe shopper leaves a field they changed and every field is valid, once the checkout is openenteredaddress.entered
enteredThe address changes, the name and the phone included, and is still validenteredaddress.updated
enteredThe address changes and is notenterednone; the Checkout keeps the last valid Address

The country

  • The list is the campaign's shipping countries, narrowed by the 0.4.x addressConfig.countries.
  • The country at load: the field's value; else the first listed of ?country, the shopper's location and US; else the first in the list.
  • A billing address is sent only while billing is separate from shipping; billing_same_as_shipping on the Checkout says which. Unticking it starts the billing address with the shipping country.

Suggestions

  • Only with the 0.4.x nextConfig.addressConfig.enableAutocomplete; the lookup runs 300 ms after the second word, or on focus, for the country picked (else US).
  • Picking one fills the fields through the form, so address.entered or address.updated follows once the address is valid.

The checks

  • Addresses are checked once the checkout is open on the page: the form is bound and the cart has lines. Once per type per checkout: a step, a reload or a return from the gateway keeps the saved address; a paid order starts over.
  • Leaving a field checks what is in it: its format, the phone through the address service, the postcode with the state (a doubt is a warning). Blanks come up at a submit.
  • Valid: every field the country requires is filled and passes its check, and so does each optional field the shopper filled, the phone included; the email is not part of it.
  • On one field: the phone or postcode read first, then address.*, then user.*. At checkout.started too, address.entered comes before user.created.

Errors

Each sends sdk.error with this action. The SDK lifecycle lists every action and code.

actionWhenWhat the SDK does next
user.saveThe Open Cart cannot be createdTries again on the next field change
address.load_rulesThe country list or a country's rules cannot loadFalls back to the campaign's countries and simpler checks
address.suggestAddress suggestions cannot loadShows no suggestions
order.createThe order is not created: refused, or the request failscheckout.failed; back to idle, and the cart unfreezes
order.loadThe next page cannot load the orderNo order.loaded there, nor order.paid after a gateway; the cart is kept