Blog Publishing Workflow with Make and Airtable Automation

Blog Publishing Workflow with Make and Airtable Automation

Setting up the triggers without overthinking

If you’ve stared at a blank Make scenario trying to decide between a webhook trigger vs. a manual Airtable poll, yeah — same. The paralysis is real. But when all you want is a clean blog publishing flow where someone fills out a row in Airtable and it automatically gets pushed to a CMS (in my case, WordPress via REST API), obsessing over perfect structure just slows you down.

Here’s what I did:

1. Set up a basic Airtable base. Each row = one blog post draft. I had fields like Title, Slug, Author, Status (a single select with options like “Draft,” “Ready to Publish,” “Published”), and a Rich Text field for the body.

2. Started with a Make scenario using the Airtable “Watch Records” module. Set it to poll only the “Ready to Publish” status. Poll every 15 minutes. Real-time triggers are great in theory, but Airtable’s webhook setup requires custom scripting and breaks randomly, so I bailed ¯\_(ツ)_/¯.

3. Connected HTTP module directly after it. Yep, raw HTTP, not the fancy WordPress module. Why? That WordPress module kept timing out or erroring when trying to upload longer posts — no real feedback. HTTP module gave me more control.

4. Added a Filter module between Airtable and HTTP to double-check that the post wasn’t already marked as “Published.” This is because Make sometimes re-triggers if the record is edited slightly later — learned this the hard way when a single post got duplicated on the blog three times 😅.

Final top-to-bottom order in Make looked like:
– Airtable: Watch Records
– Filter: “Status is Ready to Publish AND post not previously published”
– HTTP Request: WordPress API
– Airtable: Update Record: change status to “Published”

This barebones setup took maybe 20 minutes. Don’t get fancy too fast.

WordPress authentication pitfalls hurt my soul

So. WordPress REST API needs authentication. Logging in with a token should be easy, right? It was not. And it wasn’t Make’s fault this time.

When you try to connect Make to WordPress using an Application Password (which you generate in your user profile), it looks promising — you use your username + app password and set HTTP Basic Auth. But here’s the kicker: if you’re using a security plugin like Wordfence, or host on something like WP Engine, that API call might silently fail. No errors in Make, just… nothing happens.

Took me a day to troubleshoot this. Eventually I used Postman to do a test POST directly to my site with the same auth method. Yep — 403 Forbidden. Turns out my host blocks non-browser user agents unless they come from specific IPs. Whaaat.

Here’s how I got around it:

– Used a Bearer Token instead. Installed the JWT Authentication for WP-API plugin
– Added this line to wp-config.php:

“`php
define(‘JWT_AUTH_SECRET_KEY’, ‘your-super-secret-key-goes-here’);
“`

– Then, made a Make module to first hit the token endpoint and retrieve the JWT token (using username and password in the body).
– Once JWT was fetched, passed it as a Bearer token on subsequent POSTs.

Works like a charm. And I learned way more about WordPress API limits than I ever wanted to 😵.

Cleaning up long Airtable text for API calls

Okay, this part was mildly infuriating. Airtable’s Rich Text field looks great when editing — bolds, bullet points, inline code — but when your Make scenario pulls that into an API call, it comes out as Markdown.

You’d expect WordPress REST API to understand Markdown. NOPE. It publishes everything as-is, so all those asterisks and angle brackets show up literally in your final blog post. Funny for a minute. Then horrifying.

My workaround:

– Added a Markdown-to-HTML conversion step in Make using a Code module (JavaScript).
– The Code module input field was just:

“`js
const showdown = require(‘showdown’);
const converter = new showdown.Converter();
return { html: converter.makeHtml(input.markdown) };
“`

– Passed the `markdown` from Airtable Rich Text into it, and got back real HTML.
– Then used the result as the content value in the WordPress API call.

Now it publishes like a normal person wrote the content. Clean tags. Working links. No stray underscores lol.

Bonus: I later realized Airtable formula fields can do some basic cleanup too — like removing double line breaks or weird tags. But I prefer letting the Code module do the heavy lifting.

Tracking post status and failures without adding UI

Let’s be real: opening Airtable, drilling into the Automations or Make logs every hour is just not happening. So I wanted a way to eyeball post status fast without installing anything or opening extra tabs.

I added two helper fields:

– `Published At`: A formula that shows TODAY() if the Status = Published. Made it easier in filtered views.
– `Sync Log`: A long text field I update from Make when there’s a problem. I set Make to write something like: “Failed to publish: 403 – Forbidden” or “Published successfully at 4 PM”

Here’s where stuff got messy: Make’s Update Record module doesn’t append — it REPLACES whatever’s already in the Airtable field. So if I pushed success logs multiple times, I’d lose earlier notes.

Found a hacky way around it:
– Added another Airtable module **before** the Update step, just to pull the existing contents of the field.
– Then inside the Update module, used a formula to merge new message + old message.
– End result was a running log like:

“`
Published successfully at 4 PM
Failed to publish: 403 – Forbidden
“`

It’s not pretty, but it gives me the info I need at a glance.

Slug problems that ruined everything

LOL this took me four hours. So: WordPress uses the `slug` field when creating posts — that’s the URL part like “my-first-post.” Easy. Except… I didn’t add slug validation in Airtable.

And one record had a title like “My First Blog Post!” but the slug field was empty.

When Make tried to POST this to WordPress, it returned a vague 400 error. No detailed message. Nothing helpful. I thought it was the auth again. Spent two hours chasing ghosts.

Eventually, I realized: no slug = API freaks out.

To fix:

– Added a formula in Airtable to auto-generate a slug from Title:

“`airtable
LOWER(SUBSTITUTE(Title, ” “, “-“))
“`

– Added a validation step in Make with a Filter: if `slug` is blank or longer than 100 characters, skip.

Later I got fancier and made the Airtable formula remove punctuation too — because “Why doesn’t this slug work?” was not a question I wanted to ask again.

Final awkward table of what broke and when

Here’s a quick snapshot of where things went wrong (and also right):

| Step | What I Thought Would Happen | What Actually Happened | Fix I Did |
|————————–|—————————————|———————————————-|——————————-|
| Airtable Trigger | Watch updated rows only | Re-fired on minor edits | Added Filter for final status |
| WordPress Auth | App password works | Auth blocked by hosting/security plugin | Switched to JWT token |
| Rich Text Conversion | Would look fine in WP | Shows raw Markdown | JS Code module with showdown |
| Slugs | Always manually filled | Sometimes blank → 400 Error | Auto-generate with formulas |
| Publish Logs | Update field adds new info | Overwrites old info | Pulled old value, merged text |

This is the kind of stuff you don’t find in the docs. You find it at 1 AM when nothing works and you’re yelling at your keyboard 😛