Make.com build, running on sample data

IntakeSync

Your intake form connected to your Airtable client database, built and running end to end on a synthetic intake. A WordPress JetFormBuilder submission comes in through a webhook, the automation checks whether that client is already in the base, and then either adds a new record or updates the existing one. No duplicates.

Built from the request you posted publicly on Make's Hire a Pro board. Rather than write to you about how I would do it, I built it and put it here so you can see it run. Everything below uses invented sample data. There are no live keys and nothing touches your account.

Why a working build instead of a message

You wanted this connected and tested right away, so the most useful thing I could send is the thing itself rather than a description of it. The part that matters in a client database is that the same person submitting twice does not become two records, so the whole flow is built around a check before write. The two places it earns its keep, the field mapping and the deduplication, are called out inline.

The sample scenario

A synthetic matchmaking intake form posts a submission to Make. The Clients table in Airtable holds one row per person, keyed by email. The automation has to keep it that way: a returning applicant updates their row, they do not spawn a second one.

Source
JetFormBuilder (WordPress)
Transport
Call Webhook to Make
Destination
Airtable, Clients table
Match key
Email (normalized)
On new
Create a record
On returning
Update, no duplicate
Trigger

A form submission arrives from JetFormBuilder

gateway:CustomWebHook · receives the intake POST

Field mapping In JetFormBuilder the form action is set to Call Webhook, pointed at this Make webhook. On the first real submission you run Determine Data Structure once, and Make maps every form field to a clean top level key by its field name. After that each field is addressable directly, so the rest of the scenario reads {{1.email}}, {{1.full_name}}, and so on. This is what keeps the mapping stable instead of guessing at field order.

The webhook receives one submission. Here is the sample intake bundle Make sees:

// intake submission, as Make receives it after Determine Data Structure { "full_name": "Jordan Ellis", "email": "jordan.ellis@example.com", "phone": "+1 415 555 0142", "age": "34", "city": "Denver", "seeking": "Long-term relationship", "age_range_preference": "32-42", "how_heard": "Instagram", "consent": "true", "submitted_at": "2026-07-05T09:14:22Z" }
1

Validate and normalize before anything is written

util:SetVariables · with a filter

A blank or malformed email would break the match and let a junk record through, so a filter here requires a well-formed email before the flow continues. The email is lowercased and trimmed into one value the search and the write both use, so casing or a stray space cannot cause a false new record.

// filter: only continue when the email is present and well formed { "a": "{{1.email}}", "o": "exist" } { "a": "{{trim(1.email)}}", "o": "text:pattern", "b": "a valid email" } // then set one normalized key for the rest of the scenario email_norm = "{{lower(trim(1.email))}}"
2

Look for this client before creating anything

airtable:Search Records · match on email

Deduplication Airtable does not enforce a unique field, so a plain Create a Record would add a duplicate every time someone resubmits. The scenario searches the Clients table for the normalized email first. The result count decides what happens next: {{2.__IMTLENGTH__}} is zero for a new person and one for a returning one. If the base already has duplicates the search returns the first, and you pick the tie break, for example update the oldest or flag it for review.
Search Records formula: AND({Email}!="", LOWER({Email})=LOWER("{{email_norm}}")) · max records 1

The same scenario handles both of the cases below. The only thing that differs is what the search returned.

3

Create if new, update if the client already exists

builtin:BasicRouter · to Create a Record or Update a Record

Case A · a brand new applicant
jordan.ellis@example.com
Search returned
0 records
no one in the base has this email
Route taken
CREATE A RECORD
filter: count equal 0
Result
New client row
Status New, Intake Count 1, First Seen stamped now
Result: one new record created (recJORDAN00000001). Nothing existed to collide with.
Case B · someone who applied before
Priya.Nair@example.com (note the different casing, the match still works)
Search returned
1 record
recPRIYA000000001, first seen 2026-05-20
Route taken
UPDATE A RECORD
filter: count greater than 0
Result
Same row refreshed
no second Priya created

The existing record is updated in place. Changed fields move, the identity and history stay:

FieldWasNow
CityPortlandSeattle
Preferred Age Range35-4536-46
Phone+1 206 555 0143+1 206 555 0197
Intake Count12
Last Updated2026-05-202026-07-05
First Seen kept2026-05-202026-05-20
Email keypriya.nair@example.compriya.nair@example.com
Result: the existing record is updated, First Seen and the email key are preserved, and no duplicate is created.
Why this order Search first, then a router with two filters that cannot both be true (count equal 0, count greater than 0). Airtable also has a single Upsert a Record module that merges on email, and for a plain one to one sync that is fine. The explicit search then branch is here because it gives you the decision to work with: you can log which happened, run different update logic than create logic, and handle the duplicate-already-in-the-base case deliberately. The runbook shows the one module upsert as an alternative if you would rather keep it compact.
4

Nothing gets silently lost

onerror handler on each write · builtin:Break

Airtable can rate limit or return a transient error under load. Each write has an error handler that retries a few times at an interval, and if it still fails, the run is stored as an incomplete execution you can resume rather than dropped. The scenario also carries an error tolerance so one bad submission does not stall the rest.

// on a Create or Update error retry 3 times, 5 minute interval // still failing -> store as an incomplete execution to resume, do not drop the intake

The runbook notes where to add a notification before the retry, or a small dead letter table that captures the raw payload, if you want a louder signal on repeated failures.

Take the build with you

The importable Make blueprint and a module by module runbook. The blueprint uses the native Airtable Search Records, Create a Record, and Update a Record modules, and the JetFormBuilder side is a standard custom webhook. Connect your Airtable and set the base and table, and it runs.