--- title: "Add session bookings to WooCommerce without the WooCommerce Bookings extension: a plugin you can build today" description: Most activity venues need date selection and a capacity limit, not a full booking engine. Here is the smaller plugin and the exact prompt to build it. source: https://steem.dev/blog/woocommerce-session-booking-plugin published: 2026-10-05 updated: 2026-10-05 alternative_to: WooCommerce Bookings site: Steem — AI WordPress plugin generator --- # Add session bookings to WooCommerce without the WooCommerce Bookings extension: a plugin you can build today WooCommerce Bookings is a first-party extension built for operations that schedule rooms by the hour, assign bookings to specific staff members, manage multiple resources per reservation, and apply different pricing at different times of day. It is a complete reservation engine, and the scope is deliberate. Most activity businesses need none of that. A yoga studio, a boat tour operator, an escape room, a cooking class venue: they have a short list of session types, fixed days for each, and a fixed number of spots. A customer picks a date and a session. The store needs to know when a slot fills up. That is the whole requirement. WooCommerce already holds all the data this needs: product settings for session configuration, order meta for what was booked, and order status for whether a slot is still occupied. A small plugin connects those three things and handles the job for most simple session businesses without a paid extension. ## What one build covers - Three configurable session types (Full Day, Morning, Evening) per product with per-session day-of-week availability and capacity - A date picker on the product page constrained to the selected session's available days - Live remaining capacity shown on the product page, with sold-out blocking when capacity is reached - Booking date and session type stored as order item meta, visible in cart, checkout, and order screens - An admin Bookings page listing upcoming bookings grouped by date with order links ## What it does not cover - Custom session type names: Full Day, Morning, and Evening are fixed in the plugin code - Per-date capacity overrides: capacity is set per session type and applies to every date equally - Specific date blocking for holidays or closures: dates can only be excluded by day of week - Booking multiple sessions in a single add-to-cart action: to book two different sessions, add the product to cart twice with different selections - Google Calendar sync, SMS or email reminders, and waiting lists ## The prompt ```text Build a WooCommerce plugin called Session Booking for WooCommerce. Plugin Name: Session Booking for WooCommerce. Description: Per-product session bookings with capacity tracking. Single PHP file. No dependencies beyond WooCommerce. Session types are hard-coded as three slots with keys fullday, morning, evening and labels Full Day, Morning, Evening. On each product Inventory tab (using woocommerce_product_options_inventory_product_data), render a fieldset labelled Session booking with one row per session type. Each row has: a checkbox to enable the session (id/name _session_fullday_enabled etc.), seven day-of-week checkboxes (value 0 for Sunday through 6 for Saturday, stored as a comma-separated string in _session_fullday_days, _session_morning_days, _session_evening_days), and a capacity number input (_session_fullday_capacity, _session_morning_capacity, _session_evening_capacity, min=1). Save all meta on woocommerce_process_product_meta using update_post_meta with absint for capacity and sanitize_text_field for days strings and enabled checkboxes. On woocommerce_before_add_to_cart_button for simple and variable products, output: a date input (type=date, name=sbfw_date, id=sbfw_date, min=today in Y-m-d format) and a select (name=sbfw_session, id=sbfw_session) populated only with enabled session types for this product. For each option include a data attribute data-days containing the comma-separated days string for that session. Below the select, output a paragraph (id=sbfw_remaining) showing remaining capacity for the default-selected session on today's date, calculated server-side: remaining = capacity minus count of woocommerce_order_itemmeta rows where meta_key=sbfw_session AND meta_value=the session key AND there exists another meta row on the same order item with meta_key=sbfw_date AND meta_value=the date, joined with wp_woocommerce_order_items and wp_posts where post_type=shop_order and post_status IN (wc-processing,wc-on-hold,wc-completed) and the order item has a meta_key _product_id matching this product. Register a nonce-protected wp_ajax and wp_ajax_nopriv action sbfw_get_remaining. It reads POST fields product_id, session, date; runs the same capacity query; returns JSON {remaining: N, capacity: N}. Add inline JavaScript on the product page. On change of sbfw_session or sbfw_date: if both have values, fetch sbfw_get_remaining via admin-ajax, update sbfw_remaining text to X of Y spaces remaining. If remaining is 0, set the text to Sold out for this date and session and disable the add-to-cart button; otherwise re-enable it. On change of sbfw_session, also validate the currently selected date: read the new session option data-days attribute, split on comma, check if getDay() of the selected date is in the array; if not, clear the date value and show an inline message below sbfw_date reading This session does not run on [day name]. Pass the admin_ajax url and nonce to JS via wp_localize_script. Validate in woocommerce_add_to_cart_validation: sbfw_date must be a valid date in Y-m-d format and must be today or later; sbfw_session must be one of the enabled session keys for this product; the day of week of sbfw_date must be in the session days list; remaining capacity must be at least 1. On any failure add a wc_add_notice error and return false. Store cart item meta via woocommerce_add_cart_item_data (add sbfw_date and sbfw_session). Display in cart via woocommerce_get_item_data with labels Date and Session. On woocommerce_checkout_create_order_line_item save both as order item meta with wc_add_order_item_meta. Escape all output with esc_html. Add a submenu page Bookings under WooCommerce (add_submenu_page, parent_slug woocommerce, capability manage_woocommerce, slug wc-session-bookings). Query order items that have sbfw_date meta with value >= today, joining sbfw_session meta and wp_posts for status, and wp_postmeta for customer first and last name (_billing_first_name, _billing_last_name). Output an HTML table. Group rows by date: print a full-width heading row for each new date. Columns: Session, Product (linked to product edit screen), Customer, Order (order number linked to order edit screen), Status. Order by sbfw_date ASC then order_id ASC. Escape all output. ``` ## Why WooCommerce Bookings is more than most activity venues need WooCommerce Bookings was designed for scheduling complexity: multiple bookable resources per location, per-person and per-unit pricing, buffer time between bookings, availability rules that account for staff calendars, Google Calendar sync, and a backend calendar view that spans every product and every booking at once. For a studio running three session types per day with twelve spots each, none of that applies. The schedule does not change by the hour. There are no resources to assign. The calendar view you actually need is a list of who booked which date. The mismatch matters because Bookings is a paid extension and the setup overhead is real. Before reaching for it, it is worth identifying exactly which of its features your operation uses, and whether a smaller plugin covers those features completely. ## How session booking works without a dedicated extension Session booking has three moving parts: a list of session types defined per product with their available days and capacity, a date and session picker on the product page, and a capacity check that counts existing orders. When a customer selects a date and session type, the plugin queries how many orders already exist for that combination. If the count is below capacity, the booking proceeds. The slot count does not live in a separate booking table. It comes from querying real orders in processing, on-hold, and completed status, which means it reflects the actual state of the store at the moment of purchase. The date picker constrains to days the selected session runs. If Morning sessions only run Wednesday through Friday, the calendar rejects Monday and Tuesday as soon as Morning is chosen. A customer cannot pick a date the session does not cover. ## What the plugin adds to WooCommerce Session configuration on the product Inventory tab. Three session types: Full Day, Morning, and Evening. For each, a set of day-of-week checkboxes and a capacity field. Enable only the sessions relevant to a given product. A product with only Morning and Evening enabled will not show Full Day as an option at checkout. A date picker and session selector on the single product page, above the Add to Cart button. The picker rejects days the selected session does not run. Remaining spaces are shown next to the session dropdown and recalculated when either the date or the session changes. When a session is sold out for a chosen date, the Add to Cart button is disabled and a sold-out notice appears. Cart and checkout display of the chosen date and session, stored as order item meta. The customer sees the booking details on the confirmation page and in the order email. The store admin sees the same on the order screen. A Bookings page under the WooCommerce admin menu listing upcoming bookings grouped by date: date, session type, product name, customer name, order number linked to the edit screen, and order status. This is the screen to check at the start of each day before sessions run. ## When WooCommerce Bookings or a dedicated tool is the right answer If your operation needs anything beyond date and session selection, this plugin is not enough. Staff assignment, per-booking resource allocation, Google Calendar sync, per-slot custom pricing, and waiting lists all require either the full Bookings extension or a purpose-built appointment scheduling tool. Amelia, Bookly, and WooCommerce Bookings are all justified for businesses where scheduling complexity is built into the service: a clinic matching patients with specific practitioners, a hotel assigning rooms to reservations, a gym where a trainer's personal calendar drives what slots exist. This plugin is not a replacement for any of those in those contexts. A simpler test: if your session schedule is a fixed table that changes maybe once a season, and the only variable is how many spots remain on each date, this plugin covers the job completely. If the schedule is dynamic, or if your operation depends on calendar integrations or per-practitioner availability, use a dedicated solution. ## Questions ### Can I change the session names from Full Day, Morning, and Evening? Not in this version: the three session types are fixed in the plugin code. To use different names, edit the plugin file to replace the labels and key strings, or ask Steem for a version that reads session names and counts from a settings field. ### What happens to the slot when a customer cancels their order? Capacity is calculated in real time from orders in processing, on-hold, and completed status only. When an order is cancelled or refunded, it drops out of that count immediately. No manual action is needed to free the slot. ### Can I block bookings on a specific date, like a public holiday? The plugin excludes dates only by day of week. To prevent bookings on a specific calendar date, the simplest option is to temporarily set that session's capacity to zero for the affected date. Per-date closure support can be added as a follow-up build. ### Does this work for variable products? Session types are defined at the parent product level and capacity is shared across all variations. Per-variation session configuration is not supported. ### Can a customer book two different session types in the same order? Yes, by adding the same product to the cart twice with different date and session selections. Each cart line is validated independently, so both slots are checked against remaining capacity at add-to-cart time. --- Source: https://steem.dev/blog/woocommerce-session-booking-plugin Build this plugin: https://steem.dev/app