Title: EffortLess Simple House Booking
Author: domclic
Published: <strong>October 12, 2026</strong>
Last modified: October 12, 2026

---

Search plugins

![](https://ps.w.org/effortless-simple-house-booking/assets/banner-772x250.jpg?rev
=3741249)

![](https://ps.w.org/effortless-simple-house-booking/assets/icon-256x256.jpg?rev
=3741249)

# EffortLess Simple House Booking

 By [domclic](https://profiles.wordpress.org/domclic/)

[Download](https://downloads.wordpress.org/plugin/effortless-simple-house-booking.1.0.89.zip)

 * [Details](https://wordpress.org/plugins/effortless-simple-house-booking/#description)
 * [Reviews](https://wordpress.org/plugins/effortless-simple-house-booking/#reviews)
 *  [Installation](https://wordpress.org/plugins/effortless-simple-house-booking/#installation)
 * [Development](https://wordpress.org/plugins/effortless-simple-house-booking/#developers)

 [Support](https://wordpress.org/support/plugin/effortless-simple-house-booking/)

## Description

A multisite-compatible booking plugin for house tours. Features:

 * Global available dates & bookings (one booking per slot network-wide)
 * Morning and afternoon time slots
 * Optional meal add-on for morning tours
 * Simple CAPTCHA protection
 * Email verification for bookings & subscriptions
 * Uses WordPress native wp_mail() for emails
 * Admin email selectable from all network users
 * All settings sync across network
 * QR code generation for booking confirmations
 * Optional online payment for verified bookings, through the separately installed
   EffortLess Easy Online Payment plugin

## Installation

 1. Upload the plugin folder to `/wp-content/plugins/`
 2. Network Activate the plugin
 3. Go to Network Admin > Bookings > Settings to configure
 4. Use shortcodes `[elsbh_booking]` or `[elsbh_booking_button]`
 5. For SMTP configuration, use a dedicated SMTP plugin (e.g., WP Mail SMTP)

## FAQ

### How do I add available dates?

Go to Bookings > Available Dates in the WordPress admin and use the date picker 
to add dates.

### Can I customize the booking form?

The form uses CSS classes that can be styled. The templates are in `public/views/`.

### How do I let customers pay for their booking online?

Install and activate the separately available EffortLess Easy Online Payment plugin,
configure at least one of its payment gateways, then turn on “Enable payment integration”
in ELSBH Settings. A verified booking’s confirmation page then shows a “Pay Now”
button. This plugin never modifies the payment plugin — it only creates data through
its own documented product model and embeds its own checkout shortcode. Which gateways
are offered, and in which currency, is controlled entirely by that plugin’s own 
settings; ELSBH always charges in TWD.

## Reviews

There are no reviews for this plugin.

## Contributors & Developers

“EffortLess Simple House Booking” is open source software. The following people 
have contributed to this plugin.

Contributors

 *   [ domclic ](https://profiles.wordpress.org/domclic/)

[Translate “EffortLess Simple House Booking” into your language.](https://translate.wordpress.org/projects/wp-plugins/effortless-simple-house-booking)

### Interested in development?

[Browse the code](https://plugins.trac.wordpress.org/browser/effortless-simple-house-booking/),
check out the [SVN repository](https://plugins.svn.wordpress.org/effortless-simple-house-booking/),
or subscribe to the [development log](https://plugins.trac.wordpress.org/log/effortless-simple-house-booking/)
by [RSS](https://plugins.trac.wordpress.org/log/effortless-simple-house-booking/?limit=100&mode=stop_on_copy&format=rss).

## Changelog

#### 1.0.89

 * Completed the bundled translation files: a template (.pot) and translations for
   Spanish, Traditional Chinese, Korean, French, Japanese, German, Italian and Brazilian
   Portuguese.

#### 1.0.88

 * The check that recreates missing email templates now runs only for users who 
   can manage bookings, and no longer runs during AJAX requests.

#### 1.0.87

 * Database queries on the Bookings screen and in the legacy table migration now
   bind table and column names with the `%i` identifier placeholder instead of building
   them into the SQL string. Minimum WordPress version raised to 6.2, which introduced`%
   i`.

#### 1.0.86

 * Removed the manual `load_plugin_textdomain()` call; translations are loaded by
   WordPress.

#### 1.0.85

 * Added the call that loads the bundled translations (French, Spanish, Japanese,
   Korean, Traditional Chinese), which were not being loaded.

#### 1.0.84

 * Renamed the plugin folder and main file to `effortless-simple-house-booking` 
   so they match the text domain.

#### 1.0.83

 * Changed the text domain to `effortless-simple-house-booking` in all translatable
   strings, the plugin header and the bundled translation files.

#### 1.0.82

 * Fix: several form fields and boxes (the booking form’s text/email/phone/number
   fields and date/slot dropdown, the CAPTCHA field, the subscribe form’s email 
   field, the slot-selection options, and the verification/unsubscribe confirmation
   overlay) had no explicit text color of their own, so they silently inherited 
   the active theme’s body text color — on a theme with light/white body text, they
   could render nearly invisible text on their fixed light backgrounds. All now 
   set their own explicit text color instead of relying on the theme.

#### 1.0.81

 * Security/Fix: an actual, real-database upgrade test from a genuine 1.0.72 install(
   not just a fresh install) surfaced a bug in the 1.0.78 table-prefix migration—
   if the one-time table rename ever failed (a hosting account whose database user
   lacks rename privileges, a locked table, a read-only replica), the plugin silently
   marked the migration complete anyway, permanently leaving every query targeting
   a table that was never renamed with no way to recover short of manual database
   intervention. It now correctly keeps retrying on every future request until the
   rename actually succeeds.

#### 1.0.80

 * Fix: translations updated for all 5 bundled languages (Spanish, French, Japanese,
   Korean, Traditional Chinese) — around 60 strings added since the previous 1.0.7x
   feature/security work (payment integration, access control, rate-limit messages,
   and more) had never been translated; a handful of pre-existing translations that
   had drifted onto the wrong English source string after a prior merge were also
   corrected.
 * Fix: several text/background color combinations across the admin list tables,
   the frontend booking form, and the customer-facing booking recap page did not
   meet WCAG AA’s 4.5:1 contrast minimum (some as low as ~1.7:1) — status badges,
   success/error messages, and disabled-slot labels were darkened for readability;
   rows are no longer dimmed with CSS `opacity` (which reduced text legibility along
   with the background).

#### 1.0.79

 * Security/Fix: fixed two critical regressions from the 1.0.78 fix round — on a
   multisite network, the legacy-table cleanup could duplicate and then delete the
   live, current bookings/subscribers tables (the “old per-site table” name for 
   the main site had become identical to the new global table name); and the payment-
   reconciliation cron was never actually being scheduled, because the code that
   registers its interval ran after the code that schedules it. Also: the table-
   prefix migration now runs immediately for every request rather than waiting for
   an admin to visit wp-admin after an upgrade; the legacy-total backfill keeps 
   running in small batches until it’s fully caught up, instead of processing only
   one batch per plugin version; the booking-form rate limit is now only counted
   on attempts that pass basic validation, so trying a couple of unavailable dates
   in a row no longer locks a real visitor out for a day; a min/max settings pair
   is now rejected (with a notice) instead of being silently swapped; deleting an
   available date no longer gets permanently blocked by an invisible, long-abandoned
   booking attempt; and several smaller hardening fixes (rate-limit window accounting,
   a null-safety fix in unsubscribe token validation, admin notification email can
   no longer be silently blanked by a typo, and more).

#### 1.0.78

 * Security/Fix: full code-review fix round covering the database layer, the payment
   integration, and the admin/public forms. Highlights: the plugin’s own database
   tables now include the site’s own table prefix (matching WordPress’s own tables),
   so two WordPress installs sharing one database can no longer read or write each
   other’s bookings/subscribers/dates; a legacy per-site upgrade path now copies
   data into the shared tables instead of dropping it; payment confirmation now 
   has a server-side fallback sweep (not only the customer’s browser tab) so a closed
   tab or a slow gateway can no longer leave a completed payment unreconciled; a
   booking’s total can no longer be changed once it has already been paid, closing
   a path that could otherwise orphan the completed payment; a rare stuck state 
   in the payment product creation now self-heals; booking/subscription forms are
   now rate-limited per IP and per email address; the unsubscribe link now requires
   an explicit confirmation click rather than acting on a plain GET (so an email
   client’s link-prescanning can no longer unsubscribe someone automatically); deleting
   an available date is now refused while it still has active bookings; the admin
   conflict check when editing a booking now uses the exact same “is this slot taken”
   rule as the public booking form; several date/time comparisons now use the site’s
   own timezone instead of UTC; and a handful of smaller hardening and consistency
   fixes throughout.
 * Trimmed older changelog entries to keep this file under the WordPress.org readme
   length limit.

#### 1.0.77

 * Feature: optional online payment for verified bookings through the separately
   installed EffortLess Easy Online Payment plugin. Turn on “Enable payment integration”
   in Settings (only available when that plugin is active) and a verified booking’s
   recap page shows a “Pay Now” button, which creates a one-off product in the payment
   plugin (using its own documented data model, never by modifying its code) priced
   at that exact booking’s total in TWD, and embeds its own checkout form. Since
   the payment plugin confirms payment client-side with no page it navigates back
   to, this plugin polls its own status endpoint in the background and marks the
   booking paid — and sends the existing payment-confirmation email — as soon as
   that payment plugin’s own order record shows the payment completed.
 * Removed the “Enable Payment Integration” setting’s dead state from 1.0.76 (it
   stopped doing anything once the vulnerable self-service payment endpoint was 
   removed); it now does what its label always said, via the integration above.
 * Fixed frontend assets (booking form CSS/JS) only loading when a shortcode was
   found in a page’s raw content; they now also load correctly when a shortcode 
   renders from a widget or a block template.

#### 1.0.76

 * Security/Fix: full code-review fix round. An Editor-role user (a role this plugin
   can grant plugin access to) could redirect the network-wide booking-notification
   email address, which carries customer name/email/phone, to an address of their
   choosing; propagating that address network-wide now requires a network administrator.
   The subscribers admin list and delete action were not scoped to the current site,
   exposing another site’s subscriber emails; both are now site-scoped, matching
   how subscription itself already worked. The booking-form CAPTCHA could be solved
   once and replayed indefinitely; it is now single-use (the expected answer is 
   held in a short-lived transient keyed by a random, single-use challenge id, never
   derived from WordPress’s own salts) and the subscription forms now require the
   same CAPTCHA, which they previously skipped entirely.
 * Fixed a multisite access-scope gap: switching Roles With Access from Global to
   Per-site left every site but the current one holding whatever role list Global
   scope had last pushed to it, until that site’s next version-triggered sync; the
   switch now re-syncs every site immediately.
 * Fixed a booking-slot race condition: two near-simultaneous submissions for the
   same date/slot could both pass the availability check and both be inserted; the
   second insert is now detected and rolled back with a “slot already booked” response
   instead of silently double-booking.
 * Fixed missing required-field and email-format validation on booking submission;
   a request missing a field or supplying an invalid email previously created an
   unreachable booking that permanently held its slot.
 * Removed the “payment success” self-service endpoint, which had no real payment
   gateway behind it and authenticated only on a token the customer already legitimately
   holds — any customer could mark their own booking paid. The pricing/settings 
   fields it did not gate are unaffected.
 * Fixed the admin hook suffixes used to load this plugin’s admin CSS/JS: they were
   hardcoded to their English-language form, so on a non-English site the Settings
   screen’s “Send Test Email” button silently never worked (no localized script 
   was ever enqueued).
 * Fixed a double-notification race: two near-simultaneous visits to the same booking-
   verification link could both send the admin the “booking verified” notification;
   only the request that actually transitions the booking’s status now sends it.
 * “Notify subscribers” on adding a new date is now an explicit, unticked-by-default
   checkbox instead of firing automatically on every date added, and only emails
   the current site’s own verified subscribers (previously it queried every site’s
   subscribers regardless of which site added the date).
 * The available-dates cache is now a single network-wide cache entry instead of
   one per site, matching the fact that the underlying dates/bookings tables are
   already shared network-wide; previously a booking made on one site could leave
   another site advertising the same slot as available for up to an hour.
 * A subscription to an email already on file but never verified (e.g. the original
   confirmation email was lost) now rotates the token and resends it, instead of
   just reporting “already subscribed” with no way to recover.
 * Removed a dead code path (`ELSBH_Email::send()`, no callers) whose unsubscribe
   link had no token, and fixed an undefined-variable edge case in the booking-modification
   email’s error handling.
 * Moved the subscribers list’s Delete action from running during page render (also
   meant a refresh re-submitted it) to the same admin_init hook every other admin
   action here already uses.
 * Moved an inline `<style>` block out of the booking-recap page into an enqueued
   stylesheet, and gave every admin screen the standard `.wrap` margin override 
   so this plugin’s cards sit centered like the rest of wp-admin.
 * Removed two files that should never have shipped in the release package: a build
   script (`languages/po-to-mo.py`) and this project’s own `CLAUDE.md`. Fixed two`
   phpcs:ignore` annotations that referenced a sniff code from a different toolchain,
   which silently voided the rest of the annotation.

#### 1.0.75

 * Fixed the Donate link, which pointed at the author’s own site instead of the 
   designated donate destination, and added the reusable donate notice on the Settings
   screen.
 * Removed the Plugin URI and Author URI headers, which pointed at the author’s 
   own promotional site.
 * Updated “Tested up to” to WordPress 7.1.
 * Removed a leftover build script (`languages/po-to-mo.py`) and a stray generically-
   named compiled translation file (`languages/messages.mo`) that were not needed
   at runtime.

#### 1.0.74

 * Feature: Access Control scope on multisite — choose “Global” (one role selection
   applied to every site on the network) or “Per site” (each site manages its own).
   The scope and the global role list are managed by network administrators only;
   the capability is synced network-wide on save. Defaults to Global.

#### 1.0.73

 * Feature: Administrators can choose which user roles may access the booking admin
   pages — new “Access Control” section on the Settings page (visible only to administrators);
   selection syncs the `elsbh_manage_bookings` capability across roles. Administrators
   always have access.

#### 1.0.72

 * Feature: Editors can now access all plugin admin pages — new `elsbh_manage_bookings`
   capability granted to the Administrator and Editor roles on activation and on
   upgrade; admin menus and action handlers gated on it instead of `manage_options`

#### 1.0.71

 * Fix: Slot selection broken after moving JS to separate file — jQuery .data() 
   returns integer 1, not string ‘1’; changed strict === to loose == comparison

#### 1.0.70

 * Fix: dates-page add/delete handlers moved to admin_post/admin_init hooks (same
   fix as bookings in v1.0.62) — prevents state mutation after headers sent and 
   eliminates delete-by-GET CSRF risk
 * Fix: booking-recap double DOCTYPE removed — template owns the full HTML document
 * Fix: notify_subscribers() loop wrapped in try/finally to guarantee restore_current_blog()
   on exception
 * Fix: send_verification() blog restore moved into finally block
 * Fix: handle_edit_booking() now validates booking exists and is not in the past(
   server-side enforcement of UI restriction)
 * Fix: pagination/sortable helpers extracted to ELSBH_Admin::pagination_links()
   and ELSBH_Admin::sortable_column() — removes duplication between bookings-page
   and dates-page
 * Fix: booking-form slot-toggle JS moved to dedicated public/js/booking-form-init.
   js — replaces inline script block, enables browser caching

#### 1.0.69

 * Fix: Booking recap page no longer shows theme header/footer — renders a minimal
   standalone HTML page with only the plugin CSS

#### 1.0.68

 * Fix: Removed {name} from subscription_verification template — subscribers only
   provide email, name is never collected

#### 1.0.67

 * Feature: Added {name} to subscription_verification template; added {booking_link}
   to admin_notification, booking_cancellation, booking_modified_admin, and post_visit_thanks
   templates

#### 1.0.66

 * Fix: All email link placeholders ({link}, {booking_link}, {review_link}) revert
   to plain URLs — anchor text is set directly in the template editor

#### 1.0.65

 * Fix: All email link placeholders now use descriptive anchor text — {link} shows“
   Click here to verify” / “View available dates”, {booking_link} shows “View your
   booking details”, {review_link} shows “this link” — raw URLs no longer visible
   in email body

#### 1.0.64

 * Fix: {review_link} placeholder now expands to a plain clickable URL instead of
   the full “We would love your feedback” sentence — surrounding copy belongs in
   the email template

#### 1.0.63

 * Fix: Subscription insert failure on upgraded sites — auto-run DB schema migrations
   on version change via maybe_update_db_schema() (adds missing unsubscribe_token
   column without requiring deactivate/reactivate)

#### 1.0.62

 * Fix: Admin booking row actions (verify, mark_paid, cancel, send_thanks, edit)
   moved to admin_init / admin_post hooks — fires before HTML output so redirect
   works; replaced empty-page issue with proper admin notice at top of bookings 
   page

#### 1.0.61

 * Fix: Admin action redirects now include show_cancelled=1 so cancelled bookings
   remain visible after any action

#### 1.0.60

 * Fix: Remaining Plugin Check DirectDB warnings — esc_sql() on $order_dir, $column;
   suppress comment on $where_sql (built from wpdb->prepare fragments)

#### 1.0.59

 * Fix: Removed load_plugin_textdomain() calls — WordPress 4.6+ auto-loads translations;
   Plugin Check warning resolved
 * Fix: All table name variables wrapped with esc_sql() to satisfy Plugin Check 
   DirectDB sniff

#### 1.0.58

 * Security: Add current_user_can() check to admin booking edit POST handler (C1)
 * Fix: Cancel action redirects with notice when booking is already cancelled (C2)
 * Fix: Booking recap page now renders inside the active theme (get_header/get_footer)(
   C3)
 * Fix: Past dates rejected in process_booking() even if still in available_dates(
   I2)
 * Fix: Subscribers table gets UNIQUE KEY (email, site_id) to prevent race-condition
   duplicates (I3)
 * Fix: Plugin assets enqueued only after token validation in handle_verification()
   and handle_unsubscribe() (I5)
 * Fix: remove_action(‘wp_mail_failed’) moved into finally block in send_booking_modified()(
   I6)
 * Fix: (int) casts on DB values in backfill_booking_totals(); skip rows with zero
   persons (I7)
 * Fix: Admin email not propagated to network sites if sanitize_email() returns 
   empty string (I8)
 * Fix: elsbh_message removed from URL after display via history.replaceState (I1)
 * Fix: mark_past_bookings_completed() guarded by daily transient — runs at most
   once per day (M1)
 * Fix: Redundant elsbh_load_classes() call removed from activation hook (M4)
 * Security: CAPTCHA range widened to 1–50 and per-request nonce added to hash (
   M5)
 * Fix: get_404_template() used instead of get_template_part(‘404’) for block-theme
   compatibility (M6)
 * Security: Separate unsubscribe_token column added; verification token no longer
   reused in unsubscribe links (M7)
 * Fix: Deprecated $GLOBALS[‘phpmailer’] access removed; rely on wp_mail_failed 
   hook exclusively (M8)
 * Fix: clean_email_content() HTML nesting fix applied only to Gutenberg-generated
   content (M3)

Older changelog entries (1.0.56 and earlier, back to 0.9.13) have been trimmed from
this file to stay within the readme length limit. See the plugin’s git history for
the full history.

## Meta

 *  Version **1.0.89**
 *  Last updated **1 day ago**
 *  Active installations **Fewer than 10**
 *  WordPress version ** 6.2 or higher **
 *  Tested up to **7.1.3**
 *  PHP version ** 7.4 or higher **
 * Tags
 * [booking](https://wordpress.org/plugins/tags/booking/)[email verification](https://wordpress.org/plugins/tags/email-verification/)
   [multisite](https://wordpress.org/plugins/tags/multisite/)
 *  [Advanced View](https://wordpress.org/plugins/effortless-simple-house-booking/advanced/)

## Ratings

No reviews have been submitted yet.

[Your review](https://wordpress.org/support/plugin/effortless-simple-house-booking/reviews/#new-post)

[See all reviews](https://wordpress.org/support/plugin/effortless-simple-house-booking/reviews/)

## Contributors

 *   [ domclic ](https://profiles.wordpress.org/domclic/)

## Support

Got something to say? Need help?

 [View support forum](https://wordpress.org/support/plugin/effortless-simple-house-booking/)

## Donate

Would you like to support the advancement of this plugin?

 [ Donate to this plugin ](https://id7.dev/donate/)