data-ef-package attributes; the checkout does the rest.
When the buyer picks a row:
- the checkout’s main product becomes that package (
checkout.product_code,product_title,product_price,retail_price, the cart line and every total); - ticked order bumps stay ticked;
- bonus rules, coupon eligibility, tax, shipping and the Apple Pay / Google Pay amount are recalculated for the new package;
- the address bar gets
?p=<code>(no new history entry), so a reload keeps the choice; - the card submit, PayPal and Klarna all charge the package the buyer picked.
Copy-paste example
Three bundles of one product,WRAP-1, WRAP-2 and WRAP-4. Each row is a <label> with a radio input, so it works with a keyboard and a screen reader without extra code.
Attributes
The price attributes are optional. With them, the switch is instant and makes no request. When a row has no price, the checkout fetches the package prices once from the products API and the switch waits for that answer. Either way, the server prices the order from the product code, so a wrong attribute can never change what the buyer is charged, only what the page shows.
The
data-ef-product-* spellings used on add-to-cart buttons (data-ef-product-price, data-ef-product-name, …) are read too.Selected state
On every row the runtime keeps these in step:data-selected="true"or"false"aria-checked="true"or"false"(androle="radio"on rows that are not inputs)- the class
is-selected checkedon the row’s radio input
tabindex="0", so Tab then Space or Enter picks a row.
Links as rows
A row can be a buy link, for example<a href="[BUY=WRAP-2]" data-ef-package="WRAP-2">. The link is the fallback for a browser without JavaScript. With JavaScript, a click picks the package and never follows the link, and it is not recorded as a buy-link click.
Product-code mode and cart mode
A checkout sells either one product (from?p=<code> or from the page’s backend script) or a cart. The selector works in both.
A checkout that sells nothing yet (no
?p=, empty cart) picks the default row and runs in product-code mode.
Pages that set their product in a backend script
A page whose backend script setscheckout_product pins that product to the session, and the submit charges the pin, whatever the browser posts. List the packages too, or the buyer’s pick is ignored at payment:
checkout_packages set, a posted code from that list is charged, ?p= naming one of them is rendered on reload, and any other posted code still falls back to checkout_product. See How to design a checkout page.
Order bumps
Bumps the page offers stay offered, and ticked bumps stay ticked, across a switch. One exception: a bump whose product code is the package the buyer just picked is taken out ofcheckout.bump_products (it would sell the same product twice) and comes back when the buyer picks another package.
Events and API
checkout:packageChanged fires on every switch the buyer makes, not when the page loads. Each switch is also recorded in analytics as a package-selected event with the picked code.
From your own scripts: