Booking
v1.4.17Take appointments on your own site — services, providers, time slots and calendar sync (two-way Google/Outlook, or a no-login subscription feed), all from one WPStack panel with no third-party booking service.
Overview
The Booking module turns any WordPress page into a self-serve appointment scheduler. Define your services, publish a booking page, and manage every appointment from one panel.
Booking is built for service businesses — consultants, studios, clinics, salons and agencies — that want clients to book (and optionally pay) online without bolting on a separate plugin or a paid scheduling service. Every appointment stays inside your own site.
What you can do
- Create unlimited services, each with its own duration, buffer, price and custom intake fields — or offer several duration & price options per service
- Add providers (staff) and assign them to time slots
- Publish availability as specific-date or recurring weekly time slots with a capacity per slot — one window can serve several services at once
- Take full payment at booking with Stripe, or collect payment on location
- Send automatic confirmation emails to the client and notifications to the provider
- Sync two ways with each provider’s Google Calendar or Outlook Calendar
- Or skip the setup with a no-login calendar subscription — each provider gets a private link/QR that drops bookings onto their phone
- Translate every front-end label, with one-click presets for EN / NL / FR / DE / ES
Requirements & compatibility
Booking runs on any modern WordPress host. Payments and calendar sync use their own free accounts.
| Requirement | Minimum | Recommended |
|---|---|---|
| WordPress | 6.0 | 6.5 or newer |
| PHP | 7.4 | 8.1 or newer |
| Permalinks | Pretty permalinks | Required for Outlook sync |
| HTTPS | Required for payments & calendar OAuth | Site-wide |
Optional integrations
| Integration | Used for | Needed? |
|---|---|---|
| Stripe | Online card payments | Only if you take payment |
| Google Calendar | Two-way calendar sync | Optional |
| Outlook Calendar | Two-way calendar sync | Optional |
| Calendar subscription (ICS) | No-login feed to any calendar app | Optional |
Installation & activation
Booking ships inside WPStack — there’s nothing extra to download. Switch it on per site from the modules panel.
Open the WPStack modules panel
In your WordPress admin, go to WPStack → Modules and find Booking.
Activate Booking
Flip the Booking toggle to on. A new Bookings item appears in the WPStack menu.
Set your basics
Open Bookings → Settings → General and set your time zone, currency and date/time format.
Add a service, provider and slot
Create at least one service, one provider, and one slot that ties them to a time.
Publish your booking page
Add the [wpstack_booking] shortcode (or the Elementor widget) to any page, then publish.
The four building blocks
Booking is made of four connected pieces. Set them up in this order.
1 · Services
What a client books — e.g. “30-min consultation”. Holds duration, price, payment mode and any custom fields — and can offer several duration/price options. Under Bookings → Services.
2 · Providers
The people who deliver the service (staff). Each provider can connect their own Google or Outlook calendar. Under Bookings → Providers.
3 · Slots
When a service is available and by whom. A slot links one or more services + a provider to either a specific date or a recurring weekly schedule, with a capacity. Under Bookings → Slots.
4 · Bookings
Every appointment a client makes lands here, where you confirm, reschedule, cancel or re-sync it. Under Bookings → Bookings.
Services
A service is the thing clients pick first. Create as many as you like under Bookings → Services.
| Setting | Type | Default | What it does |
|---|---|---|---|
| Name & description | text | — | Shown on the booking page. An optional image can be added too. |
| Duration | number (min) | 30 | How long one appointment takes. Drives how slots are split into times. |
| Gap | number (min) | 0 | Buffer added after each appointment before the next start time. |
| Price | number | 0 | Shown to the client. A price of 0 displays as free. |
| Duration & price options | single / multiple | Single | Switch a service to multiple options, each with its own duration and price (e.g. 60 min €50, 90 min €70). Clients pick one before choosing a time; it sets the appointment length and the amount charged. Single stays the default. |
| Payment mode | select | On location | on_location (pay in person) or online (pay the full amount now via Stripe). |
| Min notice | number (hrs) | 0 | How far in advance a client must book — blocks last-minute times. |
| Max days | number (days) | 60 | How far into the future clients can book. |
| Custom fields | builder | none | Extra intake questions (text, number, select, checkbox…) captured at booking and shown on the booking + in the calendar event. |
| Payment gateways | select | Stripe | Which connected gateway online payments use. |
Providers
Providers are your staff. Add them under Bookings → Providers, then assign them to slots.
Each provider has a name, email, phone and short bio. The bio and name appear on the booking page when a slot is assigned to them. A provider’s email is used for the “new booking” notification.
Calendar subscription (no login)
The easiest way to get appointments onto a provider’s phone — a private calendar link they subscribe to once, with no Google/Outlook login.
Under Settings → Calendar, choose Calendar subscription (no login). Each provider then gets a private ICS feed, shown as a QR code and a copy link on their Providers screen. They scan it (or paste it into Apple, Google or Outlook Calendar once) and every booking appears on their phone automatically. It is read-only and refreshes on the calendar app’s own schedule (about hourly).
- One link works for Apple, Google and Outlook — it’s the standard iCalendar format
- No OAuth, no API keys — nothing to configure per provider
- The link carries a private secret token; Reset link revokes old subscriptions
- The QR is generated on your own server — no external calls; the copy link is the backup
Availability (Slots)
Slots decide when each service is bookable, by which provider, and how many people can book at once.
Specific vs recurring
- Specific — a single calendar date (e.g. a one-off workshop on 12 March).
- Recurring — a weekly schedule with per-day start/end times (e.g. Mon–Fri 09:00–17:00).
| Setting | Type | Default | What it does |
|---|---|---|---|
| Services | checkboxes | — | One or more services this availability window applies to — tick several to reuse the same schedule across services. |
| Provider | select | — | Who delivers it. Their connected calendar blocks conflicting times. |
| Type | specific / recurring | specific | A single date, or a repeating weekly schedule. |
| Start / end time | time | — | The daily window the service’s duration is split across into individual times. |
| Capacity | number | 1 | How many bookings each time can take (e.g. a group class). |
Managing bookings
Every appointment appears under Bookings → Bookings, grouped by upcoming, completed, cancelled and past.
- Statuses — confirmed, completed and cancelled. Completing or cancelling removes the event from the provider’s calendar; confirming (re)adds it.
- Reschedule — move a booking to a new date/time; the calendar event moves with it.
- Re-push to Calendar — force a fresh sync of a single booking if it ever drifts.
- Payment status — paid, pending or failed is shown for services paid online.
Settings reference
The Settings screen is split into tabs. Here’s what each one controls.
| Setting | Type | Default | What it does |
|---|---|---|---|
| General | tab | — | Time zone, currency & symbol, and date/time format. |
| tab | — | Confirmation email (sender, subject, message) and provider notifications, with placeholders like {service} {provider} {date} {time} {duration} {name}. | |
| Calendar | tab | — | Pick Google, Outlook, or Calendar subscription (no login). For Google/Outlook enter your API credentials; for subscription there’s nothing to configure — each provider gets a QR/link on their screen. |
| Labels | tab | — | Override every front-end label; one-click language presets for EN / NL / FR / DE / ES. |
| Style | tab | — | Service-grid columns and the step/button accent colors. |
| Payment | tab | — | Connect and configure the Stripe gateway. |
| Shortcodes | tab | — | The booking shortcode and a quick setup checklist. |
Embedding the booking page
Place the booking flow anywhere with a shortcode or the Elementor widget.
The full booking flow: service picker, date & time selection, details form, payment (if enabled) and confirmation.
[wpstack_booking]
[wpstack_booking service="12"]Payments (Stripe)
Collect payment at booking with Stripe, or take payment on location.
Connect Stripe
Under Settings → Payment, enter your Stripe keys.
Set the service to “online”
On a service, set Payment mode to online and choose Stripe as the gateway. Leave it on_location to collect payment in person.
Test before going live
Use Stripe test keys to confirm the checkout, then switch to live keys.
Google Calendar setup
Two-way sync using your own Google API credentials — bookings appear on the provider’s calendar, and their busy events block those times.
Create the Google credentials
Create a Google Cloud project
At console.cloud.google.com, create (or pick) a project.
Enable the Calendar API
In APIs & Services → Library, enable Google Calendar API.
Configure the consent screen
Set user type External, add the .../auth/calendar scope, and publish to Production so refresh tokens don’t expire after 7 days (the “Testing” limit).
Create an OAuth client
In Credentials → Create credentials → OAuth client ID, choose Web application.
Add the redirect URI
Copy the Redirect URI shown in Bookings → Settings → Calendar → Google (it looks like https://your-site/?wpstack_gcal_callback=1) and paste it under Authorized redirect URIs.
Paste the credentials
Copy the Client ID and Client Secret into Settings → Calendar → Google and pick Google as the active provider. Save.
Connect each provider
Generate a link
Open Bookings → Providers → (a provider) and click Generate Authorization Link (valid 24 hours).
Send it to the provider
They open it, click Connect with Google, and choose their Google account.
Verify
The provider row shows Google (connected). Use Test Connection on their screen any time.
Outlook Calendar setup
Two-way sync with Outlook / Microsoft 365 using Microsoft Graph and your own app registration.
Register the app
New registration
At entra.microsoft.com → App registrations → New registration, give it a name.
Account types
Choose Any Entra ID Tenant + Personal Microsoft accounts so any provider’s calendar can connect.
Redirect URI
Platform Web, and paste the URI from Settings → Calendar → Outlook — https://your-site/wpstack-outlook-callback. It has no query string (Microsoft rejects those) and needs pretty permalinks.
Client secret
In Certificates & secrets → New client secret, copy the secret Value (not the Secret ID) immediately — it’s masked after you leave.
Permission
In API permissions, add Microsoft Graph → Delegated → Calendars.ReadWrite.
Paste the credentials
Copy the Application (client) ID and the secret Value into Settings → Calendar → Outlook, pick Outlook as the active provider, and Save.
Connect each provider
Exactly like Google: open a provider, Generate Authorization Link, send it, and they click Connect with Microsoft. The provider row then shows Outlook (connected).
How calendar sync works
The details behind two-way sync — worth knowing before you rely on it.
- Only one calendar is active — the provider you select in Settings → Calendar (Google or Outlook). Configuring both is fine; only the selected one is ever contacted.
- Bookings push out — confirming a booking creates an event on the provider’s calendar; cancelling/completing removes it.
- Busy events block times — anything marked “busy” on the provider’s calendar hides those times on the booking page.
- Up to ~5 minutes — a manually-added personal event can take up to 5 minutes to start blocking (busy times are cached briefly).
- Tokens stay fresh — access tokens auto-refresh every 50 minutes, so providers don’t need to reconnect.
- Break alerts — if a connection dies (revoked/expired), the site admin gets an email naming the provider with a link to reconnect.
Labels & translation
Every word on the booking page can be changed under Settings → Labels.
Override step names, field labels, buttons, messages and email row labels. A language preset (English, Dutch, French, German, Spanish) fills every label and sets the calendar language in one click — a great starting point you can then tweak.
Webhooks & integrations
Send every booking straight to Make, Zapier, n8n or your own CRM, the moment it happens.
The Connect module can post a booking to any address you give it. That turns a booking into anything you can automate — a row in a spreadsheet, a Slack message to your team, a deal in your CRM, an SMS to the client. No code required.
Enable Connect
Under WPStack → Modules, switch on Connect. A new App Connect item appears in the WPStack menu.
Create a webhook in your tool
In Make add a Custom webhook trigger; in Zapier use Webhooks by Zapier → Catch Hook. Each generates a URL for you.
Paste it into WPStack
Go to WPStack → App Connect → Integrations, paste the URL, tick which events it should receive, and save.
Press “Send test”
Your tool needs one sample delivery before it can map any fields. After that, real bookings flow automatically.
Events you can subscribe to
| Event | Sent when |
|---|---|
booking.created | A booking is made — from your website or the mobile app. |
booking.status_changed | You confirm, complete or cancel a booking. Carries the previous status too. |
booking.rescheduled | The date or time changes. Carries the old date and time as well as the new one. |
booking.deleted | A booking is removed. The full record is included, since it no longer exists afterwards. |
X-WPStack-Signature header your receiver can verify.For developers
Every event is also a standard WordPress action, so you can handle it in a plugin or your theme instead of sending it anywhere. They fire for bookings made on the website and in the mobile app.
| Hook | Type | Description |
|---|---|---|
| wpstack_booking_created | action | $booking_id — a booking was made. |
| wpstack_booking_status_changed | action | $booking_id, $new, $old — status moved between confirmed / completed / cancelled. |
| wpstack_booking_rescheduled | action | $booking_id, $date, $time, $old_date, $old_time |
| wpstack_booking_deleted | action | $booking_id, $booking — fires just before the row is removed, so $booking still holds the record. |
| wpstack_booking_archived | action | $booking_id, $is_archived — archived or restored. |
| wpstack_booking_payment_changed | action | $booking_id, $new, $old — payment status changed after creation. |
| wpstack_booking_updated | action | $booking_id, $changes, $before — catch-all; $changes is [ field => [ from, to ] ]. |
add_action( 'wpstack_booking_status_changed', function ( $booking_id, $new, $old ) {
if ( 'cancelled' !== $new ) {
return;
}
$booking = WPStack_Booking_DB::get( $booking_id );
// …free the slot elsewhere, notify a colleague, write to your own table…
}, 10, 3 );add_action() is how many arguments your callback receives. Leave it off and WordPress hands you only the first one — a classic source of silent bugs.Frequently asked questions
No. Booking runs entirely inside your WordPress site — there’s no external account and no embed. Your data stays on your site.
Yes, with Stripe. Set a service’s payment mode to online to charge the full price at booking, or leave it on_location to collect payment in person.
Yes — two-way with Google Calendar or Outlook, per provider. Their busy events block availability and new bookings appear on their calendar automatically.
You pick one active calendar per site in Settings → Calendar. Both sets of credentials can be saved, but only the selected provider is used, so there’s never a double-booking.
No. Google’s Calendar API and a Microsoft Entra app registration are both free for this use — no Azure subscription or credit card required.
Yes. Add providers under Bookings → Providers, assign them to slots, and each can connect their own calendar.
Yes. Settings → Labels lets you override every label, with one-click presets for English, Dutch, French, German and Spanish.
Troubleshooting
The most common issues and how to clear them.
| Symptom | Likely cause | Fix |
|---|---|---|
| No time slots appear | No slot covers that date, or min notice is too high | Add a slot for the service and lower the service’s min-notice. |
| Payment step is skipped | Service payment mode is on_location | Set it to online and connect Stripe under Settings → Payment. |
| Outlook connect link 404s | Site is on Plain permalinks | Use pretty permalinks, or re-save Settings → Permalinks once. |
| Calendar not syncing | Token expired or connection revoked | Regenerate the provider’s link and reconnect; use Test Connection to check. |
| A personal event isn’t blocking | Event marked “free”, or the ~5-min cache | Mark it busy and wait a few minutes. |