Turn one of your Listeo listing packages into a recurring subscription by adding a few billing settings on top of it.
Author Archive
Customer Experience
Here is exactly what your customers see when they buy a recurring package, how they manage or cancel it later, and the few settings you control behind the scenes.
Getting Started
Welcome! This guide gets Listeo Subscriptions installed and shows you how it fits into your site, so you can start selling auto-renewing listing packages.
Listeo Booking Plus Changelog
1.0.22
- Consistent tax-inclusive totals and tax information across booking forms, booking dashboards and QR tickets.
1.0.21
- Listeo Core > Booking > Booking Rules > "Hide the 'Slot capacity counts' setting" (off by default). When on, the dropdown is hidden on the front-end and admin forms (listing and resource) and every slot counts separate bookings; stored values are kept. Filter `lbp_hide_slot_capacity_mode`. Also fixes a tooltip that never rendered on the front-end form.
- ### Fixes
- Events removed from the feed are pruned, unchanged feeds are skipped, one unreachable feed no longer stops the other resources.
- ### New Features
- Resource iCal feeds refresh automatically every 30 minutes (cron `lbp_refresh_resource_icals`, offset 15 min from Core's listing sync). Filters `lbp_resource_ical_cron_batch_size`, `lbp_resource_ical_cron_time_budget`.
- Resource iCal import never worked: it called Core's export method instead of reading the feed. Now uses `Listeo_Core_iCal_Reader`.
- Listing-level blocks (owner "Block dates", Core listing iCal import) now block every resource of the listing: slot list, "Any resource", "Next available" on resource cards and the server-side booking check. Filters `lbp_listing_level_blocks_apply_to_resources`, `lbp_listing_level_block_rows`.
- Removing or re-importing a resource calendar left resource metadata on bookings.
- An imported event counted as one booking, so multi-capacity slots stayed bookable; imported events and owner blocks now make the slot fully unavailable.
- Booking phone validated with Core's shared rule (local fallback if Core is older).
- reCAPTCHA v3 uses Core's shared verification.
1.0.20
- Fixed issues with resource Availability Calendar.
1.0.19
- Grouped multiple guest categories into a compact list with matching bordered quantity controls and subtle separators. Supports all category combinations, resource switching, long translations, mobile and RTL layouts, with neutral dark-mode styling. The single Guests row keeps its existing layout.
- Placed compact extra-service quantity controls inside each service card, before the price on wider popup columns and on a second row inside the card on narrow screens. Keeps prices aligned, supports dark mode and RTL, and preserves quantity selection and the classic dropdown layout.
- Extra services in the booking popup now appear as an always-visible, neutral checklist by default, with scrolling for longer lists and controls styled to match the popup. The new Extra services display setting restores the classic dropdown when preferred. Service selection, quantities and pricing rules are unchanged.
- Replaced hardcoded blue and violet-gray tints in the booking popup and event badges with neutral grays, including the calendar overlay, dark-mode surfaces, shadows, guest controls and price summary. Selection and button colors continue to respect the configured accent; legacy blue accent fallbacks now follow the theme.
- Centered the feature and activation sections on the Booking Plus License overview while retaining left-aligned content.
- Moved Booking Plus License into the Listeo Core menu directly below License. Updated activation links, page hooks and form redirects, and redirected old Settings-page bookmarks to the new location.
- Redesigned the Booking Plus License page for sites without a saved key: premium features and the tracked offer link appear first, with activation in an expandable section. Activation links open that section directly and failed submissions keep it open. Existing licensed, saved-key and Hosted screens remain unchanged.
- Added staggered automatic feature icon animations: recurring-event arrows rotate once per 12-second cycle, while other icons make small movements followed by a long pause. Reduced-motion preferences disable all feature icon animations.
- Added a subtle outline arrow to Explore premium features buttons in the settings overview and admin notice, with RTL direction support.
- Increased premium overview icons to 24px in Listeo red with a subtle hover motion that respects reduced-motion preferences. Added UTM campaign parameters to offer links, distinguishing the settings overview, admin notice, license page and feature cards.
- Added small, consistent outline SVG icons to the Booking Plus feature overview, with aligned descriptions and decorative icons hidden from screen readers.
- Restyled the Booking Plus premium overview to match Listeo settings: a flat, responsive feature list, simpler descriptions, standard typography and button, and a direct license activation link. Removed nested tiles, decorative gradients, hover movement and Pro branding.
- Redesigned the free-mode admin notice with a concise feature-focused headline, a responsive layout, an outlined Explore premium features button, and a separate license activation link. Preserves existing visibility and dismissal behavior.
- Refined the booking popup price summary with compact, consistently styled cost rows and lighter heading/total weights matching Listeo typography. Coupon entry now uses a compact field and an accent-colored Apply button with rounded styling matching the popup actions, with clearer focus, feedback and applied-code states in light, dark and RTL layouts.
- Refreshed the booking popup with clearer typography, consistent outline icons, a listing thumbnail, connected step indicators, larger time-slot cards with localized durations, always-visible guest controls, and a highlighted estimated total. Preserves configurable colors, resource-specific guest categories and multi-slot selection, with responsive and dark-mode styles, keyboard focus indicators and reduced-motion support.
- Time-slot capacity can now be counted as a shared guest pool instead of separate booking records. The new opt-in "Slot capacity counts" setting reuses each slot's existing number as the total adults and children allowed, shows the remaining places in the Booking Plus popup, supports per-resource overrides and multi-slot service spans, and stores each booking's party size for reliable future calculations. Existing listings remain in separate-bookings mode. The same setting and calculation also apply to Listeo Core's regular booking widget. Simultaneous final submissions are serialized so the shared pool cannot be oversold. Requires the companion Listeo Core update.
- The booking popup now respects Listeo Core's new "Prevent overlapping bookings" option for listings that use the hourly time picker (single day / service listings without time slots). When the option is enabled on the listing, the popup checks the chosen start and end time against existing bookings as soon as the time is picked (the Date & Time step shows "This time overlaps an existing booking" and Next stays disabled) and checks again on submit, so a stale or crafted request can't book over a taken hour. Only approved bookings block; pending, cancelled or expired ones don't. When the End Hour picker is off and the booked length comes from the selected services' durations, that end time is now stored on the booking so later checks see the full span. Resource bookings, time-slot listings and events keep their existing availability rules. Requires the companion Listeo Core update; on older Core versions the popup simply behaves as before.
- Aligned extra-service checkboxes with their names when no duration is shown. On narrow screens, prices appear below the service text without shifting the checkbox.
- Fixed the extra-service counter refresh after loading resource-specific services. The classic services dropdown now stays open when Next highlights a missing required service.
- Overnight time slots (a slot whose end time is earlier than its start, such as 22:00 - 02:00) are now booked and checked against the following day. The popup previously stored such a booking with its end before its start, an interval no availability query can match, so the slot never counted as taken and could be booked over and over. Bookings already stored that way are not altered; only new bookings are affected. Slots that do not cross midnight are unchanged.
- Booking a listing with "Any" resource selected no longer creates a booking with no resource attached when every resource is actually taken. The booking was saved unassigned, so it blocked nobody's calendar, never appeared under a team member's bookings, and left the owner to work out who was supposed to take it. The customer is now told "No resource has enough availability for the selected time and group size." and can pick another time. Listings without resources are unaffected.
- A time slot that is shorter than the services booked into it is now refused, with "The selected service needs more time than this slot allows." Previously the booking went through and the overrun silently ate into the next slot.
- The classic widget now carries multi-slot metadata through confirmation when the browser associates the hidden booking payload with the form even though it sits outside the form's DOM container. The previous descendant-only lookup skipped that payload, so valid guest-capacity spans could still be rejected on final submission.
- Guest-capacity validation on the classic booking form now checks all selected slots on final submission. A valid multi-slot group booking could previously fail with "There are not enough places left for this group" because only the starting slot was passed to the final check, even though the availability preview checked the full span. Guest-capacity checks also preserve the listing's maximum selected-slot limit.
- The classic widget's multi-slot picker now shows the live remaining capacity returned by the server instead of the configured slot total, including when capacity counts guests. Remaining places stay visible alongside "Tap to add" and "Selected" labels. Initial loading preserves received counts, late responses cannot overwrite a different date, and updated picker assets invalidate the browser cache automatically.
- With no minimum advance notice configured (the default), a visitor who kept the booking popup open could still submit a time slot or hour that had already passed. Past times were only hidden from the popup, not rejected by the server, so a stale or crafted request went through. The popup now rejects start times in the past both when the time is picked (the Date & Time step shows "This time is no longer available" and Next stays disabled) and again on submit, for listing and resource bookings alike, and events whose start has passed are rejected the same way. The classic booking widget gets the same protection through the availability check. Owners adding manual bookings for past dates are unaffected. Developers who need the old behaviour can allow past start times with the lbp_allow_past_bookings filter.
1.0.18
- Minimum advance notice can now be entered in minutes, hours or days on the global Booking Rules setting, per-listing Booking Options metabox, and frontend submit form.
- A new Minimum advance notice unit option pairs with the existing value.
- The per-listing Minimum advance notice field is now a predefined field you can add in Listeo Editor wherever needed.
- The per-listing Minimum advance notice field placeholder now shows the resolved site default instead of a blank box.
- Minimum advance notice is now enforced for events and ticket-type listings, including booking popups, classic widgets, and date pickers.
- When no bookable date remains because of minimum advance notice, the booking widget and popup now show a bookings closed message.
- The booking popup now respects Core's Prevent overlapping bookings option for hourly time-picker listings.
- Multi-tier ticket events now include the listing's Mandatory Fees in the booked price.
- With no minimum advance notice configured, the popup now refuses past start times.
- Percent-based fees are now computed on the ticket subtotal, and the popup price breakdown now itemizes each fee alongside the ticket lines.
1.0.17
- Booking popup and team member profile popup now open with a zoom/fade animation
- Booking popup price preview now includes the "add" commission, shown as a "Site fee" breakdown line, so guests see the same total the checkout charges (standard, event/ticket and resource bookings). The breakdown stored on the booking matches too.
- The popup open-during-close race fix ("Cannot read properties of null (reading 'inline')"), which also guards the theme's and Core's popups since they share the same Magnific singleton.
1.0.16
- New hook: lbp_resource_list_row_details - Lets devs inject custom per-resource content (e.g. internal notes) into each resource row server-side.
- Resource manager access fix - Any active team member can now open resource manager (role no longer blocks entry); per-resource permissions still gate what they can actually touch.
- Duration + resource time slots bug - Fixes bug when listings slots configuration was used over the resource config
- Weekday timezone bug - Slot weekday is now computed server-side instead of browser-side, fixing wrong-day slot selection for visitors west of UTC.
- Race condition on quick date/team switches - Stale slot responses are now discarded so they can't overwrite newer ones.
- Date format bug - Compact dates across the booking widget/popup now respect the site's actual date order (day-first sites no longer get month-first dates); new lbp_short_date_format filter for overrides.
1.0.15
- capacity issues on recurring events
1.0.14
- resource popup fixed on mobile; booking dates no longer drift to 2029–2030; per-resource minimum days enforced.
- Booking Plus admin resource editor now matches the frontend.
- Booking Plus ticket types and recurring schedule can be used as multi-step form sections
1.0.13
- Availability Calendar on the resource form saves reliably (was broken/collapsed, toggle didn't persist).
- "Import slots from main listing" now persists.
- Popup bookings now save custom booking fields (requires companion Core update).
- Multi-step submit form: Ticket Types & Recurring Schedule now assignable to a step (requires companion Core + Forms & Fields Editor).
- Kept the existing mobile sticky "Book Now" fix.
- Styling improvements
- Tems support
Managing Resources from the Front-End
Owners can manager their booking resources the same way they already control listing. On plugin activation, Listeo Booking Plus will automatically create a Manage Resources page and set correct content and template for that. In case it didn’t happen, here’s instruction
Setting up the page
- Create a new page (e.g. “Manage Resources”).
- Drop the shortcode in:
[lbp_manage_resources]
- Add the page to the owner’s dashboard menu (you can configure the dashboard menu under Listeo Core → Pages → Resource page).
What owners can do from this page
- Submit a new resource
- Edit any of their own resources.
- Duplicate a resource to spin up a near-identical one quickly.
- Import/Export iCal – import or export bookings to their personal calendar
- Pause a resource — temporarily takes it out of the booking pool without deleting it.
- Delete a resource permanently.
Each resource has its own availability calendar and its own iCal export / import URLs. This mirrors Listeo Core’s per-listing iCal flow — if you already use it for listings, the resource version will feel identical.
Each resource gets its own subscribe URL so external calendars (Google, Apple, Outlook, Airbnb, Booking.com) always see the right slice of the schedule.
Exporting a resource’s bookings
- Open the Manage Resource page for your listing
- Find the iCal Export section.
- Copy the subscribe URL.
- Paste it into Google Calendar (Other calendars → From URL), Apple Calendar (File → New Calendar Subscription), or any iCal-compatible app.
The feed updates every time the external app re-fetches it (the cadence is controlled by the receiving calendar — typically a few hours).
Importing external calendars into a resource
- In the iCal Import section, click Add Calendar.
- Enter a friendly name (e.g. “Airbnb — Apartment 4”) and the external
.icsURL. - Save.
Listeo Booking Plus pulls events from each imported URL on a schedule and creates blocked bookings on the resource. Imported events are tagged so a later re-fetch can update or remove them cleanly without disturbing real bookings.
Conflict rules
- A booking from your site always wins — imported events never overwrite an existing booking.
- An imported event that overlaps with an existing import is updated, not duplicated.
- Removing an imported calendar removes only its events; manually-added bookings stay put.
Recurring Events
If you run the same event every week, you don’t need to create 52 listings. Listeo Booking Plus generates occurrences from a single rule and lets you override any individual date without touching the rule itself.
Defining a recurrence rule
- Edit an Event listing.
- Scroll to the Recurrence meta box.
- Pick a pattern: Daily, Weekly, Monthly, or a Custom rule.
- For Weekly, pick the days of the week. For Monthly, pick the day-of-month or a Nth-weekday rule.
- Set the start date and (optionally) an end date.
- Save.
How occurrences are generated
A background cron job materialises future occurrences up to the Recurrence lookahead window – 12 months by default, configurable in Listeo → Settings → Booking. As time passes, the cron extends the window so there’s always ~12 months of bookable dates ahead.
You don’t need to “regenerate” anything manually — saving the listing triggers an immediate refresh of upcoming occurrences.
Per-occurrence overrides
Sometimes one specific date needs to be different — a higher price for New Year’s Eve, a smaller capacity because half the venue is being renovated, or just cancelling a single class because the instructor’s on holiday.
- In the Occurrences panel on the listing edit screen, find the date you want to change.
- Click Override.
- Set the override price, override capacity, or Cancel this occurrence.
- Save.
The recurrence rule itself stays unchanged — the override applies only to that one date. Remove the override and the date falls back to the rule’s defaults.
What customers see
The single-event page shows a date picker with all upcoming occurrences. Cancelled occurrences disappear; occurrences with overridden prices show the override price; sold-out occurrences are greyed out.
Event Listings & Ticket Types
Listeo Booking Plus turns Listeo’s Event listing type into a real ticketing system. You can define multiple ticket types per event, set capacity per type, control sale rules, and (optionally) collect attendee details at checkout.
Defining ticket types
- Edit an Event listing.
- Scroll to the Ticket Types meta box.
- Click Add ticket type for each tier — for example: Adult, Child, VIP, Early Bird.
- For each tier set:
- Label — what customers see (“Adult”, “VIP”).
- Price — per-ticket price in your store currency.
- Capacity — how many of this ticket type are available. Leave blank for “as many as the event capacity allows”.
- Min & Max – set how many tickets user could buy at once.
- Sales Start and Sales End date – when tickets will be available
How capacity works
Booking Plus respects two capacity limits at the same time: the per-ticket-type capacity (the cap you set on each tier) and the event total capacity (Core’s listing-level field). Whichever is reached first stops sales for that tier.
Example: an event with total capacity 100 and a “VIP — 20 tickets” tier. Once 20 VIP tickets are sold, the VIP tier shows as sold out even if total ticket sales are well below 100.
The front-end ticket selector
Customers see a quantity selector per ticket type. They can mix tiers in a single booking (2 Adult + 1 Child + 1 VIP), and the booking summary breaks each line out for transparency.
Collecting attendee names and emails
Toggle Collect attendee names and / or Collect attendee emails in Listeo Core → Listeo Booking Plus Settings. When on, the confirmation step shows one name (and / or email) field per ticket. Names appear on the individual e-tickets; emails are stored against the booking so each attendee can be contacted directly.
Reservation holds
When a customer clicks “Book” and lands on the confirmation step, Booking Plus puts a temporary hold on the tickets they’ve selected. While the hold is active, those tickets are invisible to other customers — the inventory shows fewer seats, and the ticket selector won’t let anyone else buy them.
If the customer completes checkout, the hold becomes a real booking. If they abandon the page (or the timer runs out), the hold expires and the seats go back into inventory.
Configuration
- Reservation hold time (minutes) — Listeo → Settings → Booking. Default: 15.
- Raise it if your checkout requires a slow third-party step (a complex payment redirect, a manual approval).
- Lower it on high-demand events where seats need to recycle quickly when checkout is abandoned.
What happens when a hold expires
The customer doesn’t get an aggressive error — when they submit the form, the system re-checks availability and tells them politely that their hold expired and to pick again. No silent overselling.
Individual ticket codes
When Generate individual ticket codes is on (default), Booking Plus creates one unique scannable code per ticket — not per booking. A family that buys 4 tickets gets 4 codes.
Where customers see their codes
- In the booking confirmation email.
- On the booking detail page in their dashboard.
- Each code includes a QR for the door scanner.
Why per-ticket and not per-booking
Door scanning works ticket-by-ticket: each attendee can arrive separately, get their own code scanned, and the system marks just that ticket as used. With one code per booking, a single scan would either let the whole family in (no count) or block subsequent scans (annoying).
If you really do want per-booking codes (small private event, you trust the headcount), switch the setting off and the legacy single-code-per-booking behaviour comes back.
The Booking Popup – Appearance & Steps
The booking popup is the customer-facing modal used by every booking type — Services, Rentals and Events. Booking Plus replaces Listeo Core’s inline booking widget with this multi-step popup whenever the listing is configured to use Booking Plus features (resources or ticket types).
The steps
| # | Step | When it appears |
|---|---|---|
| 1 | Resource | When the listing has resources attached. Picks which resource to book. |
| 2 | Date/time | Always. Picks the date(s) and (for time-aware bookings) the time slot. |
| 2 / 3 | Tickets | Event listings. Pick ticket types and quantities. |
| Last | Confirm | Always. Reviews the booking, collects guest info, optional attendee details. |
| Last+1 | Success | After a successful booking. Shows confirmation + next steps. |
Customising appearance
Three colors in Listeo → Settings → Booking → Booking Popup Appearance control the look:
- Popup sidebar — color — main sidebar background. Defaults to
#2d2d32(close to black). - Popup sidebar — gradient end (optional) — set this for a gradient sidebar; leave blank for solid.
- Popup accent color — used for the dot before each section label, the active step number, the “Next” button, and selection highlights. Defaults to
#3b82f6(blue).
Values are injected as CSS custom properties before the popup paints — no flicker of the old color when the page loads.
Mobile behaviour
The popup goes full-screen on mobile and the multi-step navigation collapses to a top progress bar. Sidebar content moves to a collapsible header so the form always has the full screen width.
Overriding the templates in a child theme
Every step is a separate template file you can override (see Customizing Templates):
templates/booking/modal.php— the popup shell.templates/booking/modal-sidebar.php— the left sidebar.templates/booking/modal-step-datetime.phptemplates/booking/modal-step-resource.phptemplates/booking/modal-step-confirm.phptemplates/booking/modal-step-success.php
Services – Durations, Individual Services & Slot Spans
For Service listings, Listeo Booking Plus adds two opt-in features that change how the booking widget interprets service selections.
Service durations
Off by default. Turn on with Enable service durations in Listeo Core → Booking.
When on, each bookable service on a listing gains a Duration field. Set a duration in minutes (e.g. 90 for a 90-minute massage), and when a customer picks that service the booking widget reserves enough consecutive slots to cover it.
Example with 30-minute slots:
- Customer picks a 90-min service starting at 10:00.
- Booking widget blocks 10:00, 10:30 and 11:00 — three consecutive slots.
- No other customer can book any of those three slots, even though only one was “selected”.
This is the right model whenever a service is longer than your underlying booking grid.
Individual Services
Off by default. Turn on with Enable Individual Services in Listeo Core → Booking.
When on, each service has an Individual service toggle. The rule:
- A customer can pick at most one Individual service per booking.
- They can stack as many non-Individual services as they like on top — these act as add-ons.
The model: an Individual service is “the appointment” (haircut, massage, consultation); non-Individual services are “the add-ons you can tack on” (scalp treatment, hot towel, extra 15 min). This matches how most service businesses actually quote work.
If you don’t sell anything that fits the “main + add-on” pattern, leave this off – the regular Listeo Core behaviour applies and customers can pick any combination.
Slot spans
When service durations are on, the underlying mechanism is called slot spans — the booking record itself stores the span (start slot + number of slots) so that conflict checks, the calendar and emails all see one logical booking spanning multiple slots rather than several separate ones.
You don’t configure slot spans directly — they’re how durations get expressed under the hood. The main effect for you is that the bookings admin shows one row per booking (not one per slot), which keeps the list readable.
Pricing Extras & Repeatable Fees
Listeo Booking Plus extends Listeo Core’s pricing with repeatable fees — costs that scale with the booking instead of being a flat add-on.
What’s a repeatable fee?
Any cost that’s calculated per unit-of-something. Common examples:
- Per-guest fee —
$5 per gueston a tour or event. - Per-night cleaning fee —
$25 per nighton a rental. - Per-attendee surcharge — VIP service fee charged per ticket.
Compare to a flat fee (Listeo Core’s existing feature), which is the same regardless of party size or length of stay.
Adding a repeatable fee
- Edit the listing.
- In the pricing / extras section, find Repeatable Fees.
- Click Add fee and set:
- Label (shown in the booking summary).
- Amount per unit.
- Unit — guest, night, ticket, hour, etc.
- Save.







