WooCommerce integration hooks

How the paid path is wired, and where to hook into it.

The flow

  1. Get access adds the product to the cart with the event's identity attached as cart item data.
  2. At checkout, the event is written onto the order.
  3. When the order's thank-you page renders, the buyer is enrolled in the event.

Each of those is a standard WooCommerce extension point, so integrations use WooCommerce's own hooks rather than POM Events-specific ones.

The cart item

The event identity travels as cart item data under the key event_id_to_enroll.

To inspect it:

add_filter( 'woocommerce_get_item_data', function ( $item_data, $cart_item ) {
    if ( ! empty( $cart_item['event_id_to_enroll'] ) ) {
        $item_data[] = array(
            'name'  => __( 'Event', 'my-plugin' ),
            'value' => get_the_title( (int) $cart_item['event_id_to_enroll'] ),
        );
    }

    return $item_data;
}, 10, 2 );

That snippet is worth deploying on any site selling events: it shows the buyer which event they are paying for, in the cart and at checkout.

The order

The event is stored on the order as meta under associated_event_id:

add_action( 'woocommerce_order_status_processing', function ( $order_id ) {
    $order    = wc_get_order( $order_id );
    $event_id = $order ? $order->get_meta( 'associated_event_id' ) : 0;

    if ( ! $event_id ) {
        return;
    }

    // React to a paid event order.
} );

Use it for order confirmation emails that mention the event, for reporting, or for your own enrollment logic.

Enrollment happens on the thank-you page

Enrollment runs on woocommerce_thankyou. Two consequences for integrations:

  • A buyer who never reaches the page is not enrolled. Any integration that assumes an order always produces an attendee will be wrong sometimes.
  • Do not remove or bypass the thank-you page for event products.

To make enrollment happen on payment instead, you can write your own handler on an order status transition, reading associated_event_id and writing into event_assistants. Reproduce the plugin's behavior carefully — the capacity check, the duplicate check and the values taken from the order — or the two paths will disagree.

What enrollment stores

Attendee field Source
Identity The order's customer account
comments The customer's order notes
tel The order's billing phone
status Empty, or waiting-list if the event is full

If your checkout does not collect a billing phone, attendee telephones will be empty. That is a checkout configuration decision, not a plugin setting.

Sending confirmation emails for paid events

The registration action does not fire for purchases. Implement the paid path separately, on an order hook, or attendees who bought will hear nothing while attendees who registered do.

Reconciliation is part of any integration

Because enrollment depends on a page render, a robust integration should reconcile rather than trust:

$orders = wc_get_orders( array(
    'limit'      => -1,
    'status'     => array( 'processing', 'completed' ),
    'meta_key'   => 'associated_event_id',
    'meta_value' => $event_id,
) );

$assistants = get_post_meta( $event_id, 'event_assistants', true ) ?: array();

foreach ( $orders as $order ) {
    $user_id = $order->get_user_id();

    if ( $user_id && ! isset( $assistants[ $user_id ] ) ) {
        // Paid, not enrolled.
    }
}

Guest orders have no user ID and cannot be matched this way, which is a good argument for requiring accounts at checkout.

Capacity and stock are independent

The event's available_space and the product's stock are not synchronized. If your integration manages one, decide explicitly what it does about the other.