PHP actions
Every action CartPops V2 fires, where each drawer position sits in the markup, and how to use them safely.
CartPops V2 fires one lifecycle action and 18 drawer position actions. All of them take no arguments, and they work the same in Free and Pro.
How the drawer actions behave
- They fire during the server render of the Cart Drawer block. The block renders once per page, so each position fires once per page load.
- They do not run again when the cart changes. The drawer updates in the browser after the first render. Your callback is not called again when a shopper adds an item, applies a coupon or removes a line. Print static markup, not cart-dependent markup.
- You own the output. Escape everything, print balanced HTML, and keep it accessible. Do not add
data-wp-*directives or change the dialog’s attributes. - Your markup is not styled by your theme. Inside the drawer panel, CartPops resets inherited styles, so theme and page builder rules do not reach your elements. Give your elements a class and style them in Custom CSS.
- CartPops’ own sections are not hooked on these actions. You cannot use priority to place something between the native header, items and totals. The positions below are the complete contract.
cartpops_loaded
Fires on plugins_loaded, after CartPops has initialized. Use it to register your own hooks that depend on CartPops being ready.
It does not fire when WooCommerce is not active. It also does not fire when the Free and Pro editions are both active, because CartPops pauses itself in that case.
add_action( 'cartpops_loaded', static function (): void {
// CartPops is ready. Register your integration here.
add_action( 'cartpops_drawer_footer_after', 'my_prefix_print_returns_note' );
} );
Drawer positions
The table lists the positions from the outside of the drawer to the inside, in the order they run.
| Action | Where it fires |
|---|---|
cartpops_drawer_wrapper_start |
First child of the drawer’s outer wrapper, before the overlay and the panel. This is outside the dialog and stays visible when the drawer is closed. |
cartpops_drawer_panel_wrapper_start |
First child of the drawer dialog, before the header. |
cartpops_drawer_header_before |
Inside the header, before the title and the close button. |
cartpops_drawer_header_after |
Inside the header, after the title and the close button. |
cartpops_drawer_content |
At the start of the scrollable content area, before CartPops’ notifications, shipping meter, items, empty-cart message, recommendations and totals. |
cartpops_drawer_footer_before |
First thing inside the footer. |
cartpops_drawer_footer_content |
In the footer, after cartpops_drawer_footer_before and before CartPops’ add-ons, coupon field, totals and checkout button. |
cartpops_drawer_coupon_wrapper_start |
Just before the coupon block. Only fires when Show coupon code field is on (Drawer screen). |
cartpops_drawer_coupon_form_before |
Inside the coupon block, before its title and form. Same condition. |
cartpops_drawer_coupon_form_after |
Inside the coupon block, after the form and before the applied-coupon tags. Same condition. |
cartpops_drawer_coupon_wrapper_end |
Just after the coupon block. Same condition. |
cartpops_drawer_before_checkout_button |
Just before the checkout link. |
cartpops_drawer_after_checkout_button |
Just after the checkout link. |
cartpops_drawer_before_secondary_checkout_button |
After the checkout link, before the optional Pro secondary action. Fires even when there is no secondary action. |
cartpops_drawer_after_secondary_checkout_button |
After the optional secondary action, before the small View Cart link. Fires even when there is no secondary action. |
cartpops_drawer_footer_after |
Last thing inside the footer, after the View Cart link and the Powered by link. |
cartpops_drawer_panel_wrapper_end |
Last child of the drawer dialog, after the footer. |
cartpops_drawer_wrapper_end |
Last child of the outer wrapper, after the dialog and the screen reader live region. Like the start position, it is outside the dialog and stays visible when the drawer is closed. |
The footer and an empty cart
The footer is rendered even when the cart is empty, so the footer actions still fire on a page with an empty cart. CartPops hides the footer element while the cart is empty and shows it again as items are added. Your footer output is hidden and shown with it. The callback is not run again.
The coupon, checkout and secondary action positions all live inside the footer, so they behave the same way. Positions outside the footer (cartpops_drawer_content, the header positions and the wrapper positions) are not hidden when the cart is empty.
Examples
Print a short note at the top of the drawer content.
add_action( 'cartpops_drawer_content', static function (): void {
printf(
'<p class="my-drawer-note">%s</p>',
esc_html__( 'Free returns within 30 days.', 'my-plugin' )
);
} );
Add a link under the checkout button, and style it in Custom CSS.
add_action( 'cartpops_drawer_after_checkout_button', static function (): void {
printf(
'<a class="my-drawer-link" href="%s">%s</a>',
esc_url( home_url( '/shipping-and-returns/' ) ),
esc_html__( 'Shipping and returns', 'my-plugin' )
);
} );
.cpops-drawer .my-drawer-link {
display: block;
margin-top: 8px;
text-align: center;
font-size: 14px;
color: var(--cpops-text-secondary);
}
Not a CartPops hook
fs_cartpops_loaded also exists. It belongs to the Freemius licensing layer and fires when that layer is ready. It is not part of the extension contract described here.