WooCommerce Bookings
Running a booking site? Rentals, appointments, or classes?
Standard exports show the product name. Not booking dates, resources, or person counts.
Here’s how to export everything from WooCommerce Bookings.
What this code exports
Booking fields:
- Booking ID
- Booking Status
- Booking Start Date
- Booking Start Time
- Booking End Date
- Booking End Time
- Booking Resource (which room, car, or equipment)
- Booking Persons Total
- Booking Persons (by type)
Plus individual columns for each person type (Adults, Children, Seniors, etc.)
The complete code
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
//WooCommerce Bookings , added # of persons class WOE_Bookings{ function __construct() { add_filter('woe_get_order_product_fields',array($this,'add_product_fields') ); add_filter('woe_get_order_product_item',array($this,'fetch_booking') ); //set global filters add_filter('woe_get_order_product_value_booking_id', array($this,'get_booking_field_id'), 10, 5 ); add_filter('woe_get_order_product_value_booking_status', array($this,'get_booking_field_status'), 10, 5 ); add_filter('woe_get_order_product_value_booking_start_date', array($this,'get_booking_field_start_date'), 10, 5 ); add_filter('woe_get_order_product_value_booking_start_time', array($this,'get_booking_field_start_time'), 10, 5 ); add_filter('woe_get_order_product_value_booking_end_date', array($this,'get_booking_field_end_date'), 10, 5 ); add_filter('woe_get_order_product_value_booking_end_time', array($this,'get_booking_field_end_time'), 10, 5 ); add_filter('woe_get_order_product_value_booking_resource', array($this,'get_booking_field_resource'), 10, 5 ); add_filter('woe_get_order_product_value_booking_persons_by_type', array($this,'get_booking_field_persons_by_type'), 10, 5 ); add_filter('woe_get_order_product_value_booking_persons_total', array($this,'get_booking_field_persons_total'), 10, 5 ); // add function for person types if( class_exists("WC_Product_Booking_Data_Store_CPT") AND method_exists("WC_Product_Booking_Data_Store_CPT", "get_person_types_ids") ) { $person_types_ids = WC_Product_Booking_Data_Store_CPT::get_person_types_ids(); foreach($person_types_ids as $type_id) { add_filter('woe_get_order_product_value_booking_person_type_'.$type_id, function($value,$order, $item, $product, $item_meta) use ($type_id){ if (!$this->booking) return $value; $counters = $this->booking->get_person_counts(); return isset($counters[$type_id]) ? $counters[$type_id] : 0; }, 10, 5 ); } } } function add_product_fields($fields) { $fields['booking_id'] = array('label'=>'Booking ID','colname'=>'Booking ID','checked'=>1); $fields['booking_status'] = array('label'=>'Booking Status','colname'=>'Booking Status','checked'=>1); $fields['booking_start_date'] = array('label'=>'Booking Start Date','colname'=>'Booking Start Date','checked'=>1); $fields['booking_start_time'] = array('label'=>'Booking Start Time','colname'=>'Booking Start Time','checked'=>1); $fields['booking_end_date'] = array('label'=>'Booking End Date','colname'=>'Booking End Date','checked'=>1); $fields['booking_end_time'] = array('label'=>'Booking End Time','colname'=>'Booking End Time','checked'=>1); $fields['booking_resource'] = array('label'=>'Booking Resource','colname'=>'Booking Resource','checked'=>1); $fields['booking_persons_by_type'] = array('label'=>'Booking Persons (by type)','colname'=>'Booking Persons(by type)','checked'=>1,'segment'=>'cart'); $fields['booking_persons_total'] = array('label'=>'Booking Persons Total','colname'=>'Booking Persons Total','checked'=>1,'segment'=>'cart'); // add person types as columns if( class_exists("WC_Product_Booking_Data_Store_CPT") AND method_exists("WC_Product_Booking_Data_Store_CPT", "get_person_types_ids") ) { $person_types_ids = WC_Product_Booking_Data_Store_CPT::get_person_types_ids(); foreach($person_types_ids as $type_id) { $post = get_post($type_id); if( $post ) $fields['booking_person_type_'.$type_id] = array('label'=>'Booking Persons - ' .$post->post_title,'colname'=>'Booking Persons - ' .$post->post_title,'checked'=>1); } } return $fields; } // booking for item function fetch_booking($item) { global $wpdb; $this->booking = false; $booking_id = $wpdb->get_var( "SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key= '_booking_order_item_id' AND meta_value=" . intval( $item->get_id() ) ); if( $booking_id ) { try { $this->booking = new WC_Booking($booking_id); } catch (Exception $e) { ;// do nothing } } return $item; } function get_booking_field_id($value,$order, $item, $product, $item_meta) { return $this->booking ? $this->booking->get_id() : $value; } function get_booking_field_status($value,$order, $item, $product, $item_meta) { return $this->booking ? $this->booking->get_status() : $value; } function get_booking_field_start_date($value,$order, $item, $product, $item_meta) { return $this->booking ? date_i18n( wc_date_format(), $this->booking->start) : $value; } function get_booking_field_start_time($value,$order, $item, $product, $item_meta) { return $this->booking ? date_i18n( wc_time_format(), $this->booking->start) : $value; } function get_booking_field_end_date($value,$order, $item, $product, $item_meta) { return $this->booking ? date_i18n( wc_date_format(), $this->booking->end) : $value; } function get_booking_field_end_time($value,$order, $item, $product, $item_meta) { return $this->booking ? date_i18n( wc_time_format(), $this->booking->end) : $value; } function get_booking_field_resource($value,$order, $item, $product, $item_meta) { if (!$this->booking) return $value; $resource = $this->booking->get_resource(); return $resource ? $resource->get_name() : $value; } function get_booking_field_persons_by_type($value,$order, $item, $product,$item_meta) { if(!$this->booking) return $value; $counters = array(); foreach($this->booking->get_person_counts() as $type_id=>$number) { $post = get_post($type_id); $counters[] = $post->post_title . " - " . $number; } return join(", ", $counters); } function get_booking_field_persons_total($value,$order, $item, $product,$item_meta) { return $this->booking ? $this->booking->get_persons_total() : $value; } } add_action("init", function(){ new WOE_Bookings(); }); |
Setup steps
- Copy the entire code block
- Paste into your theme’s
functions.php - Go to Advanced Order Export for WooCommerce
- Create or edit an export profile
- Open Setup Fields → Products
- You’ll see all booking fields. Check the ones you need
- Save and test on a booking order
What your export looks like
| Order | Product | Booking Start Date | Booking Start Time | Booking Resource | Adults | Children | Total Persons |
|---|---|---|---|---|---|---|---|
| #1001 | Surf Lesson | 2026-07-15 | 10:00 AM | North Beach | 2 | 1 | 3 |
| #1002 | Kayak Rental | 2026-07-16 | 2:00 PM | South Dock | 1 | 0 | 1 |
When you need this
You rent equipment by the hour. Need start and end times.
You run a tour company. Need person counts per booking type.
You manage multiple locations. Need resource (which room, guide, or vehicle).
Your staff needs daily schedules. Export by date. See who’s coming.
Person types explained
If you sell “Fishing Trip” with person types:
- Adults ($50)
- Children ($25)
- Seniors ($40)
The code creates three columns:
| Booking Persons – Adults | Booking Persons – Children | Booking Persons – Seniors |
|---|---|---|
| 2 | 1 | 0 |
Each person type has its own column. No parsing needed.
Common mistake
The code expects the official WooCommerce Bookings plugin (from WooCommerce.com). Not third-party booking plugins.
Booking IDs must exist. Bookings are created after payment. Test with a completed booking order.
Empty columns?
Check that:
- WooCommerce Bookings is active
- The order has completed bookings (not just products in cart)
- You selected booking fields in Setup Fields
Pro tip
Need to filter by booking date? Combine with the Appointment Date Filter code (similar structure). Replace _appointment_start with booking start logic.
Want resource names as separate columns? The booking_resource field gives you one column. Works for most cases.
Real talk
WooCommerce Bookings stores booking data as custom post types (wc_booking). Each links to an order item via meta key _booking_order_item_id.
This code finds that link. Loads the full booking object. Pulls every field you need.
Your operations team gets clean schedules. No more clicking into each order to find booking times. One export. Everything they need.