MevvForms documentation

Accessible forms, local entries and a reversible migration.

MevvForms owns the form schema, server-side validation, accessible rendering, local entries and a durable notification queue — and on top of that a conditional-logic engine that is re-run on the server, front-end views, retention and privacy tools, local AI form generation and importers for seven other form plugins. This guide documents what the plugin actually does today and says plainly where it has not been proven.

Overview and requirements

MevvForms Free is the local runtime. A published form is read from a versioned WordPress form record, rendered with real labels and error relationships, validated again on the server, stored locally and handed to a durable notification queue.

WordPress
6.6 or newer; tested through WordPress 7.1.
PHP
8.1 or newer; the release matrix covers PHP 8.1–8.5.
Data boundary
Form definitions, entries and queued jobs remain on the WordPress site by default.
Tables
Thirteen tables of its own: entries and their typed values, the job queue, files, part-finished submissions, the notification log, two analytics counters, content links, inventory, coupons, payments and payment events.
Scheduled work
Two hourly jobs. One applies retention, the other drains the single job queue that carries notifications, deferred feeds and exports — one queue rather than one cron per feature.
Translation files
Nineteen WordPress locales ship with the plugin, source catalogues included.

Free makes no licence, telemetry, AI or update request to an external service while a visitor renders or submits a form.

Installation

  1. Take a restorable database and wp-content backup.
  2. Upload and activate the MevvForms Free ZIP.
  3. Confirm that the MevvForms database tables were created and that an administrator can open the dashboard.
  4. Keep the source form plugin active until migration preview, import and health checks are complete.
  5. Install the matching Pro companion only when the saved form uses a released Pro module.

Do not remove the Free package while Pro is installed. The saved form runtime belongs to Free; Pro extends it.

The builder

Fields are dragged into place, and everything the mouse can do the keyboard can do as well. Adding, selecting and removing a field are ordinary buttons, so Enter and Space already work; moving a field has one shortcut of its own, Ctrl with the up or down arrow, which calls exactly the same move as a drag. After every change focus is put back on the card you were working with, and a live region announces what happened — “Moved Email from position 2 to position 5 of 9” — so the reordering is followed without sight.

Columns are a layout tool with a rule attached: the reading order must stay identical to the field order. This is checked on the server, not left to CSS. A layout that would place fields in the page in a different order from the schema is refused with an error rather than rendered, because a screen reader and a sighted visitor have to receive the same form.

Autosave
The draft is written to the form’s own draft record about two and a half seconds after you stop typing. It never touches the published form and never creates a WordPress revision, so autosaving cannot publish anything by accident.
Revisions
Saving uses WordPress’s own revision system rather than a private one, which means the revisions are visible to anything else that understands WordPress. The builder lists the most recent fifty and restores any of them.

There is no undo or redo in the builder. Restoring an earlier revision is the way back, and it restores the whole form rather than the last action. If you are about to make a large change, save first so there is a revision to return to.

Field types

Thirty-eight field types, in five groups. All of them are in the free package, including signature, repeater, matrix and quiz.

Basic
Single line text, paragraph text, email, email with confirmation, phone, website URL, number, password, hidden value.
Choice
Dropdown, dropdown with multiple selection, radio group, checkbox group, single checkbox, consent, rating, ranking, slider.
Advanced
Name, address, date, time, date and time, colour, file upload.
Payment
Calculation, order total, product, discount code.
Layout
Heading, section break, divider, content block, page break. These carry no input and produce no stored value.

A password field is rendered and validated but its value is never written to an entry. Neither is any field marked as not stored. The calculation and total fields do show a box on the screen, but their value does not come from the browser: the server re-runs the formula and overwrites whatever arrived.

Templates

Twenty-eight ready forms, meant as a starting point rather than a finished product: contact, quote request, job application, event registration, feedback survey, support request, appointment request, newsletter signup, product order, complaint, donation, table reservation, user registration, quiz, poll, file submission, testimonial, exit survey, maintenance request, meeting scheduler, course registration, parent consent, recommendation survey, accommodation booking, volunteer signup, bug report, supplier registration and call-back request.

A template is copied into a new form and then edited; it is not a live link, so changing a template later does not change forms already built from it.

Rendering and submitting a form

Embed a published form with [mevvforms id="123"]. The renderer prints stable field identifiers, real labels, descriptions, an error summary target and a signed session tied to the current form revision.

In the block editor the same thing is a block — MevvForms Form — and its preview is not an approximation: the editor asks the server to render the block, and the server renders it through exactly the code the front end uses. What you see in the editor is the page.

  • Required state and validation rules are taken from the server-owned schema.
  • Hidden or unknown client values cannot relax server rules.
  • A valid submission creates the entry before any notification side effect runs.
  • The response contains the configured message or safe redirect, never the stored field values.

If a form changed after the page was opened, refresh the page before submitting so the signed session matches the current revision.

Conditional logic

A field can be shown or hidden on the value of other fields, with AND and OR groups nested inside one another up to ten levels deep. Fourteen operators are available: equals, does not equal, contains, does not contain, starts with, ends with, is empty, is not empty, greater than, less than, greater than or equal, less than or equal, is one of, and is not one of.

The conditions are re-evaluated on the server on every submission. A field the browser hid can still be posted by hand, so hiding it in the browser is a convenience and never a rule. The same evaluation decides which fields exist for validation, for storage and for the notification body — which also means the form behaves correctly with JavaScript switched off, just without the live show and hide.

Multi-step forms and save-and-continue

A page break turns one form into several steps. It is an ordinary layout field, so a long form becomes a multi-step form by adding a field rather than by converting it into something else.

Save-and-continue keeps a part-finished submission and hands the visitor a link back to it. The link carries a signed token — the row identifier and an HMAC over it — and the signature is derived from the site’s own secret. Nothing in the database is enough to forge one on its own, the comparison is made in constant time, and the link expires after thirty days.

The token is the credential: no login is required and no cookie is set, so anyone holding the link can continue that submission. Treat a resume link the way you would treat a password reset link — send it to the person, not to a shared inbox.

Entries and privacy boundary

Entries and typed field projections are stored in dedicated local tables. Passwords, card data, CVV, WordPress nonces, session tokens and fields marked store=false are never written to entry values.

  • IP addresses are represented only by a site-specific HMAC where rate limiting needs it.
  • Text, numeric and date projections support later search without changing the original field identity.
  • A failed entry or outbox write rolls the complete submission transaction back.
  • Production evidence records only form, entry and job identifiers; it never records submitted values.

The entry list searches the stored values, filters by status, by read and starred state and by date range, and applies read, unread, star, unstar, spam, trash, restore and delete to a selection at once. Each of those is checked against your capabilities separately, so a role that may read entries but not delete them cannot delete them through a bulk action.

CSV that opens correctly
The file begins with a byte order mark, which is what makes Excel read it as UTF-8 — without it Turkish characters arrive broken and the usual reaction is to blame the export rather than the encoding.
CSV that cannot execute
A value beginning with =, +, -, @, a tab or a carriage return is prefixed with an apostrophe. Those characters make a spreadsheet treat a submitted value as a formula, and a form is exactly the place where a stranger chooses that value.

Notifications and confirmations

Notifications are durable jobs. A mail outage cannot erase an accepted entry: transient failures retry with bounded delays, while permanent configuration errors stop for administrator action.

A form can carry several notifications, each with its own recipients, subject, body and condition. Recipients can be fixed addresses, addresses taken from a field the visitor filled in, or routes chosen on a field value — and every matching route is used, not only the first one, because a form that reaches sales and support at once is the normal case rather than a mistake. An autoresponder is the same machinery pointed back at the person who filled the form.

Headers
Recipients and header merge tags are validated; CR/LF injection is stripped.
Body
HTML is escaped or filtered for its output context.
Confirmation
Message, same-site page and allowlisted redirect decisions are selected from the saved schema.
Idempotency
The same notification job key cannot create the same side effect twice.
Delivery log
One row per attempt: which form, entry, notification and job, whether it was sent or failed, which attempt it was, the recipients, the subject and the error code and message. A failed row can be sent again from the screen.

The log records what was attempted, not what was delivered. Mail is handed to WordPress and from there to your host; a row marked sent means it left the site, and only a bounce at the far end can tell you the rest.

Spam protection

Two defences are on from the moment you install: a honeypot field that a person never sees and a timing check that refuses a form submitted in under three seconds. Neither costs the visitor anything and neither breaks assistive technology, which is the reason they are the default rather than a challenge.

Beyond that, everything is optional and off until you turn it on: reCAPTCHA v2 and v3, hCaptcha, Cloudflare Turnstile and Akismet, plus keyword, address and country rules that run entirely on your own server.

A submission judged as spam is marked, not deleted. A honeypot hit, a failed or low-scoring CAPTCHA and an Akismet verdict all store the entry with a spam status, where you can read it and change your mind — because the cost of a wrongly discarded enquiry is far higher than the cost of a row you have to look at. The two exceptions are the timing check and rate limiting, which refuse the request before an entry exists at all; there is nothing to mark, and nothing was ever accepted and then thrown away.

Akismet is the one option that sends the submitted values, the visitor’s IP address, the browser user agent and the referring URL to a third party. That is a transfer of personal data: tell your visitors before you switch it on. The other providers receive only what their own script collects plus the challenge token, and the visitor’s IP address is not passed to them unless a filter on your site asks for it.

Access control

A form can open and close on a schedule, stop after a number of submissions, require a logged-in user or a particular role, or sit behind a password. All four are decided by one function, and that function is called from two places: once when the form is about to be rendered and once when a submission arrives.

Two call sites, one decision. If hiding the form and refusing a direct submission were written separately they would drift apart, and the closed form would still accept a POST from someone who had the address. Nothing here is enforced in the browser.

The submission limit is checked once more immediately after the row is written, with the count locked while it is read. Two visitors pressing submit in the same second would otherwise both pass a check made before either of them had been counted.

File uploads

Uploaded files are kept out of reach of the address bar. The directory name is unguessable and carries deny rules for Apache, IIS and a directory index, so a file is not served even if someone learns its path.

The vault sits inside your uploads directory unless you define MEVVFORMS_FILE_VAULT_DIR and point it somewhere outside the web root. Below the web root is stronger than deny rules, because it survives a web-server configuration that has been reset or is not read at all. If your host lets you, set it.

A file is judged by what is inside it, not by the name it arrived with. The first bytes are compared against a table of known signatures, executable magic is refused outright, and a file is scanned for an embedded script even when its signature looked innocent. An extension is a claim made by whoever uploaded the file.

Downloads go through a signed link rather than a path. The signature covers the file, the person and an expiry — fifteen minutes by default and never more than a day — and the download still re-checks that the person is allowed to have it, even while the link is inside its window. A link forwarded to someone else does not work for them.

Front-end views

Entries can be published back to the site as a view: a grid, a table, a calendar, a timeline or a map. Views are placed with [mevvforms_view id="12"], or with the MevvForms View block, and pinning a single record to a page is a matter of naming the entry.

The map contacts no outside service. There are no tiles to fetch, no key to obtain and no geocoding request: the points are drawn as an inline vector image on your own page, with the coordinates also written out as text underneath for anyone who cannot see the drawing. It looks plainer than a tiled map, and in exchange no visitor’s address is sent to a mapping company by a page they did not know had a map on it.

Privacy and retention

MevvForms is registered with WordPress’s own personal data export and erase tools, so a data request handled through WordPress finds entries, part-finished submissions and files without anybody remembering to check a second screen.

Retention is set per form as a number of days — zero means keep forever, and the ceiling is ten years. An hourly job applies it.

Before a retention change is saved, the screen tells you how many entries it would make eligible for permanent deletion. The count is worked out first and the deletion is a separate, separately confirmed step. Typing 30 into a box should never be the same gesture as destroying four thousand records.

Form analytics

Analytics answers one question — where do people give up on this form — and it is off until you switch it on and name the forms it may measure. While it is off nothing is written, no script is added to your pages and no public endpoint exists at all.

Switched on, it keeps two tables of daily counters: per form, the views, starts, submissions and abandonments; per field, the abandonments at that field, the times it was left empty, the validation errors, the total focus time and how many visitors focused it.

No visitor identifier is created and no cookie is set. The tables have no column for an IP address, a user, an email, a session, a fingerprint, a referrer or a submitted value — the shape of the schema is what makes a row untraceable, rather than a promise not to look. The browser signal goes to your own site and is authenticated with the form’s own short-lived ticket, which is identical for every visitor of that form. Because the rows are aggregates, a personal data export finds nothing to export, and an erase request is answered with a line saying so.

Generating a form with AI

You can describe a form in a sentence and have the fields laid out for you. Three connections are supported: Ollama and LM Studio, which run on your own machine or your own server, and an OpenAI-compatible endpoint for anyone who would rather use a hosted model with their own key.

  • There is no quota, no credit and no usage counter anywhere in the plugin — nothing to run out of, because the model is not ours.
  • With Ollama or LM Studio, the description of your form never leaves the machine the model runs on.
  • With no connection configured, the feature is not shown at all and no request is made. There is no hosted fallback waiting to be used by accident.

A key you paste is kept in a single WordPress option that is not loaded on every page, and the screen shows it masked afterwards — but it is stored as you typed it, not encrypted. Anything with database access can read it. Use a key scoped to what it needs, and rotate it if the site changes hands.

What comes back is a draft. It is a starting layout to correct, not a form to publish unread — and a generated field carries no idea of what your law requires you to ask or to leave out.

Importing from another form plugin

Forms can be imported from seven other plugins: Contact Form 7, WPForms, Gravity Forms, Fluent Forms, Formidable Forms, Ninja Forms and SureForms.

  • The source is only ever read. Nothing in the other plugin is changed, deactivated or deleted by the import, and its own data stays exactly where it was.
  • Whatever cannot be carried over is listed, with the reason. The import refuses to write until you have seen that list and accepted it — a silent partial import is how a missing notification is discovered three weeks later by a customer who never got an answer.
  • Old shortcodes keep working. The source plugin’s shortcode is answered by MevvForms once the migration is active, so pages that were never edited keep showing a working form. If something else has already claimed that shortcode, MevvForms leaves it alone.

Keep the source plugin installed until you have submitted the new form yourself and seen the entry and the notification. Rolling back is easy while the original is still there and awkward once it is gone.

Reversible WPForms migration

Migration starts read-only. Preview lists mapped fields, notifications, confirmations, embeds and unsupported settings. Apply creates or updates one staged MevvForms form and records the source hash. It does not delete WPForms data, revisions, tables or page content.

  1. Require an exact preview before applying.
  2. Import the form as staged and compare source hashes again.
  3. Run the cutover health gate: publish, render, signed test submission, local entry and queued notification.
  4. Only after those checks pass may the source plugin be switched off.
  5. If any check fails, rollback restores the former active-plugin list and returns the imported form to draft.

The measured mevvshop.com inventory is one source form with 4 fields, 1 notification, 1 confirmation and one live embed. Those counts are a release gate for that site, not a promise about every WPForms form.

Taking a payment

A form can carry a price. Product fields hold the items, calculation and total fields work out what is owed, and the order is built on the server from the schema on every submission.

  • The amount never comes from the browser. A total that arrives with the submission is used only for comparison, and a mismatch rejects the submission rather than quietly correcting it — a visitor must never be charged an amount other than the one they were shown.
  • Money is carried as whole numbers of the currency’s smallest unit from end to end. No monetary value passes through a floating-point number anywhere.
  • Nothing becomes paid without an answer from the provider. A browser returning from the payment page moves the order to “needs reconciling” at most; paid requires a signature-verified notification or a direct question put to the provider.
  • Card details never reach the site. There is no field for a card number, an expiry or a security code in the payment contract and no column for one in the database.
PayPal — a Pro gateway
Pro adds a PayPal gateway built on Orders v2. The order is opened on your server, the visitor approves it on PayPal’s own page, and the money is captured on the way back — or, if they close the tab first, when the signed notification arrives. Both routes end in the same place, so an approved order is not left uncaptured with the money uncollected. Double capture is guarded twice over: the capture call carries a fixed request id that PayPal will not replay, and an “already captured” answer is read as work already done rather than as a failure. Refunds, whole or partial, are issued from the entry.
PayPal is not available in Türkiye
PayPal does not operate in Türkiye and does not settle in Turkish lira, so this gateway is for selling abroad. Turkish payment providers stay where they were, on the MevvPos bridge, and nothing about that changes here.

No transaction fee, on any tier. Several form plugins take a percentage of what you collect on their free payment layer; a test asserts that the amount sent to the provider equals the order total exactly.

No payment has been run end to end, PayPal included. There is no live or sandbox merchant account behind any of this yet: every provider path is exercised against a stand-in, and the request and notification shapes were checked line by line against the providers’ published references rather than against a completed call. Treat the payment features as unproven until that changes, and do not put them in front of real customers on our word alone.

Zapier and Make

Pro can also publish entries to Zapier and Make as REST hooks. Zapier subscribes to one of your forms, MevvForms remembers the subscription, and every entry after that is queued and delivered to it. Unsubscribing removes it again, and a separate samples route hands Zapier a recent entry so its field-mapping screen has real field names to show instead of empty boxes.

  • Authentication is a site key you generate on the Zapier settings screen. It is the only credential, and it identifies the site rather than a person.
  • Deliveries go out through the signed webhook and job queue the free edition already uses. This is a new destination, not a second delivery system, so the delivery log and the retries work the same way.
  • Without a valid licence the module does not boot at all: no route is registered, no hook is added, and there is no code path that could reach a remote address.

Zapier and Make were already reachable without Pro, because the free edition can POST a signed webhook to any address. What Pro removes is the part in between — you no longer build the subscription, the field mapping and the retry yourself.

Salesforce

Pro can turn a submission into a Salesforce Lead, Contact or Case. You map form fields onto the object’s fields on the connector screen, and each entry is sent through the queue the other connectors use — so a Salesforce outage delays the record, it does not lose the entry.

  • Authentication is OAuth 2.0 with a refresh token. No Salesforce password is stored on your site.
  • Sandbox and production are a switch, not a second set of credentials to keep straight.
  • The entry itself stays on your own site either way. Sending a copy to Salesforce is not moving your data there.

Uploads on your own object storage

By default the file vault sits on your own disk, outside the web root. Pro can move it to any S3-compatible store instead — AWS S3, Cloudflare R2, MinIO, DigitalOcean Spaces, Backblaze B2 or Wasabi — signing each request itself, so no third-party SDK ever sees the entries.

What changes is where the bytes sit, not who may fetch them. Files are still handed out only through a time-limited link tied to one person, and the free plugin still decides who is allowed one. Moving the storage does not move the permission check.

Languages

Nineteen WordPress locales ship with the plugin: German (Germany, formal Germany and Switzerland), English, Spanish (Spain, Mexico, Argentina, Chile, Colombia), French, Italian, Japanese, Dutch (Netherlands and Belgium), Polish, Portuguese (Brazil and Portugal), Russian and Turkish. The editable source catalogues are included, so a translation can be corrected on your own site.

Turkish and English are the two that have been read through line by line. The others are complete but not all of them have had a human pass yet; if a string reads oddly in your language, that is what it is, and the catalogue is there to fix it.

Free and Pro boundary

Free owns the dependable runtime and almost everything on this page with it: the schema, all thirty-eight field types, the accessible renderer, server-side validation and conditional logic, multi-step forms with a review step and a conversational mode, save-and-continue, local entries with CSV export and an audit trail, admin notes and an approval workflow, the notification outbox and delivery log, outbound webhooks signed with HMAC, the full spam suite, access control, the file vault, front-end views, retention and privacy tools, analytics, AI generation, the importers for seven plugins, and one-time payments with no transaction fee.

Pro adds the named service connectors: Mailchimp, HubSpot, Brevo, ActiveCampaign, Airtable, Notion, Google Sheets, Discord, Telegram and Slack, each speaking that service's own shape, plus a PayPal gateway, a Zapier and Make connector built on REST hooks, recurring payments, discount codes and partial payments. Note what this still means: the free edition already POSTs a signed webhook anywhere, so Zapier, Make and anything you write yourself stay reachable without Pro — what Pro removes is the part in between, the subscription, the field mapping and the retry you would otherwise write yourself. The licence gate is the module's own boot check — without a valid licence no connector class is loaded, no job filter is registered and no remote call can happen.

A roadmap item is not advertised as a working capability. Check the installed version and release notes before designing a form around a Pro module.

Troubleshooting and rollback

The legacy shortcode is blank
Confirm that the source ID has an active migration mapping and that another plugin does not own the wpforms shortcode.
Submission reports an expired session
Reload the page and submit against the latest published revision.
A notification is waiting
Open the queue status, correct the permanent configuration error or allow the scheduled retry for a transient transport error.
Cutover did not deactivate WPForms
Read the health result. The safety gate kept or restored WPForms because render, submit, entry or job verification failed.
A field the visitor could not see arrived anyway
That is the point at which the server decides. Conditions are re-evaluated on submission, so a value posted for a hidden field is discarded there — check the condition itself rather than the browser.
Turkish characters are broken in the CSV
The file carries a byte order mark and is UTF-8. A spreadsheet that was told to import it as something else will still show it wrongly; open it directly rather than through an import wizard with an encoding already chosen.
A download link says it has expired
Links last fifteen minutes by default and are bound to the person who asked for them. Generate a new one from the entry; a link cannot be forwarded to a colleague.
The AI panel is not there
No connection is configured. The panel is hidden rather than shown broken, and nothing is sent anywhere while it is hidden.
A menu entry opens an empty screen
Some entries in the menu are placeholders for screens that are not built yet. An empty one is not a broken installation.

For support, share the plugin, WordPress and PHP versions plus the safe error code. Remove field values, customer data, session tokens, nonces and licence keys before sending logs.

Updates

Updates arrive through WordPress itself. The plugin asks our store whether a newer version exists and hands the answer to WordPress’s own update flow, so a new release turns up on the plugins screen with an ordinary Update button instead of waiting for someone to fetch a zip by hand. In the free edition that request carries only the package name and the installed version — no site address, no e-mail address, no licence key and no plugin inventory. Because nothing in it identifies you, trust rests on the signature: the reply is signed with our Ed25519 key, and one that is unsigned, wrongly signed, replayed from an old timestamp or that points the download at any host but ours is discarded without touching the site.

Limits

Stated plainly, so that nothing on this page has to be taken on trust.

  • The payment features have not been verified against a live or sandbox merchant account. They are built to the providers’ documentation and tested against a stand-in transport.
  • There is no undo or redo in the builder. Revisions are the way back.
  • PDF output depends on the site. If a PDF library is installed, MevvForms uses it; if not, it produces a printable document instead and leaves the printing to the browser. No PDF library is bundled and none is fetched from anywhere.
  • Every menu entry now opens a real screen. Reports, integrations, import and export, settings, roles and logs were placeholders in earlier releases; each is served by its own package as of 1.1.0.
  • The uploaded-file vault is inside the uploads directory by default and is protected by deny rules rather than by its location, unless you point it outside the web root yourself.
  • AI keys are stored as typed, not encrypted. They are masked on the screen and kept out of the always-loaded options, which is not the same as being unreadable.
  • The keyboard equivalent of the builder is complete but small. Buttons carry the ordinary keys and moving a field has one shortcut; there is no larger keymap to learn, and none to discover either.

Where this page says something has been measured, it was measured. Where it says something has not been proven, that is not modesty — it means the test does not exist yet, and you should treat the claim as unfinished.