EP Booking
EP Booking is a full appointment-scheduling system. Services, staff, availability schedules, a multi-step booking form your customers fill out on your site (in their own timezone), Stripe payments, calendar invites, self-serve rescheduling, a multi-tier reminder ladder, public per-service booking pages, an embeddable widget for any website, signed webhooks, an admin calendar, and (via the companion add-on) automatic Zoom meeting creation.
This page documents EP Booking 2.4.45. If you are on a 1.x version, take the update from your admin Updates screen; the upgrading section covers the one setting to check first.
Published by ElmsPark Studio.
Overview
Section titled “Overview”What it does end-to-end:
- You define services (haircut, consultation, massage) with price and duration.
- You define staff with individual availability schedules, which services they offer, and optionally a personal calendar feed that blocks their slots.
- A customer visits your site (or your public booking page, or the widget embedded on another site), picks a service, picks a staff member (optional), picks a date and a time slot, with every time shown in their own timezone.
- They enter their details, optionally pay via Stripe, and confirm.
- Automated emails go out: a confirmation carrying a calendar invite (.ics), then reminders on your configured ladder (up to 7 days, 24 hours and 1 hour before).
- The customer can reschedule or cancel themselves from links in the confirmation email, within your configured window.
- Your admin panel shows the booking in a filterable list and on a month calendar. You can confirm, cancel, reschedule or refund from the admin.
- If you use webhooks, your CRM or automation platform is notified of every booking event, with an HMAC signature to verify.
- If EP Booking Zoom is installed, a Zoom meeting was created automatically and the link is in the confirmation email and the invite.
What EP Booking is NOT: a calendar app, a resource scheduler for rooms, or a class-booking system for group events. It is appointment-by-appointment scheduling between one customer and one staff member.
Requirements
Section titled “Requirements”- PageMotor 0.10.3b or later (the 2.x line relies on 0.10 core plugin APIs; 1.x supported 0.8.2b+)
- EP Suite base class (bundled)
- EP Email (required for notifications)
Optional add-ons:
- EP Booking Zoom for auto-created Zoom meetings
- EP Cron for reliable reminder delivery on quiet sites (without it, reminders piggyback on page loads)
- EP Newsletter to offer opt-in on the booking form
- EP GDPR for consent logging
- EP Affiliate to attribute bookings to referrers
Installation
Section titled “Installation”ep-booking.zipcomes with an EP Suite licence, and ElmsPark supplies it directly (see EP Suite plugins); after install it updates through your site’s Updates screen.- Upload via Plugins → Manage Plugins. Activate.
- Work through the settings sections in this order: General → Services → Staff → Categories → Booking Rules → Notifications → Form Design → Payments → Booking Form.
Upgrading from 1.x
Section titled “Upgrading from 1.x”The 2.x line converts your bookings to be anchored in universal time (UTC), so daylight-saving changes and international customers can never shift an appointment. The conversion runs automatically on your first admin visit after updating, and it uses one setting to interpret your existing bookings:
Before you update, check Settings → General → Business Timezone and make sure it names your actual business timezone (for example Europe/London). Everything in 2.x derives from it: availability, slot generation, reminders, invites and the one-off conversion of your existing bookings.
Everything else is opt-in. Rescheduling, public pages, webhooks and round-robin assignment are all off by default, so nothing about your live booking flow changes until you switch a feature on.
Setting up the basics
Section titled “Setting up the basics”General
Section titled “General”- Business name, address, phone for notification emails.
- Opening / closing times are the outer envelope of when bookings are possible. Individual staff schedules can be tighter.
- Business Timezone. The single most important setting. All availability, booking maths and reminders derive from it.
Services
Section titled “Services”Create each bookable service with:
- Name (e.g. “60-minute massage”).
- Category (optional grouping).
- Duration in minutes.
- Price. Set to 0 for free bookings.
- Require payment? Per-service toggle. Off for free or pay-on-arrival services.
- Active? Inactive services don’t appear on the booking form.
Create each staff member with:
- Name and photo (optional).
- Availability schedule, a recurring weekly pattern (e.g. Mon-Fri 9-5, Wed off).
- Holiday blocks, specific date ranges to mark unavailable.
- Services offered, picked from your service list.
- Busy calendar (ICS URL), optional. Paste a secret ICS address from their Google, Outlook or Apple calendar and events on it block their booking slots. See external calendar sync.
- Block with EP Calendar entries of, optional, shown when EP Calendar is active. Pick a site user and every entry that user makes in EP Calendar blocks this staff member’s slots straight away. See external calendar sync.
Categories
Section titled “Categories”Optional. Groups services for display on the booking form and the [booking-services] catalog shortcode.
Booking Rules
Section titled “Booking Rules”- Minimum advance time. Can’t book less than N hours before the slot.
- Maximum advance time. Can’t book more than N days ahead.
- Default duration for services that don’t override.
- Time slot interval. How finely slots are offered: 15, 20, 30, or 60 minutes.
- Cancellation window. Customer can cancel (or reschedule) themselves up to N hours before the booking.
- Self-Serve Rescheduling. Adds a reschedule link to confirmation emails so customers can move their own appointment. Off by default.
- “Any Available” Assignment. How a booking is assigned when the customer picks “Any Available”: List order (legacy) always favours the first listed staff member; Least recently booked (round-robin) shares work evenly across the team. See round-robin assignment.
- Auto-confirm? If off, bookings start in Pending and you manually confirm each one.
Notifications
Section titled “Notifications”Four emails are configurable with templates:
- Confirmation, sent immediately after booking, with the calendar invite attached.
- Reminder, sent on the ladder you pick in Reminder Schedule: 24 hours + 1 hour before (recommended), 7 days + 24 hours + 1 hour, or a single 24-hour or 1-hour reminder. Each tier sends once, timed from the exact appointment instant; appointments booked inside a tier’s window simply skip that tier.
- Rescheduled, sent after a customer moves their booking, with the updated invite attached.
- Cancellation, sent when a booking is cancelled, with a cancellation invite that removes the event from the customer’s calendar.
Templates support placeholders: {customer_name}, {service_name}, {booking_date}, {booking_time}, {staff_name}, {business_name}, {cancel_url}, {reschedule_url}, and more. The rescheduled template additionally supports {old_booking_date} and {old_booking_time}. An admin-alert toggle emails you too whenever a customer books.
The default confirmation template includes the reschedule link automatically when rescheduling is enabled; if you have written your own template, add {reschedule_url} where you want it.
Form Design
Section titled “Form Design”Visual controls so the booking form matches your site’s look:
- Primary colour, accent colour, text colour.
- Corner rounding on buttons and cards.
- Max width of the form container.
- Card shadow strength.
Group classes (capacity > 1)
Section titled “Group classes (capacity > 1)”EP Booking is not only one-to-one appointments. Set a service’s Capacity above 1 and the slot accepts that many concurrent bookings. Set the Price label to something like per person and the price displays as £12 per person. Use it for yoga classes, group workshops and fitness sessions. Buffer times still apply between the slot and the next.
Buffer times
Section titled “Buffer times”Each service has a buffer before and a buffer after, in minutes. These block the slots immediately adjacent to a booking so staff have time for cleanup or prep. They do not block whole days. For days off, use staff exceptions.
Booking statuses
Section titled “Booking statuses”Bookings move through five states:
| Status | Set by | What happens |
|---|---|---|
| Pending | A new booking when Auto-confirm is off | No confirmation email yet. Waits for admin approval. |
| Confirmed | Auto-confirm on, or an admin clicking Confirm | Confirmation email sent, reminder ladder armed, Zoom meeting created if EP Booking Zoom is installed. |
| Completed | An admin, after the appointment | Closes the booking. Used for reporting. |
| Cancelled | The customer’s cancellation link, or an admin | Cancellation email sent. Stripe refund attempted if Auto-refund is on. |
| No-show | An admin, after a no-show | Closes the booking without a refund. Used for reporting. |
Stripe Payments
Section titled “Stripe Payments”- API keys for test and live modes.
- Currency: GBP, USD, EUR, AUD, CAD, NZD, CHF, JPY.
- Webhook secret so Stripe can notify the plugin when payments settle.
- Per-service payment toggle lets you mix paid and unpaid services in the same booking system.
Timezones
Section titled “Timezones”EP Booking is timezone-correct end to end:
- Your availability is defined in your Business Timezone. A 9-to-5 Tuesday schedule means 9-to-5 in your local wall-clock time, on both sides of a daylight-saving change.
- Visitors see slots in their own timezone. The form detects the visitor’s timezone and renders every slot label in it, with a note saying so, and a day marker when a slot falls on a different calendar day for them. A client in New York booking your 09:00 London slot sees 4:00 am, and both of you hold the same instant.
- Bookings are stored as universal instants. Reminders, invites and rescheduling all work from the exact UTC moment, so nothing drifts when the clocks change.
Calendar invites (ICS)
Section titled “Calendar invites (ICS)”Every confirmation email attaches a standards-compliant .ics invite that lands the appointment in Apple Calendar, Outlook or Google Calendar at the correct local time, with a built-in 1-hour alarm. When a booking is rescheduled the updated invite moves the existing calendar event rather than duplicating it, and a cancellation sends the matching cancellation file so the event is struck through or removed. If EP Booking Zoom is installed, the Zoom join link is the event’s location.
Self-service rescheduling
Section titled “Self-service rescheduling”Enable Booking Rules → Self-Serve Rescheduling and every confirmation email carries a reschedule link. The customer lands on a plain page (no login, no JavaScript required) showing their current booking and a date picker of genuinely open slots. The move applies atomically: the slot is re-checked at the moment of submission, the updated invite goes out, the Zoom meeting is recreated, and pending reminders re-arm for the new time. The cancellation window doubles as the reschedule cutoff.
Public booking pages and the embed widget
Section titled “Public booking pages and the embed widget”Enable Public Pages & Embed → Public Booking Pages and every active service gets its own shareable booking page URL, ideal for email signatures, social bios and QR codes. The settings panel lists the URL for each service.
The same panel gives you a one-line embed snippet:
<script src="https://YOUR-SITE/…/ep-booking-embed.js" data-ep-booking="SERVICE-SLUG" async></script>Paste it into any website (a partner’s site, a landing page, anywhere) and a fully working, auto-resizing booking widget appears there, while your PageMotor site processes the booking exactly as normal. Optional data-staff="ID" pins the widget to one staff member. Copy the snippet from the settings panel rather than this page, as it carries your site’s real URL.
Webhooks
Section titled “Webhooks”Set Webhooks → Webhook URL and EP Booking POSTs a JSON payload to it on four events: booking.created, booking.confirmed, booking.rescheduled and booking.cancelled. Delivery is best-effort with a 3-second timeout; failures are logged, never retried, and can never block or slow a customer’s booking.
Set a Signing Secret and every delivery carries an X-EP-Booking-Signature: sha256=… header, the HMAC-SHA256 of the raw body. Verify it before trusting the payload. Use webhooks to wire bookings into a CRM, an automation platform, or your own dashboard.
The admin Calendar
Section titled “The admin Calendar”The Calendar section of the settings screen shows a month grid of every booking, colour-coded by status, with customer and service details on hover and previous/next month navigation. The bookings list remains the place to act on a booking; the calendar is the at-a-glance view of the month’s shape.
Round-robin staff assignment
Section titled “Round-robin staff assignment”By default, “Any Available” bookings go to the first listed staff member who is free (the behaviour of every earlier version). Switch Booking Rules → “Any Available” Assignment to Least recently booked (round-robin) and the work is shared: each slot is offered under the team member who was booked longest ago, with ties broken by fewest upcoming appointments, then list order. Staff-specific bookings and each person’s exclusive hours are unaffected; only the choice among equally available team members changes.
External calendar sync (free-busy)
Section titled “External calendar sync (free-busy)”Give any staff member a Busy calendar (ICS URL) in the Staff editor and events on that calendar block their booking slots. This is the provider-agnostic route: Google Calendar, Outlook and Apple Calendar all offer a secret ICS address for exactly this purpose, with no accounts to connect and no API keys.
- Timed events and recurring events (daily, weekly, monthly and yearly, including “the last Friday” and Outlook’s “last weekday of the month”) are honoured, and dates removed in the source calendar stay open. All-day events block slots only when All-day calendar events is switched on under Booking Rules (it is off by default, so an all-day reminder or birthday does not close a whole day).
- Feeds are checked at most every five minutes, so a change on the external calendar takes up to five minutes to affect the booking form.
- If a feed is temporarily unreachable, the last fetched copy is used; if there is no copy at all, slots stay open rather than your booking page going blank, and the failure is logged.
The ICS URL is a secret: anyone holding it can read that calendar’s events. Use the calendar provider’s “reset private address” if it ever leaks.
With EP Calendar (2.5.0 and later). Instead of copying a calendar address, link the staff member to a site user under Block with EP Calendar entries of. That user’s EP Calendar entries, and any EP Calendar external feed set to block slots for them, then block this staff member’s slots immediately, with no five-minute wait. Cancelled entries never block, all-day entries follow the All-day calendar events setting, and a Busy calendar address keeps working alongside the link. If EP Calendar is switched off, bookings carry on as before.
Shortcodes
Section titled “Shortcodes”| Shortcode | Purpose |
|---|---|
[booking-form] | The full multi-step booking form. Can be preset: [booking-form service=60-min-massage] or [booking-form staff=alice] or [booking-form category=wellness]. |
[booking-services] | Service catalog grid. Each service links to a prefilled booking form. |
The customer flow
Section titled “The customer flow”- Customer lands on your booking page and sees the multi-step form.
- Step 1: service — pick from the list (or already preset via shortcode attribute, public page, or embed).
- Step 2: staff — pick a specific staff member, or “any available”.
- Step 3: date — calendar showing which dates have availability.
- Step 4: time — slots for the chosen date, shown in the customer’s own timezone, based on staff schedule, existing bookings and any external busy calendar.
- Step 5: details — name, email, phone, notes. Optional newsletter opt-in and GDPR consent.
- Step 6: pay (if applicable) — Stripe checkout.
- Confirmation — success message plus confirmation email with the calendar invite and, if enabled, the reschedule link.
Admin dashboards
Section titled “Admin dashboards”- Bookings. Filterable list. Status column (Pending / Confirmed / Cancelled / Completed). Actions to change status, cancel, refund via Stripe, or add notes.
- Calendar. Month grid of all bookings, colour-coded by status.
- Customers. Contact records with booking history per customer.
- Services, Staff, Categories. CRUD interfaces for each.
- Import / Export. JSON and CSV for bulk moves between sites.
Import / Export
Section titled “Import / Export”Round-trips your booking structure between sites. Use it to move a sandbox configuration to live, to back up before a big change, or to stand a new site up from a config an AI wrote for you.
What an export actually contains
Section titled “What an export actually contains”Five things, and only these five: categories, services, staff, staff-service assignments, and weekly availability.
Worth being precise about what is not in an export, because it is easy to assume otherwise:
- Settings are not exported. Business details, timezone, booking rules, form design, notification copy and integration toggles all stay on the site. An export is not a settings backup.
- Staff exceptions are not exported. Per-staff holidays, days off and custom hours stay behind too.
- Bookings and customer records are not exported. They live on the site they were made on.
Because no settings leave the site, no Stripe key or webhook secret can leak through an export. The file is safe to share or commit.
File formats
Section titled “File formats”JSON and CSV both round-trip. JSON is easier to edit by hand or with an LLM. CSV is easier to spot-check in a spreadsheet, and uses a ## Section header per section.
Duplicate handling on import
Section titled “Duplicate handling on import”Pick the mode from the Duplicate Handling dropdown before importing:
- Add to existing records (recommended, the default). Existing entries are left alone and only new ones are inserted.
- Replace existing records. Entries matching on name, or email for staff, are overwritten by the imported version.
- Delete all existing records and import fresh. Wipes categories, services, staff and availability before importing. Bookings and customers are not touched.
Generate with AI
Section titled “Generate with AI”The Import/Export dashboard has a Generate with AI panel containing a copy-pastable prompt. Paste it into Claude, ChatGPT or Gemini, answer the interview questions about your business, and you get back a JSON file to drop into the importer. The prompt covers categories, services with capacity and buffers, staff with availability, exceptions and basic settings.
This is also the one route by which settings can arrive on a site through the importer. An export will never contain them, but a hand-written or AI-generated JSON can, and the importer applies them when they are present.
Integrations
Section titled “Integrations”- EP Booking Zoom. Install alongside. Every confirmed booking auto-creates a Zoom meeting; the link lands in the confirmation email and the calendar invite, and the meeting is recreated when a booking is rescheduled.
- EP Cron. When present, reminders ride its heartbeat instead of waiting for a page load, which matters on quiet sites.
- EP Newsletter. Optional opt-in checkbox on the booking form with list selection.
- EP GDPR. Consent logging on booking submissions.
- EP Affiliate. Confirmed bookings fire an affiliate conversion, so referred bookings earn commission.
- Stripe. Payment, webhook verification, and admin-initiated refunds from the bookings list.
Self-service cancellation
Section titled “Self-service cancellation”Every confirmation email includes a tokenised cancel link. The customer clicks it, confirms, and the booking is cancelled with a cancellation invite removing the event from their calendar — no login required. The cancellation window setting controls how close to the appointment they can still cancel (or reschedule) themselves.
How reminders are sent
Section titled “How reminders are sent”There are two paths, and which one you get depends on whether EP Cron is installed.
With EP Cron active, EP Booking registers a task called ep-booking-reminders on the five-minute heartbeat. This is the scheduler of record: reminders fire on time whether or not anybody is browsing the site.
Without EP Cron, the fallback is a check that runs during ordinary page loads, throttled so it runs at most once every 60 seconds. A busy site is fine. A quiet site is not: if nobody visits for three hours, reminders queued in that window go out late by roughly that much.
If reminder timing matters at all, install EP Cron. That is the supported fix, and it is why the ladder can be trusted on a low-traffic site.
Security
Section titled “Security”- Honeypot spam protection on the booking form.
- CSRF tokens on every endpoint.
- Rate limiting per IP so the form can’t be scraped.
- Stripe webhook verification so fake payment confirmations can’t mark bookings as paid.
- Outbound webhook deliveries are HMAC-signed when a secret is set.
- Reschedule and cancel links use one unguessable token per booking, checked together with the booking’s email address.
Troubleshooting
Section titled “Troubleshooting”“The form shows no available slots”
Section titled ““The form shows no available slots””Check:
- A staff member has been assigned to the service.
- That staff member’s availability schedule covers the date range customers are trying to book.
- No holiday block is covering the date.
- Existing bookings haven’t filled every slot.
- If the staff member has a busy calendar URL, events on that external calendar may be blocking the slots. Remember all-day events block the whole day.
“Slot times look wrong to a customer”
Section titled ““Slot times look wrong to a customer””Almost always the Business Timezone. The form deliberately shows each visitor their own local time, so a customer abroad seeing a different clock time than you is correct behaviour, and the form says “times shown in your timezone”. But if times are wrong for local customers too, check Settings → General → Business Timezone names your real timezone.
“Confirmation emails aren’t sending”
Section titled ““Confirmation emails aren’t sending””EP Email handles delivery. Check EP Email’s delivery log. Common causes: SMTP config is wrong, from-address is unverified, or the email queue is stalled.
“Reminders aren’t going out”
Section titled ““Reminders aren’t going out””The ladder needs something to wake it. On busy sites page loads are enough; on quiet sites install EP Cron so reminders ride its heartbeat. Also remember each tier sends once, and an appointment booked inside a tier’s window (e.g. booked 3 hours ahead, 24-hour tier) skips that tier by design.
“My webhook endpoint isn’t receiving events”
Section titled ““My webhook endpoint isn’t receiving events””Deliveries are fire-and-forget with a 3-second timeout, and failures are logged to the PHP error log rather than retried. Check the endpoint responds within 3 seconds, and if you set a signing secret, make sure you are verifying X-EP-Booking-Signature against the raw request body, not a re-serialised copy.
“Stripe webhook says signature invalid”
Section titled ““Stripe webhook says signature invalid””The webhook secret in your EP Booking settings does not match the webhook endpoint secret in your Stripe dashboard. Rotate the secret on both sides.
“I can’t refund a booking from admin”
Section titled ““I can’t refund a booking from admin””Stripe refunds require the original charge to exist on the Stripe side. If the booking was imported from a prior system or paid outside Stripe, the refund button is inactive. Refund through Stripe directly.
“Customers are booking impossible slots”
Section titled ““Customers are booking impossible slots””Check the time slot interval and the staff duration. If a service is 45 minutes and your slot interval is 60 minutes, customers can still book at :00 and :15 adjacent slots. Tighten the interval to 15 minutes, or align durations to your interval.
“The booking form submits but nothing appears in the admin”
Section titled ““The booking form submits but nothing appears in the admin””Check for CSRF or rate-limiting errors in your browser’s network tab. Both return a 403 that shows as a generic error in the form.
“The embedded widget doesn’t appear on the other site”
Section titled ““The embedded widget doesn’t appear on the other site””The snippet must be pasted as-is from the settings panel (it carries your site’s URL), and Public Booking Pages must be enabled: the widget loads the public page in an iframe, so turning public pages off turns the widget off too.
“I deleted a category but the services still exist”
Section titled ““I deleted a category but the services still exist””That is by design and not a bug. Deleting a category clears the category from its services rather than deleting them, so they survive as uncategorised. Reassign them from the Services dashboard, or delete them individually.
“I imported a JSON but my settings didn’t change”
Section titled ““I imported a JSON but my settings didn’t change””An export never contains settings, so a file produced by the exporter has none to apply. Only a hand-written or AI-generated JSON carries a settings block. If you were expecting an exported file to restore your configuration, it will restore your categories, services, staff and availability, and nothing else.
Feedback and corrections
Section titled “Feedback and corrections”For a quick question about this plugin, EP Support inside your admin is the fastest option. The chat widget sits on every EP plugin settings page and knows which one you’re on, with starter questions and links preloaded for that exact screen.
For anything bigger — a bug report, a feature request, or a “how do I…” that needs a real reply — open a ticket at help.elmspark.com. A real person, helped by AI, writes the reply. Usually within a few hours. Tickets don’t disappear into the void.
Changelog
Section titled “Changelog”- Monthly and yearly events in a linked calendar now block every date. When a staff member’s busy calendar address (Google, Outlook or Apple) had a monthly meeting or a yearly event, only its first date blocked booking slots; every later one was left open to be booked. Every occurrence now blocks, including “the second Tuesday”, “the last Friday”, Outlook’s “last weekday of the month” and yearly dates, and dates removed in the source calendar stay open.
- Weekly and daily events block exactly as before.
- Block a staff member’s slots with EP Calendar. When EP Calendar is active, each staff member has a new choice, “Block with EP Calendar entries of”. Pick a site user and every entry that user makes in EP Calendar makes those times unbookable for this staff member, on your booking form and when customers reschedule, straight away: no calendar address to copy and no five-minute wait. External feeds in EP Calendar set to block booking slots for that user count too. Leave it on Off and nothing changes.
- The staff table shows “Blocked by the calendar of …” under the name of each linked staff member.
- All-day calendar entries follow your existing All-day calendar events setting under Booking Rules, which is off by default. Cancelled entries never block. A staff member’s busy calendar address keeps working alongside the link, and both apply.
- If EP Calendar is switched off or cannot answer, bookings carry on exactly as before.
2.4.47
Section titled “2.4.47”- A repeating appointment in a linked calendar keeps its time after the clocks change. When a staff member’s linked calendar (Google, Outlook or Apple) had a weekly or daily event, every repeat after a clock change was placed one hour out. From 25 October a 9 o’clock weekly commitment blocked 8 to 9 instead of 9 to 10, so a customer could book on top of the real appointment. Repeats now keep their local time all year, in the time zone the calendar event was written in.
- A repeat that was deleted from the calendar after a clock change is now left open as it should be. Before, that deletion was missed in the same way.
2.4.46
Section titled “2.4.46”- Settings language menu. The language menu in this plugin’s settings now lists only the languages it is actually translated into, plus English, so you can no longer pick a language that changes nothing.
- Danish. Adds a Danish translation.
2.4.45
Section titled “2.4.45”- A refund that fails in Stripe no longer leaves the booking marked refunded. Stripe can fail a refund days later (for example when the customer’s card has been closed), or cancel one that was still pending. The money then stays with you, but the booking still said “Refunded”. Now the payment goes back to “Paid”, or to the smaller amount that is still refunded, and a note on the booking says what happened. If the customer should still get their money back, refund them again.
- The booking itself (confirmed, cancelled and so on) is not changed, just as when you make a refund.
- One step for you: in your Stripe Dashboard, add the event
charge.refund.updatedto the webhook you set up for EP Booking, so that failed refunds reach your site. The Stripe settings page now lists it with the other events.
2.4.44
Section titled “2.4.44”- Manual bookings you add in the admin check the phone number too. The check that a phone number looks like one only ran on the public booking form, so “123” typed into Manual Booking was still accepted. The same rule now applies there, with the same message.
- The embed code is ready to paste for each service. Public Pages & Embed used to show one embed line with SERVICE-SLUG in it, to be replaced by a slug you had to work out yourself. It now lists every service with its booking page link and its own embed code, with the right slug already filled in. Copy the one you want onto the other website.
2.4.43
Section titled “2.4.43”- A returning customer’s new phone number is kept. When someone who had booked before booked again with a different phone number, the new number was quietly ignored and their bookings kept showing the old one, so you could end up ringing a number they no longer use. The latest number they give now replaces the one on file. This applies to bookings from your booking form and to bookings you add by hand in the admin.
- The same number written differently (with or without spaces, for example) leaves the stored one as it is, and a number that doesn’t look like a phone number is still refused. The customer’s name on file is not changed.
2.4.42
Section titled “2.4.42”- With EP Connect 1.1.2, EP Connect decides for itself when a booking is confirmed. EP Booking no longer adjusts EP Connect’s internal settings to stop unpaid bookings being announced. Nothing changes that you can see. With an older EP Connect it works as in 2.4.41.
2.4.41
Section titled “2.4.41”- Manual bookings you add in the admin check the phone number too. The check that a phone number looks like one only ran on the public booking form, so “123” typed into Manual Booking was still accepted. The same rule now applies there, with the same message.
- The embed code is ready to paste for each service. Public Pages & Embed used to show one embed line with SERVICE-SLUG in it, to be replaced by a slug you had to work out yourself. It now lists every service with its booking page link and its own embed code, with the right slug already filled in. Copy the one you want onto the other website.
2.4.40
Section titled “2.4.40”- A returning customer’s new phone number is kept. When someone who had booked before booked again with a different phone number, the new number was quietly ignored and their bookings kept showing the old one, so you could end up ringing a number they no longer use. The latest number they give now replaces the one on file. This applies to bookings from your booking form and to bookings you add by hand in the admin.
- The same number written differently (with or without spaces, for example) leaves the stored one as it is, and a number that doesn’t look like a phone number is still refused. The customer’s name on file is not changed.
2.4.39
Section titled “2.4.39”- The summary cards at the top of the settings page now open their section. Services, Staff, Bookings and Payments looked like panels you could open, and on a phone it was natural to try, but they did nothing. Each card now opens its own section and scrolls to it, and shows a small “Open” so it is clear they can be tapped.
- The booking form checks that a phone number looks like one. A number such as “123” used to be accepted. The form now asks for a full number, 7 to 15 digits, and allows the usual extras: a leading +, spaces, dashes, dots and brackets, so “+44 (0)1234 567-890” is fine. The same check runs on your site as well as in the customer’s browser, and it applies whenever a phone number is entered, whether or not you require one.
2.4.38
Section titled “2.4.38”- The Bookings list can be scrolled sideways on a phone. On a narrow screen the list was cut off after the Date column, so Status, Payment and the View button that leads to Confirm could not be reached at all. The list now scrolls sideways, and keeps a readable width instead of squeezing each date onto three lines. The other admin lists (Customers, Services, Staff, Categories) get the same treatment.
- Confirmation emails tell the customer what the appointment involves. If you have written a description for a service (the text shown under it on the booking form), the confirmation now includes it under “About your appointment”. Services without a description are unchanged.
- If you write your own confirmation message, the new
{service_description}placeholder adds the same text wherever you put it.
2.4.37
Section titled “2.4.37”- Booking invites now say who they are from. The calendar invite in booking emails had no organiser. Apple Mail, Gmail and Outlook showed it properly anyway, but Thunderbird prints ”… has invited you” and left the name blank. The invite now names your business as the organiser, using the address your booking emails are sent from, and lists the customer as attending.
- The name shown is your business name from the General settings. If you have not set one, your EP Email sender name is used, and failing that your site title.
- The customer is marked as already accepted, with no reply requested, so their calendar does not send “Accepted” messages back to you.
- If a booking is made with the same email address your booking emails are sent from (for example when you book yourself to test), the invite is left exactly as before, because an invitation from yourself to yourself confuses calendar apps. To see the new line, test with a different address.
2.4.36
Section titled “2.4.36”- Stripe booking payment notifications keep working while you change your webhook signing secret. When you roll the secret in Stripe, Stripe signs each notification with both the old and new secret for a while. The site only checked one of those signatures, so some genuine notifications could be turned away during that time. It now accepts the notification if either signature matches.
2.4.35
Section titled “2.4.35”- Fixes Stripe card payments and Stripe webhooks failing since the signing secret and API keys started being stored encrypted. The Stripe webhook was rejecting every event with “Webhook signing secret not configured”, and the frontend booking checkout could not create a card payment, because both read those settings without decrypting them first. Both now read the saved values correctly, so paid bookings, refund and cancellation events from Stripe, and card checkout on the booking form work again.
2.4.34
Section titled “2.4.34”- Booking emails sent through EP Email now carry a calendar invite you can add. The invite was being built, but it was handed to EP Email in a form it did not read, so it arrived as an empty file, or not at all, and there was no “add to calendar”. It now arrives as a proper calendar invite on sites that send through SMTP or the server’s own mail. Sites sending through Mailgun, Brevo, SendGrid or the ElmsPark relay still do not get the attachment, because those senders do not pass attachments on yet; that needs a change to EP Email’s senders.
- A booking email that fails to send is no longer reported as sent. When EP Email turned an email down, for example for a missing sender address, the cancel and reschedule pages still said a confirmation email had been sent. They now only say so when it was, and the reason goes to the error log.
- “Contact us directly” now says how. When a customer tries to cancel or reschedule after the window has closed, the message now shows your business phone number as a tap-to-call link, if one is set under General. The same goes for the message shown when self-serve rescheduling is switched off.
- A signing secret or Stripe key that PageMotor itself had encrypted is now recovered. On PageMotor 0.11.3 and later, core encrypts password fields when you save them, and one placed inside a settings section was encrypted in a way core never undoes. If that happened to your webhook signing secret or a Stripe key, this update reads it back and stores it the plugin’s own way, the first time the site loads. If it cannot be recovered, the error log says so and asks you to enter it again.
- If the cancel or reschedule email fails with an error, the customer still sees the confirmation page. An error at that point could leave them on the home page with no message, even though the change had been saved. The cause is now written to the error log.
2.4.33
Section titled “2.4.33”- The webhook and Stripe settings now tell your browser not to fill in your login details. Each secret in these settings is a password box with an ordinary text box above it, which browsers mistake for a login form. So they filled in the username and password saved for your site: your username ended up in Webhook URL, and your site password in Signing Secret, ready to be saved as a secret. The boxes now tell browsers they are not a login form, which is the standard signal for browsers to leave them alone.
- If Webhook URL or a Stripe key box shows your username, clear it before saving. If you saved it like that, nothing was sent: the plugin only sends to an address starting with http.
- No change to how bookings, payments or webhooks work.
2.4.32
Section titled “2.4.32”- The admin Calendar no longer closes when you move to the next or previous month. Next and Prev reload the settings page at the new month, and PageMotor opens every settings section closed after a reload, so the Calendar snapped shut each time and had to be opened again to see the month you had just asked for. It now reopens itself and scrolls into view after a month change.
- No change to what the Calendar shows or to how bookings work.
2.4.31
Section titled “2.4.31”- A staff member’s busy calendar address no longer looks empty after the page is reloaded, and no longer gets wiped by an unrelated save. The address was saved correctly, but when the Staff page was first opened, the list of staff did not carry it, so pressing Edit showed an empty box. Saving that staff member again, for example to change a phone number, then saved the empty box and removed the calendar. The Edit form now always shows the saved address.
- If a staff member’s calendar seems to have disappeared, paste the address back in once and press Save.
- No change to how bookings are checked against the calendar.
2.4.30
Section titled “2.4.30”- “Test this calendar” now says so when the server was slow to look up the calendar’s address. When a hosting server took too long to look up an address such as calendar.google.com, the test said the server was “being blocked from fetching it”, which sent people looking for a block that was not there. It now says the lookup was slow, that the address itself is fine, and to test again in a moment. It also says that bookings keep using the last copy of the calendar while a slowdown lasts.
- A lookup that fails outright gets its own message too: check the address was copied in full, and if it opens in your browser, the server’s address lookup is failing, which is a hosting matter.
- No change to how bookings are checked against the calendar.
2.4.29
Section titled “2.4.29”- “Test this calendar” now tells you when the address is not saved yet. Testing an address checks it but does not store it; only Save does. Nothing on screen said so, so an address could be pasted in, tested, and then lost on the next refresh. When the address in the box is not the one you last saved, the test result now ends with “This address is not saved yet. Press Save to keep it.”
- Opening a staff member to edit, or starting a new one, now clears the previous test result, so it cannot be mistaken for a result about this person.
- No change to how bookings are checked against the calendar.
2.4.28
Section titled “2.4.28”- “Test this calendar” now says clearly what it counted. A successful test used to report something like “266 event(s), 0 of them in the next 30 days”, which looked broken on a calendar full of upcoming birthdays and holidays. It now says how many busy periods will block this person’s booking slots in the next 30 days, and whether all-day entries were counted. By default they are not, because all-day entries such as birthdays and holidays never block slots unless you turn on All-day calendar events under Booking Rules.
- The test now follows that All-day calendar events setting. On a site with it turned on, all-day entries used to be left out of the count even though they did block slots.
- The count now comes from the calendar the test has just fetched, so an event you have just added is counted as soon as your calendar provider publishes it. It no longer waits up to five minutes for a saved copy to expire, and the test fetches the calendar only once.
- No change to how bookings are checked against the calendar.
2.4.27
Section titled “2.4.27”- The “Test this calendar” button no longer tells you to reset a calendar address that is working. When Google, Outlook or Apple was limiting requests from your server (a 429 reply), the test told you the secret address had probably been reset and asked you to paste a new one. Resetting would not help, and it breaks the old address everywhere else you use it. A 429 now says the provider is limiting this server for a while, that the address itself is fine, and to test again later.
- A reply showing the provider is having trouble at its end (500 and above) now says so too, instead of blaming the address.
- No change to how bookings are checked against the calendar: while a feed cannot be fetched, the last copy is still used.
2.4.26
Section titled “2.4.26”- Fixes a doubled cache-busting tag on its booking-form stylesheet and scripts. On PageMotor 0.11 and later the page asked for each file with two version tags on the end of its address (
?v=…?v=…), because the core had started adding its own tag and the plugin was still adding one too. The files loaded correctly, so nothing was visibly broken; the addresses were just malformed and every cache saw a longer key than it needed. The plugin now leaves the tag to the core on 0.11 and later, and still adds its own on older cores, where nothing else would. - No change to what these files do.
2.4.25
Section titled “2.4.25”- Fixes a crash on the booking form when an older EP plugin is installed on the same site. Submitting the form returned an internal error and nothing was saved or sent. EP plugins share one common code library, and whichever copy loads first is the one every EP plugin on that site uses, so a single out-of-date plugin could leave this one calling a spam check its copy did not have. The check now carries its own fallback and no longer depends on another plugin being up to date.
- No change on a site where this never happened: the same spam check runs, and nothing else changed.
2.4.24
Section titled “2.4.24”- Fixes stored keys and passwords reading as empty after a PageMotor 0.11.3 or 0.11.4 update. After the core update, every secret this plugin had encrypted at rest came back blank, so anything that needed it failed with an authentication error until the value was typed in again. Nothing was deleted: the encrypted value was still in the settings row, but PageMotor 0.11.3 moved the site secret that opens it, and this plugin was still looking in the old place. It now finds the secret in both places, so an existing value opens again without re-entry, and a value that was re-entered in the meantime keeps working and is moved back under the site secret.
- If you updated PageMotor and then re-entered a key or password, there is nothing to do. If you updated and have not re-entered it, this release restores it on the next page load.
2.4.23
Section titled “2.4.23”- Fixed: installing a second plugin that also takes Stripe payments could take the whole site down. Five plugins in the suite share the same Stripe helper. With any two of them switched on, the second to load failed outright and PageMotor disabled it to protect the site, so turning on a new Stripe-capable plugin silently cost you the one you already had, with nothing obvious to explain it.
- The guard meant to prevent that had never been able to work, for reasons of when the code is read rather than when it runs. It is now written so that it does. Verified by switching two of these plugins on together: previously the site returned an error and one plugin was disabled, now both load cleanly and payment signature checking still works.