Build a WordPress Scheduling System Using Make and Airtable

Build a WordPress Scheduling System Using Make and Airtable

Why I Tried Automating Scheduling in WordPress

This whole thing started because I got sick of manually copying appointment requests from WordPress forms into a calendar. I had a client project where users would pick a time slot from a form and then I’d get an email… and then I’d cross-check that with some other Airtable or Google Sheet, and then manually reply to confirm. I probably missed around 20% of booking emails because I kept losing track 🤦. Definitely not scalable.

The client didn’t want to pay for Calendly or Acuity, and they were already using WordPress + Airtable for tracking clients. I figured: “Fine, I’ll wire it all up with Make (formerly Integromat) and just brute force it.” Turns out, building a scheduling system yourself is part therapy, part mystery horror game.

Setting Up the Frontend Form Correctly in WordPress

We started with a normal WordPress contact-like form. I used Fluent Forms because they already had the form set up and it works fine with webhook triggers. Gravity Forms can work too, but I’ve had issues with webhooks firing twice randomly from there (and not because of double submissions — one fired like 14 minutes later, completely unexplainable 🙃).

Anyway, in the form I added:
– A name field
– Email field
– Date-time picker (used the built-in one but you’ll want to lock it down in scripts later)
– Hidden field to capture the page URL (optional)

Once that was ready, I added the webhook to Make. You’ll find this in Make by creating a new scenario with a “Webhook” module at the top — no filters, no retries yet. Make gives you a unique webhook URL. You paste this into the Fluent Forms webhook option.

It helps to do at least one test submission while the Make scenario is listening, or it won’t register any fields and you’ll get super vague empty runs (just a 200 ping and nothing else). I once forgot this and wasted 40 minutes wondering why the Airtable record had blank info — it was just because the webhook payload hadn’t mapped yet 😛

Parsing Form Fields and Cleaning Dirty Inputs

Okay, so say the webhook is working. You get a bundle with name, email, and a date-time field. But the date-time is NOT usable yet.

Fluent Forms (and most WP form plugins) will send the raw input exactly as typed. Example — a value might come in as:

“July 3, 2024 at 3:30 PM”

Make is not happy with that. It can’t sort it or compare it properly. So in Make, right after the Webhook trigger, you want to add a **Tools > Text Parser** module (or use the built-in functions if you’re good with expressions). Your goal is to reformat everything into ISO format:

“2024-07-03T15:30:00”

I also added a little logic to block people from booking in the past or too soon (like same-day bookings). You can do this with a simple **Router > Condition**, checking if your parsed date-time is more than N hours from now. If it fails, you return a polite error or trigger an email saying “Please choose a time at least 24 hours ahead.”

Writing the Data Into Airtable Safely

Okay now here’s where it gets spicy. Airtable seemed like the easy part — just send the record in, done right? Nope.

First, Airtable time zones are weird. You HAVE to set the field to use the same timezone as your parsed input. Otherwise it’ll show like 7PM instead of 3PM, and your users will miss meetings and yell at you.

Second, Airtable won’t prevent record collisions on its own. So unless you create a key (like email + date) and check before inserting, you’ll end up double-booking. Here’s what I do:

1. Add an Airtable “Find Records” step filtering on the selected datetime.
2. If any records exist, divert the scenario with a router.
3. One route sends back a response like: “That time is taken. Please pick another.”
4. The other route proceeds to create the record normally.

Also worth mentioning — Airtable does that thing sometimes where it silently fails if the field name changes. Like, if you rename “booking_time” to “selected_time” in the UI, but forget to refresh the schema in Make, it’ll just skip the insert without any error.

Confirming Bookings by Email or Redirect

So you’ve got something that takes a WordPress form, parses it, checks Airtable, and inserts if available. What next?

For the user, there still needs to be a confirmation. I debated firing off an email confirmation or just redirecting to a thank-you page with their time. I tried both.

Option 1: Send Email
– Add a Gmail or SMTP Email module in Make
– Embed the date (cleaned version!) and their name into a short confirmation

Option 2: Redirect With Query Params
– On the final route path, have Make return a webhook response with a redirection header using a unique thank-you URL like:

“`
https://example.com/thanks?name=John&date=2024-07-03T15:30:00
“`
– Then the thank-you page can read those values and show a custom message.

I ended up doing both since some of our older clientele don’t trust it unless they get an actual email in their inbox.

Canceling or Rescheduling Using Airtable Status

This part was trickier than I expected. Users couldn’t cancel from the website directly because there was no login system. So we had to give them a special link in the email that was a one-time cancellation token.

How I did it:
– Generate a random string (Make’s GUID tool)
– Save it in Airtable under a field like “cancel_token”
– Add that as a URL param in the confirmation email like:

“`
https://example.com/cancel?token=d19a3183-…etc
“`

Then:
– On the cancel page, a separate webhook triggers when the token is submitted
– Make searches the Airtable base for that token
– If token matches, it changes status from “Confirmed” to “Cancelled”

Here’s where I ran into a stupid bug: if I manually cancel a booking in Airtable (for testing), then submit the same cancel token again, Make collapses the result into an empty result — because there is no route path explicitly handling zero matches.

So now I always have a fallback path that says “Sorry, this booking was already cancelled” instead of pretending it worked.

Specific Weird Things That Broke or Almost Broke

Let me just put these here because I wish *someone* had told me:

1. **Zapier won’t give you free path filters anymore** — Make’s routers with filters are way more useful for free users now.
2. **Fluent Forms doesn’t validate date-time entries on mobile** — People typed “tomorrow afternoon” and it somehow submitted.
3. **Make’s email module only supports plain links** — Don’t try to style the cancel link unless you use HTML email manually.
4. **Timezone math is a subtle villain** — My first 3 test bookings showed as next day events in Airtable due to UTC mismatch.
5. **Airtable silently trims long text fields, including cancel tokens** — If your field is set as “single line text,” it might remove the end of your token.
6. **Webhooks in WordPress fire before validation** — So I was logging stuff that never actually submitted.
7. **Make will skip modules silently if earlier bundles return zero** — Always include debug email or logging paths.
8. **You can’t use the same webhook for two scenarios** — You’ll think it works… then wonder why only one path is executing each time.
9. **Some emails treat Make-generated links as suspicious** — Especially Yahoo or Outlook inboxes. Had to adjust wording and from-address.

¯\_(ツ)_/¯ it’s always the small stuff.

The Forgotten Airtable Field That Fixed It All

This legit cost me a full afternoon: I kept wondering why two people were able to book the exact same time slot, even though the Airtable filter was working.

Answer? I was comparing against the formatted text of the datetime field — not the field itself. So two times that looked the same but had different seconds (or AM/PM formatting) slipped past.

Fix: Add a formula field in Airtable called `booking_key` that concatenates the date + hour only (like `DATETIME_FORMAT({Time}, ‘YYYY-MM-DD HH’)`) and compare against that instead.

Once I did that, Airtable showed duplicates and I could finally eliminate them via a proper uniqueness check. 🤷‍♂️