Bharat AI Saathi
ServicesIndustriesSetupsHow we workGuidesFounderVPS HostingContactGlobal (USD)
WhatsApp +91 77352 68199
support@bharataisaathi.com
Mon–Sat 10:00–19:00 IST
Voice & Chat Agents · Global catalog

Contact Form 7 to Airtable: track property enquiries

Contact Form 7 to Airtable setup for property enquiries: log by listing and agent, and let a WhatsApp bot update status on the same row.

Voice & Chat Agents

To send Contact Form 7 enquiries to Airtable, add a small hook that posts each submission to the Airtable REST API, or route it through a webhook plugin and Make or Zapier. For a property agency, the useful part is the row design: one record per enquiry, tied to a listing and an agent, with a status field the WhatsApp bot can update.

Build your enquiry form free

Design the Airtable table first

Most broken setups start in the form and discover later that the table cannot answer "which listings get enquiries but no viewings?" Build the table first, then make the form fill it.

Create a base with two tables: Enquiries and Agents. Agents holds one row per agent (name, WhatsApp number, active or not). Enquiries holds one row per submission. This is the fieeld map we use as a starting point:

Field Airtable type Written by
Created Created time Airtable
Name Single line text Contact Form 7
Phone Single line text, stored as +971501234567 Contact Form 7
Email Email Contact Form 7
Listing ref Single line text (or linked to a Listings table) Hidden form field
Agent Linked record to Agents Hidden form field
Message Long text Contact Form 7
Source Single select: Website form, Portal, Ad Hook sets it; bot sets the others
Status Single select: New, Contacted, Qualified, Viewing booked, Handed off, Lost Hook sets New; bot and agents change it
Qualification Long text WhatsApp bot
Viewing time Date with time WhatsApp bot
Last status change Last modified time, watching Status only Airtable

Keep the rule simple: the website only ever createes rows with Status = New. It never edtis an existing row. Only the bot and your agents move a status forward, so a late form resubmission cannot reset a lead that is already at "Viewing booked".

Set up the Contact Form 7 form

On each listing page, the form needs to know which listing and which agent it belongs to, and the buyer should not have to type either. Contact Form 7 handles this with hidden fields that read from the URL:

[text* your-name]
[tel* your-phone]
[email your-email]
[textarea your-message]
[hidden listing-ref default:get]
[hidden agent-code default:get]
[submit "Send enquiry"]

Your listing template then links to the form page with ?listing-ref=DB-1042&agent-code=Layla%20Haddad, or you embed the form on the listing page and set the query string through your theme. The default:get option fills each hidden field from the matching query parameter.

Ask for the phone number as a required field and tell people it is their WhatsApp number. That number is your matching key later, so a missing or malformed one costs you the status updates.

Post each submission to Airtable

You need a personal access token from Airtable with data.records:write on this one base (add data.records:read if the same token will be used for lookups). Then:

  1. In Airtable, copy the base ID (starts with app) and the table name from the API docs for your base.
  2. Put the token in wp-config.php as a constant, AIRTABLE_TOKEN, so it never sits in a theme file or a database option.
  3. Add the hook below to a small custom plugin or your child theme's functions.php, and replace the form ID.
  4. Submit a test enquiry and check that one row appears with Status = New and the Agent linked.
add_action('wpcf7_before_send_mail', function ($form) {
    if ((int) $form->id() !== 123) return;
    $sub = WPCF7_Submission::get_instance();
    if (!$sub) return;
    $d = $sub->get_posted_data();

    $body = [
        'typecast' => true,
        'records'  => [[ 'fields' => [
            'Name'        => $d['your-name'] ?? '',
            'Phone'       => preg_replace('/[^\d+]/', '', $d['your-phone'] ?? ''),
            'Email'       => $d['your-email'] ?? '',
            'Listing ref' => $d['listing-ref'] ?? '',
            'Agent'       => [ $d['agent-code'] ?? '' ],
            'Message'     => $d['your-message'] ?? '',
            'Source'      => 'Website form',
            'Status'      => 'New',
        ]]],
    ];

    $res = wp_remote_post('https://api.airtable.com/v0/appXXXXXXXXXXXXXX/Enquiries', [
        'timeout' => 8,
        'headers' => [
            'Authorization' => 'Bearer ' . AIRTABLE_TOKEN,
            'Content-Type'  => 'application/json',
        ],
        'body'    => wp_json_encode($body),
    ]);

    if (is_wp_error($res) || wp_remote_retrieve_response_code($res) >= 300) {
        error_log('Airtable push failed: ' . print_r($res, true));
    }
});

I used wpcf7_before_send_mail rather than wpcf7_mail_sent so the row is written even if the notification email fails on a flaky host. The phone line strips spaces, brackets and dashes so every number lands in the same shape.

If you would rather not touch PHP, a webhook add-on for Contact Form 7 or an automation tool with a WordPress trigger can do the same job. You will map the same fields in Make or Zapier, and you take on one more moving part.

Where the WhatsApp bot updates status

The form is only one of the doors into the table. Portal leads and ad clicks arrive in WhatsApp directly, and the bot should write them into the same Enquiries table with a different Source, so your agents see one pipeline instesd of three.

In our Dubai real estate WhatsApp bot, the form submission is the trigger for the first outbound message. A new row with Status = New starts the conversation, and from there the bot writes back to that row:

  • Contacted when the first WhatsApp message goes out.
  • Qualified once the buyer has answered the four qualifying questions; the answers go into the Qualification field.
  • Viewing booked when a slot is confirmed, with the time in Viewing time.
  • Handed off when an agent takes over the chat, including afteer a voice note has been transcribed and passed along.

The bot finds the row by phone number, since a form submission has no WhatsApp conversation ID yet. The lookup is a filter on Phone, sorted by Created descending with one record returned, so a buyer who enquired on three listings updates the newest row. If you want the earlier ones closed, that is a rule you decide, and it is better to decide it before launch.

When a different form builder makes sense

Contact Form 7 is a fine choice if your site is already on WordPress and one form is all you need. The cost is that every integration is code or a plugin you maintain, and there is no submission table beyond what you build yourself.

If you are rebuilding the site or adding forms across several landing pages, Qwenvo is worth a look. Our team builds it, and it is completely free. Webhooks to any URL, a REST API, partial submissions, a custom domain, badge removal, teammates and custom CSS are all included. Tally puts partial submissions, custom domains and branding removal on its paid Pro plan, and Fillout puts custom domains and partial submissions on Business. Partial submissions matter for enquiries: someone who typed a phone number and left is still a lead you can call.

Two honest caveats. Qwenvo has no one-click Airtable connection yet (it is being rolled out), so today you send its webhook to Make, Zapier or n8n and write the row from there. And it is hosted in the United States, which may matter if your clients have data residency questions. Tally is hosted in Europe. The details of the payload are in the form webhooks guide, and you can embed a Qwenvo form in WordPress with a custom HTML boock.

See the free webhook guide

Failure cases to test before launch

  • Misspelled agent name. With typecast on, Airtable matches linked records by the Agents primary field and creates a new agent row if nothing matches. Use short agent codes in the hidden field, and check for stray rows in Agents each week.
  • New select options. The same setting will create a new Status or Source option if the text differs by one character. Keep the strings in one place in your code.
  • Slow Airtable response. The hook runs inside the form submission, so the buyer waits. The 8 second timeout caps the damage, but if you see timeouts, move the call to a queue.
  • Spam. Every junk submission becomes a row and, with the bot attached, a WhatsApp message. Turn on Contact Form 7's reCAPTCHA integration or Akismet before you connect the bot.
  • Wrong number format. A buyer who types a local number without the country code will not match the bot's lookup. Validate the field or add a country prefix in the hook.
  • Token scope. If rows stop appearing after a rotation, check the token still has write access to this base.

Start with the free contact form

Questions teams ask

Do I need a plugin to connect Contact Form 7 to Airtable?

No. The hook above is the whole integration. A plugin or an automation tool saves you writing PHP but adds something to keep updated and, with some toosl, a per-task cost.

Should Agent be a linked record or plain text?

Linked. It lets you roll enquiries up per agent and filter views by agent without a formula. The price is the typo risk described above, which short codes in the hidden field solve.

How do I stop the same buyer creating duplicates?

Allow them. A buyer asking about two listings is two enquiries, and your listing report needs both. If you do want one row per person per listing, Airtable's upsert option on update calls can merge on fields like Phone and Listing ref.

Next step

Create the Enquiries and Agents tables with the field map above, add the three hidden fields to one listing page form, and send a single test enquiry. Once that row looks right in Airtable, copy the setup to the rest of your listing pages.

This system

Dubai Real Estate WhatsApp Bot

$1,500 setup
+ $299/month care plan

Third-party platform and model usage billed to you directly. No lock-in. Live in 10 days.

More on Dubai Real Estate WhatsApp Bot