Docs Product page Dashboard
Docs Marketing Booking

Booking

v1.4.17

Take 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.

Included in every plan Updated July 2026

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.

Bookings
Manage appointments across your services and providers.
23
Total bookings
5
Confirmed
18
Completed
0
Cancelled
ClientService & providerDate & timeStatusGcalPayment
Jordan Lee
Skin Procedure
Maya Cohen
04/06/2026
09:30 – 10:00
ConfirmedOn locationCompleteCancel
Sofia Martins
Hair
Maya Cohen
04/06/2026
13:00 – 13:30
ConfirmedOn locationCompleteCancel
Alex Kim
Spa
Maya Cohen
29/07/2026
08:00 – 08:30
ConfirmedOn locationCompleteCancel
Priya Shah
Spa
Maya Cohen
29/07/2026
09:00 – 09:30
ConfirmedOn locationCompleteCancel
Bookings — every appointment across your services and providers, with calendar sync, payment and one-click complete / cancel.

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
How the pieces fitA service is what a client books. Providers are the people who deliver it. Slots define when a service is available (and by whom). Each confirmed appointment becomes a booking. Set these four up once and your booking page runs itself.

Requirements & compatibility

Booking runs on any modern WordPress host. Payments and calendar sync use their own free accounts.

RequirementMinimumRecommended
WordPress6.06.5 or newer
PHP7.48.1 or newer
PermalinksPretty permalinksRequired for Outlook sync
HTTPSRequired for payments & calendar OAuthSite-wide

Optional integrations

IntegrationUsed forNeeded?
StripeOnline card paymentsOnly if you take payment
Google CalendarTwo-way calendar syncOptional
Outlook CalendarTwo-way calendar syncOptional
Calendar subscription (ICS)No-login feed to any calendar appOptional
Works with any themeThe booking page inherits your theme’s fonts and colors, and you can set accent colors under Settings → Style. No theme-specific setup is required.

Installation & activation

Booking ships inside WPStack — there’s nothing extra to download. Switch it on per site from the modules panel.

1

Open the WPStack modules panel

In your WordPress admin, go to WPStack → Modules and find Booking.

2

Activate Booking

Flip the Booking toggle to on. A new Bookings item appears in the WPStack menu.

3

Set your basics

Open Bookings → Settings → General and set your time zone, currency and date/time format.

4

Add a service, provider and slot

Create at least one service, one provider, and one slot that ties them to a time.

5

Publish your booking page

Add the [wpstack_booking] shortcode (or the Elementor widget) to any page, then publish.

Enable HTTPS firstIf you plan to take payments or connect a calendar, make sure your site is served over HTTPS. Stripe won’t process cards, and Google/Microsoft won’t complete sign-in, on an insecure connection.

The four building blocks

Booking is made of four connected pieces. Set them up in this order.

1

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

2 · Providers

The people who deliver the service (staff). Each provider can connect their own Google or Outlook calendar. Under Bookings → Providers.

3

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

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.

Services
The services clients can book, with their duration, price and notice.
Add new service
#NameDurationPriceMin noticeActions
4224Facials1 hr 30 min€199.993h
4303Hair30 min€18.001 day
4225Skin Procedure30 min€200.0012h
4223Spa30 min€99.981h
Services — each with its duration and price, or several duration/price options.
Multiple duration & price optionsOffer one service at several lengths — e.g. a massage at 60 / 90 / 120 minutes with different prices. Turn on Multiple options in the service’s Pricing & Duration card; the client picks one before choosing a time, and it’s recorded on the booking and shown in the confirmation email.
SettingTypeDefaultWhat it does
Name & descriptiontextShown on the booking page. An optional image can be added too.
Durationnumber (min)30How long one appointment takes. Drives how slots are split into times.
Gapnumber (min)0Buffer added after each appointment before the next start time.
Pricenumber0Shown to the client. A price of 0 displays as free.
Duration & price optionssingle / multipleSingleSwitch 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 modeselectOn locationon_location (pay in person) or online (pay the full amount now via Stripe).
Min noticenumber (hrs)0How far in advance a client must book — blocks last-minute times.
Max daysnumber (days)60How far into the future clients can book.
Custom fieldsbuildernoneExtra intake questions (text, number, select, checkbox…) captured at booking and shown on the booking + in the calendar event.
Payment gatewaysselectStripeWhich connected gateway online payments use.

Providers

Providers are your staff. Add them under Bookings → Providers, then assign them to slots.

Providers
The team members clients can book with, and their calendar connection.
Add new provider
#NameEmailPhoneCalendarActions
4252Maya Cohen[email protected]123 456 789Outlook
4305Liam Brooks[email protected]Not connected
4258Ava Reyes[email protected]Not connected
Providers — your team, each connecting their own Google or Outlook calendar.

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.

Each provider connects their own calendarCalendar sync is per provider. From a provider’s edit screen you generate a one-time authorization link and send it to them; they connect their own Google or Outlook account. See Google and Outlook below.
No login? Use a subscription linkIf per-provider OAuth is too much, switch on Calendar subscription — each provider just scans a QR to get bookings on their phone, with nothing to connect.

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
Subscription vs two-way syncSubscription is zero-config but read-only and not instant (the phone refreshes periodically). The Google / Outlook OAuth sync stays available for providers who need instant, two-way updates.

Availability (Slots)

Slots decide when each service is bookable, by which provider, and how many people can book at once.

Slots
Windows of availability per service and provider.
Add new slot
LabelServiceProviderTypeScheduleTime windowCap.Actions
HairHairMaya CohenRecurringTue, Wed, Thu, Fri, Sat, Sun09:30 – 18:301
Skin procedureSkin ProcedureMaya CohenRecurringMon, Tue, Wed, Thu09:00 – 15:001
SpaSpaMaya CohenRecurringWed08:00 – 17:001
Weekend MorningsFacialsMaya CohenRecurringSat08:00 – 16:001
Slots — recurring or one-off availability windows applied to one or more services and a provider.
One schedule, many servicesTick multiple services on a slot and that availability applies to all of them — no need to duplicate the same weekly hours per service.

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).
SettingTypeDefaultWhat it does
ServicescheckboxesOne or more services this availability window applies to — tick several to reuse the same schedule across services.
ProviderselectWho delivers it. Their connected calendar blocks conflicting times.
Typespecific / recurringspecificA single date, or a repeating weekly schedule.
Start / end timetimeThe daily window the service’s duration is split across into individual times.
Capacitynumber1How many bookings each time can take (e.g. a group class).
The service duration and gap split a slot’s window into individual bookable times. A 09:00–12:00 slot with a 30-min service and 0 gap produces 09:00, 09:30, 10:00 … automatically.

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.

SettingTypeDefaultWhat it does
GeneraltabTime zone, currency & symbol, and date/time format.
EmailtabConfirmation email (sender, subject, message) and provider notifications, with placeholders like {service} {provider} {date} {time} {duration} {name}.
CalendartabPick 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.
LabelstabOverride every front-end label; one-click language presets for EN / NL / FR / DE / ES.
StyletabService-grid columns and the step/button accent colors.
PaymenttabConnect and configure the Stripe gateway.
ShortcodestabThe booking shortcode and a quick setup checklist.

Embedding the booking page

Place the booking flow anywhere with a shortcode or the Elementor widget.

[wpstack_booking]

The full booking flow: service picker, date & time selection, details form, payment (if enabled) and confirmation.

serviceOptional. A service ID to skip the picker and book one service directly.
textpage content
[wpstack_booking]

[wpstack_booking service="12"]
Elementor widgetThe same flow is available as an Elementor widget (in the “WPStack Booking” category) — drag it in and pick a service right in the editor.

Payments (Stripe)

Collect payment at booking with Stripe, or take payment on location.

1

Connect Stripe

Under Settings → Payment, enter your Stripe keys.

2

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.

3

Test before going live

Use Stripe test keys to confirm the checkout, then switch to live keys.

Online services charge the full price at booking. The booking is only created once payment is verified, so paid times can’t be taken by an abandoned checkout.

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.

It’s freeA Google Cloud project and the Calendar API are free for this use. You enter your own credentials once; each provider then connects their own Google account.

Create the Google credentials

1

Create a Google Cloud project

At console.cloud.google.com, create (or pick) a project.

2

Enable the Calendar API

In APIs & Services → Library, enable Google Calendar API.

3

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).

4

Create an OAuth client

In Credentials → Create credentials → OAuth client ID, choose Web application.

5

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.

6

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

1

Generate a link

Open Bookings → Providers → (a provider) and click Generate Authorization Link (valid 24 hours).

2

Send it to the provider

They open it, click Connect with Google, and choose their Google account.

3

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.

Free — no billingRegistering the app is free and needs no Azure subscription or credit card. Use a Microsoft account that already has a directory (a work/school account), or create a free Entra tenant — skip the “sign up for Azure” prompt.

Register the app

1

New registration

At entra.microsoft.com → App registrations → New registration, give it a name.

2

Account types

Choose Any Entra ID Tenant + Personal Microsoft accounts so any provider’s calendar can connect.

3

Redirect URI

Platform Web, and paste the URI from Settings → Calendar → Outlookhttps://your-site/wpstack-outlook-callback. It has no query string (Microsoft rejects those) and needs pretty permalinks.

4

Client secret

In Certificates & secrets → New client secret, copy the secret Value (not the Secret ID) immediately — it’s masked after you leave.

5

Permission

In API permissions, add Microsoft Graph → Delegated → Calendars.ReadWrite.

6

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).

Callback 404?If the connect link returns “not found”, your site is on Plain permalinks. Switch to a pretty permalink structure, or open Settings → Permalinks and click Save once to flush the rules.

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.
Only the time-slot list is filteredPersonal busy events remove individual times from a day. The monthly date dots are based on your slots and existing bookings.

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.

1

Enable Connect

Under WPStack → Modules, switch on Connect. A new App Connect item appears in the WPStack menu.

2

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.

3

Paste it into WPStack

Go to WPStack → App Connect → Integrations, paste the URL, tick which events it should receive, and save.

4

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

EventSent when
booking.createdA booking is made — from your website or the mobile app.
booking.status_changedYou confirm, complete or cancel a booking. Carries the previous status too.
booking.rescheduledThe date or time changes. Carries the old date and time as well as the new one.
booking.deletedA booking is removed. The full record is included, since it no longer exists afterwards.
One-way by designData only ever leaves your site. These endpoints give no one a way to write back into WordPress, and there is no API key for an outsider to hold or lose. Optionally add a signing secret and each delivery carries an X-WPStack-Signature header your receiver can verify.
Every field is always presentMake and Zapier learn the field structure from your first test delivery. WPStack always sends the same keys — empty rather than missing — so a booking without a phone number, or on a different service, will never break a scenario you have already mapped.

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.

HookTypeDescription
wpstack_booking_createdaction$booking_id — a booking was made.
wpstack_booking_status_changedaction$booking_id, $new, $old — status moved between confirmed / completed / cancelled.
wpstack_booking_rescheduledaction$booking_id, $date, $time, $old_date, $old_time
wpstack_booking_deletedaction$booking_id, $booking — fires just before the row is removed, so $booking still holds the record.
wpstack_booking_archivedaction$booking_id, $is_archived — archived or restored.
wpstack_booking_payment_changedaction$booking_id, $new, $old — payment status changed after creation.
wpstack_booking_updatedaction$booking_id, $changes, $before — catch-all; $changes is [ field => [ from, to ] ].
php
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 );
Pass the argument countThe 4th parameter of 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.

SymptomLikely causeFix
No time slots appearNo slot covers that date, or min notice is too highAdd a slot for the service and lower the service’s min-notice.
Payment step is skippedService payment mode is on_locationSet it to online and connect Stripe under Settings → Payment.
Outlook connect link 404sSite is on Plain permalinksUse pretty permalinks, or re-save Settings → Permalinks once.
Calendar not syncingToken expired or connection revokedRegenerate the provider’s link and reconnect; use Test Connection to check.
A personal event isn’t blockingEvent marked “free”, or the ~5-min cacheMark it busy and wait a few minutes.

Changelog

2.5.0
July 2026
newTwo-way Outlook / Microsoft 365 calendar sync (per provider).
newSelf-hosted Google Calendar credentials — use your own OAuth client, no shared hub.
newPick your active calendar (Google or Outlook) in Settings → Calendar.
impBreak-alert email now names the specific provider and links to reconnect.
2.4.0
Feb 2026
newPer-provider Google Calendar connection via a one-time link.
newOnline payments with Stripe.
impCustom intake fields per service.
Was this page helpful?