Customer Cart and Checkout Hooks
The twenty-nine placement points from the catalogue to the completed order.
Overview
The placement points along the customer purchase path live here: the catalogue, the product detail, configuration, the basket, checkout and the completed order.
Everything you add along this path stands in front of a buying decision. A slow script at the payment step turns directly into orders that never complete; put tracking code on the completion page.
Reference
Above the plan list
Appears above the plan cards on the catalogue page.
null and false are skipped, so return null when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.Hook::add('ui:client.catalog.plans.before', 10, function () {
return '<div class="alert alert-info">Acme</div>';
});Below the plan list
Appears below the plan cards.
null and false are skipped, so return null when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.Hook::add('ui:client.catalog.plans.after', 10, function () {
return '<div class="alert alert-info">Acme</div>';
});The foot of a plan card
Appears at the foot of every plan card, separately. The card itself is not passed: you cannot tell which plan it is from here.
null and false are skipped, so return null when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.Hook::add('ui:client.plan_card.footer', 10, function () {
return '<div class="alert alert-info">Acme</div>';
});After the product gallery
Appears after the image area on the product detail.
null and false are skipped, so return null when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.Hook::add('ui:client.product_detail.gallery.after', 10, function () {
return '<div class="alert alert-info">Acme</div>';
});Above the purchase box
Appears above the price and the purchase button.
null and false are skipped, so return null when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.Hook::add('ui:client.product_detail.purchase.before', 10, function () {
return '<div class="alert alert-info">Acme</div>';
});Below the purchase box
Appears below the purchase button. It suits a reassuring note or an extra condition.
null and false are skipped, so return null when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.Hook::add('ui:client.product_detail.purchase.after', 10, function () {
return '<div class="alert alert-info">Acme</div>';
});The end of the product tabs
Appears at the end of the tab bar on the product detail.
null and false are skipped, so return null when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.Hook::add('ui:client.product_detail.tabs.end', 10, function () {
return '<div class="alert alert-info">Acme</div>';
});After the software store grid
Appears after the cards in the software store.
null and false are skipped, so return null when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.Hook::add('ui:client.software_store.grid.after', 10, function () {
return '<div class="alert alert-info">Acme</div>';
});After the add-on page
Appears after the content of the add-on purchase page.
null and false are skipped, so return null when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.Hook::add('ui:client.addon_page.after', 10, function () {
return '<div class="alert alert-info">Acme</div>';
});After the configuration sections
Appears after the sections in the order configuration step.
null and false are skipped, so return null when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.Hook::add('ui:client.configure.sections.after', 10, function () {
return '<div class="alert alert-info">Acme</div>';
});After the configuration add-ons
Appears after the add-on selection in the configuration step.
null and false are skipped, so return null when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.Hook::add('ui:client.configure.addons.after', 10, function () {
return '<div class="alert alert-info">Acme</div>';
});The bottom of the configuration summary
Appears below the price summary in the configuration step.
null and false are skipped, so return null when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.Hook::add('ui:client.configure.summary.bottom', 10, function () {
return '<div class="alert alert-info">Acme</div>';
});Above the basket items
Appears above the items in the basket.
null and false are skipped, so return null when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.Hook::add('ui:client.cart.items.top', 10, function () {
return '<div class="alert alert-info">Acme</div>';
});The bottom of the basket summary
Appears below the basket total summary.
null and false are skipped, so return null when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.Hook::add('ui:client.cart.summary.bottom', 10, function () {
return '<div class="alert alert-info">Acme</div>';
});After the empty basket message
Appears after the message shown when the basket is empty. It runs only when the basket is empty, which makes it right for a suggestion area.
null and false are skipped, so return null when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.Hook::add('ui:client.cart.empty.after', 10, function () {
return '<div class="alert alert-info">Acme</div>';
});The end of the checkout header
Appears at the end of the header area in the checkout step.
null and false are skipped, so return null when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.Hook::add('ui:client.checkout.header.end', 10, function () {
return '<div class="alert alert-info">Acme</div>';
});After the billing details
Appears after the billing address section.
null and false are skipped, so return null when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.Hook::add('ui:client.checkout.billing.after', 10, function () {
return '<div class="alert alert-info">Acme</div>';
});After the payment methods
Appears after the payment method choice.
null and false are skipped, so return null when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.Hook::add('ui:client.checkout.methods.after', 10, function () {
return '<div class="alert alert-info">Acme</div>';
});Above the saved cards
Appears above the list of saved cards.
null and false are skipped, so return null when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.Hook::add('ui:client.checkout.cards.top', 10, function () {
return '<div class="alert alert-info">Acme</div>';
});After the terms box
Appears after the terms checkbox. If you add a consent of your own, you must enforce it yourself: the core only knows its own box.
null and false are skipped, so return null when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.Hook::add('ui:client.checkout.terms.after', 10, function () {
return '<div class="alert alert-info">Acme</div>';
});The bottom of the checkout summary
Appears below the total summary in the checkout step.
null and false are skipped, so return null when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.Hook::add('ui:client.checkout.summary.bottom', 10, function () {
return '<div class="alert alert-info">Acme</div>';
});Before the payment step
Appears immediately before the payment begins. It suits a final warning.
null and false are skipped, so return null when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.Hook::add('ui:client.checkout.payment.before', 10, function () {
return '<div class="alert alert-info">Acme</div>';
});The end of the checkout footer
Appears in the footer of the checkout step.
null and false are skipped, so return null when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.Hook::add('ui:client.checkout.footer.end', 10, function () {
return '<div class="alert alert-info">Acme</div>';
});The top of the payment page
Appears at the very top of the payment page.
null and false are skipped, so return null when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.Hook::add('ui:client.pay.body.top', 10, function () {
return '<div class="alert alert-info">Acme</div>';
});The bottom of the payment page
Appears at the very bottom of the payment page.
null and false are skipped, so return null when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.Hook::add('ui:client.pay.body.bottom', 10, function () {
return '<div class="alert alert-info">Acme</div>';
});After the card form
Appears after the card details form. This area handles card data: remember that a script you add here can reach those fields.
null and false are skipped, so return null when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.Hook::add('ui:client.pay.card.after', 10, function () {
return '<div class="alert alert-info">Acme</div>';
});After the paid notice
Appears after the payment confirmation on the order complete page.
null and false are skipped, so return null when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.Hook::add('ui:client.order_complete.paid.after', 10, function () {
return '<div class="alert alert-info">Acme</div>';
});The end of the order summary
Appears at the end of the summary details of the completed order.
null and false are skipped, so return null when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.Hook::add('ui:client.order_complete.paid.details.end', 10, function () {
return '<div class="alert alert-info">Acme</div>';
});The bottom of the complete page
Appears at the very bottom of the order complete page. The right place for conversion tracking.
null and false are skipped, so return null when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.Hook::add('ui:client.order_complete.body.bottom', 10, function () {
return '<div class="alert alert-info">Acme</div>';
});Pitfalls
Put your own consent box at the terms point and the core never checks whether it is ticked: the order completes with the box empty. You must enforce it on your side.
A script at the payment step that calls an outside service makes the customer wait before they pay. Move work like conversion tracking to the order completion page, where waiting costs nothing.
Related Articles
- Customer Site Hooks
- Order Hooks
- Support Ticket Hooks
Thanks for your feedback!
Our support team is here around the clock for anything you can't find above.