WooCommerce Bookings provides a way for people to sell time based products and it can be made to work with a wide variety of use-cases. Unfortunately, in order to be able to work with this wide range of use-cases the configuration can be quite challenging and the interface can get difficult to use to set up complex pricing rules based on duration + person count or other variables that might determine the final cost of a booking. Consider this example for a business offering Jet Ski rentals and the pricing structure that they wish to achieve:
At first glance, this looks fairly straightforward to set up using block count price adjustments and person count pricing adjustments. However, as the block count and person count increases, the mathematical relationships begin to become less clear and would probably require a mathematician to figure out how to represent the various price points within the bookable product configuration screen. I’m no mathematician. Fortunately, Bookings does offer a filter which can be used to dynamically set the booking cost based on the booking duration and person count. Just to be clear, in this example the jetski count is represented by the person count in the bookable product.
The filter that I would used to do this is named booking_form_calculated_booking_cost and is located in wp-content/plugins/woocommerce-bookings/includes/booking-form/class-wc-booking-form.php in case you want to browse the code to see how it works. The call to apply_filters passes three parameters. The first is the booking cost – this is the value that will be conditionally filtered and eventually returned. The second parameter is an object which represents the booking form itself and contains some information about the bookable product that is currently being viewed. This object will expose the product id which we will need to ensure that only this particular product will have its cost adjusted by this filter implementation. The third parameter that is passed is the data that was posted. This data is important as it contains the block count (duration) and the person count.
Below is an example of how to achieve the required pricing table using the filter that I mentioned. The idea is this:
- On line 8 if the product id matches YOUR_PRODUCT_ID_HERE (replace with your product id – unsure how to find your product id, see this post ) then filter the price.
- Beginning on line 12 the pricing table in represented in an array. There are certainly more elegant ways to do this but here’s what I’ve done, I’ve taken the number of days (duration) and the number of jetskis (person count) – i.e. 3 jetskis for 5 days the array key will be ’35
- On line 46 there is a ternary operator that will set a default cost if the array key does not exist. You will notice that there are no array keys for 1 day 1 person, 2 days 1 person…etc. The cost in these cases would simply be 275 * (number of days) * (number of persons). This will also serve as a default price calculation in case the product configuration changes without updating the filter’s callback function – without this error handling, there is a chance that the product could be booked for free.
- Return the booking cost.
And here is the example code of how this could be achieved:
Keep in mind that since the prices for this particular product are completely overridden then you may wish to configure the “Display cost” as appropriate in your bookable product configuration. The lowest possible cost in this case would be for 5 jetskis for 7 days. This works out to $177.14 per person, per day. This might be the most appropriate value to enter in the “Display cost” field.
Not sure what to do with code snippets? See What Do I Do With These Code Snippets?