Skip to content

Your Contact Form 7 forms and Flamingo messages after moving to Laravel ​

A contact form looks like a small thing to move. On a real site it rarely is. There are several forms, each with its own fields, mail templates and messages, and a shortcode in every page that shows one. With Flamingo installed, there are also years of messages that people sent through them.

Here is where the two plugins keep it all:

  • A form is a wpcf7_contact_form post. Its template ([text* your-name] and the rest) is in the _form meta. The two mails are in _mail and _mail_2, the texts a visitor sees in _messages, the extra options in _additional_settings, and the hash a shortcode finds it by in _hash.
  • A page shows a form with [contact-form-7 id="1a2b3c4"] in its content.
  • A message Flamingo kept is a flamingo_inbound post, with a _field_<name> meta per field, plus _from, _subject and _meta (IP, browser, page, date). The form it came from is its flamingo_inbound_channel term.

A usual Laravel rebuild writes the forms again in code or in a form builder. Their mail templates and messages are typed in again by hand. The shortcodes in old pages show up as plain text, and the messages end up in a CSV export, or nowhere.

How kitloom reads it ​

kitloom runs on the WordPress database as it is. kitloom/forms reads forms where Contact Form 7 keeps them and messages where Flamingo keeps them, and needs no table of its own.

  • Shortcodes keep working. [contact-form-7 id="…"] finds the form by the start of its hash or by its post ID, and the older [contact-form id="12"] works too. The theme gets the form's template with each form-tag as a field to draw: text, email, URL, telephone, number, date, textarea, select, checkbox, radio, acceptance and submit.
  • The same submit address. The form posts to /wp-json/contact-form-7/v1/contact-forms/{id}/feedback, the plugin's own route, and gets the plugin's JSON answer: mail_sent, validation_failed, spam or mail_failed, with the invalid fields.
  • Validation checks each field against its tag (required, email, URL, ranges, length, the choices the form offers) and keeps only the form's own fields.
  • Messages are stored as Flamingo's, under the form they came from. Old messages are there as before.
  • Mail goes out through Laravel's mailer and queue, with the mail-tags filled in: [your-name], [_site_title], [_date], [_url] and the rest.
  • Additional settings that change behaviour are followed: skip_mail: on, do_not_store: true, demo_mode: on.

Spam protection is built in. A honeypot is on by default, Cloudflare Turnstile is on once its keys are set, and one address may send 10 submissions a minute by default. The same checks guard the site's comment form.

What the admin shows ​

Filament has a Contact section and Nova a Contact Forms section, each with All Forms, Add New Form, Messages and Settings. A form has Contact Form 7's tabs: Form (the template with its form-tags and the shortcode to copy), Mail and Mail (2), Messages (the texts a visitor sees) and Additional Settings. A new form starts from the plugin's default template and mail.

Messages lists what the forms received, newest first and without spam, with a filter by form. A message opens read-only, with its fields and where it was sent from. Deleting moves it to the trash. Settings holds the spam protection: the honeypot, the limit per minute and the Turnstile keys, with the secret stored encrypted.

Administrators and editors manage forms and read messages (manage_contact_forms, read_contact_messages). Only administrators open Settings.

A few modules plug in here when they are installed:

  • kitloom/languages: a form follows the page's language through its Translations tab.
  • kitloom/ai: an agent lists forms and messages, changes a form's template and marks a message as spam or not. It deletes nothing.
  • kitloom/privacy: WordPress's Export and Erase Personal Data screens include the messages a person sent.

What changes and what is not covered ​

  • The move is one way. Arrays are written as JSON and the serialized ones are read too. Contact Form 7 on WordPress would not read the JSON back.
  • Some form-tags stay as text. [file] and [quiz] are not drawn, so a form that takes file uploads needs another way to do it. The same goes for tags added by other plugins.
  • Spam protection is kitloom's own: the honeypot and Turnstile. Spam services set up for the plugin in WordPress are not read.
  • Flamingo's address book (its list of contacts) is not read. The messages are.
  • Mail needs Laravel's settings. Set MAIL_* in .env, and run a queue worker when the queue is not sync, or nothing is sent.
  • Plugin code does not run. Contact Form 7's own scripts and markup are not used. The theme draws the form from its data. Of the bundled themes, Journal, Bureau, Portfolio, Pantry and Blade draw it; Marketplace and Game Reviews do not.

The complete list of what is read is in the Forms guide.

Read and answer messages with an AI agent ​

Years of Flamingo messages are only useful if someone reads them. With kitloom/ai installed, an agent connected to the site lists the forms (forms_list, form_get), reads their messages (submissions_list), marks spam (submission_spam) and changes a form's template (form_update). You ask:

  • "Summarise this week's messages from the contact form and list the ones that ask for a quote."
  • "Mark the obvious spam from the last month as spam."
  • "Add a phone field to the quote form, optional, after the email."

The agent acts as the user whose key it holds, sees messages only if that user may, and deletes nothing. The mail settings that decide where messages go stay locked to people. How to connect one: Run your site from Claude or Cursor.

Check it on your own site ​

Create a MySQL user that can only read, point kitloom at the live database, and look at your contact pages. Then run compare-sites.php against both sites. Among its checks, it flags any [shortcode] that reached kitloom's page undrawn.

Sending a form writes to the database, so try it on a copy. Load the copy, run php artisan migrate, set the mail settings and send a test message from each form. It should show in Messages, under its form, next to the ones Flamingo kept. The steps are in Migrate from WordPress.

Try it ​

Open a sandbox in one click, with no sign-up: Filament or Nova. When it fits, see Pricing.

Forms are one plugin among several. The same approach covers WooCommerce, ACF fields and Rank Math. An overview is in your plugin data after moving to Laravel.

Last updated:

kitloom — modules and themes for Laravel.
Pricing · Services · License · Refunds · Privacy · Community · [email protected]