Flinkform is a free contact form builder for the WordPress Block Editor. You build contact forms, quote requests and multi-step forms right where you edit your pages: every field is a native block, and the form takes its colours, fonts and spacing from your theme.
Multi-step forms, conditional logic, a submissions dashboard and spam protection without CAPTCHA are all included in the free plugin. There is no reCAPTCHA and no other third-party service, so no visitor data leaves your server. That makes a GDPR-compliant contact form a lot easier to run.
Try it before you install it: live demo forms, including a multi-step form and conditional logic, at
https://demo.flinkform.de/
Contact form in two minutes
Insert the Form block, pick one of five templates (contact, callback, three-step project inquiry, appointment, newsletter, each with a GDPR consent field) and publish. Name, email and message are there in a few clicks, and the form looks like part of your site from the start, without extra CSS.
- 14 field types, including email, phone, date, dropdown, address and a dedicated consent checkbox
- Email notification to you, plus an optional confirmation email to the visitor
- Submissions are stored in WordPress, with search, filters, read state, an unread count in the menu and a trash
- Every submission shows whether its notification email went out, and Site Health warns when notifications fail
- Success message or redirect to your own thank-you page
Multi-step forms and conditional logic, free
Split a long form into steps with the Page Break block. Visitors see a progress bar and every step is validated before they move on.
Conditional logic shows or hides fields, skips whole steps and can hold back the submit button until the right answers are given. Rules can be grouped, so "(A or B) and C" is possible.
Spam protection without CAPTCHA
No puzzle, no image grid, no checkbox to tick. Flinkform stops spam bots with a hidden honeypot field, a signed timing check and a small proof-of-work task that the browser solves in the background. Visitors without JavaScript get a simple maths question instead. It works out of the box, needs no API key and contacts no outside service.
GDPR-friendly by design
No IP logging, no user-agent logging, no tracking cookies and no external services in the free plugin. It includes a consent field with a link to your privacy policy, retention periods with automatic deletion, and support for the WordPress tools to export and erase personal data.
Accessible
Real labels, grouped choices, errors that screen readers announce and focus that moves to the first problem. The form works without JavaScript, and its markup passes axe-core checks against WCAG 2.1 A/AA with zero violations, including the error state.
Flinkform Pro
The optional Pro add-on adds Stripe payments (card, SEPA direct debit, Apple Pay, Google Pay, whichever methods you enable in Stripe), calculation fields, multi-file upload, SMTP delivery, webhooks, newsletter integrations, CSV export and custom CSS. Details and pricing:
https://flinkform.de/pro
Features (free plugin)
Form building
- 14 field types: Text, Email, Textarea, Number, Date, URL, Phone, Select, Radio, Checkbox, Toggle, Hidden, Consent, Address
- Address field with street, postal code and city in a compact grid, with optional address line 2 and country
- Consent field for the privacy policy agreement
- Notice block for highlighted notes between fields (info, success, warning, important), which can appear only when a condition applies
- Section Heading and Page Break blocks for structuring longer forms
- Multi-step forms with per-step validation and a progress indicator (bar, dots or numbers)
- Conditional logic: show or hide fields, skip steps, gate the submit button, with nestable rule groups
- Two-column layout with a full-width option per field
- Radio, checkbox group and dropdown can be switched into each other without losing options or rules
Styling
- Colours, typography, spacing and border radius come from your theme's theme.json
- Style panel: primary colour, field style (bordered, soft, underline, minimal), label position (above, beside, floating, placeholder), submit button style (fill, outline, ghost) and colours for labels and help texts
Notifications
- Notification email on every submission, with configurable recipient and merge tags
- Optional confirmation email to the visitor
- Sender name and address per form, and a Reply-To for each email, without an SMTP plugin
- Sent through your site's standard WordPress mail (wp_mail)
Spam protection
- Honeypot and signed time check, always on, no configuration
- Proof-of-work challenge with an accessible maths fallback for visitors without JavaScript
- No CAPTCHA, no external service, no API key, no tracking cookies
After submission
- Success message or redirect to a thank-you page on your site (protected against open redirects)
- Optional submission ID and form ID as URL parameters for conversion tracking (GA4, Meta Pixel, Plausible and others)
Admin
- Submissions list with search, filter by form, sorting and bulk actions
- Detail view with all field labels and values
- Mark as read or unread
- Retention period per form with automatic daily deletion
Under the hood
Forms are made of native blocks (
block.json v3) and run on the WordPress Interactivity API. No separate form builder screen, no shortcodes, no jQuery, and under 15 KB of frontend JavaScript (gzipped). Requires WordPress 6.5 or newer and PHP 8.1 or newer.
1.15.0
- New: Contact Form 7 importer. Flinkform > Import from CF7 turns each CF7 form into a Flinkform form (fields, labels, notification and confirmation mail, success message), stores it as a synced pattern and switches every page that used it. Preview with a traffic light first, undo per form, CF7 itself is never changed.
- New: five starter templates when you insert a form: contact, callback request, three-step project inquiry, appointment request and newsletter sign-up, each with a consent field.
- New: submissions trash with restore (emptied after 30 days), an unread count in the admin menu, and a mail status per submission. A Site Health check warns when notification emails fail.
- New: "Mark optional fields" adds "(optional)" to every field that is not required.
- New: autofill setting for text fields (name, company, address parts …).
- New: in conditions, choice fields offer their values in a dropdown, and fields with an active condition carry a "Conditional" badge in the editor.
- New: multi-step forms keep what the visitor typed when the page is reloaded (stored in the browser tab only, never the consent box).
- Improvement: emails and the submissions screen show the option label a visitor chose instead of its internal value. {field:name} inserts the label, {field:name:value} the stored value.
- Improvement: error messages under fields are in the site's language instead of the browser's, and fields are checked when the visitor leaves them.
- Improvement: multi-step forms no longer jump while the page loads.
- Improvement: error red is the CSS variable --flinkform-color-error and turns lighter on dark backgrounds; the consent text scales with the theme.
- Improvement: a second quick click on the "please send again" page is held until the form may be sent, instead of asking again.
- Flinkform Pro features appear, marked as Pro, where they would be used. Nothing is shown once Pro is active, and add_filter( 'flinkform_show_pro_upsell', '__return_false' ) hides all of it.
1.14.4
- Improvement: the block names in the inserter are translated now. On German sites every Flinkform block showed its English name ("Text Field" instead of "Textfeld").
- Improvement: German now ships in both forms of address. Sites set to "Deutsch" get the informal "du", which matches the language pack WordPress.org will deliver, and sites set to "Deutsch (Sie)" get the formal "Sie" instead of falling back to English.
- Readme: clearer description, FAQ and screenshot captions, and a Live Preview in the plugin directory.
1.14.3
- Fix (important): a submission sent very quickly after the first click into the form was dropped silently and the visitor landed on the homepage. Since 1.14.0 the anti-bot timer starts at the first contact with the form, so clicking into a field, picking an autofill entry and pressing Send within two seconds looked like a bot. The browser now waits out the remaining moment before sending, and should a submission still arrive too early, the visitor gets their filled-in form back with a request to send again.
- Fix (important): after a successful submission, going back, changing the message and sending again showed the success message without storing the second message. A resend with different content is now always treated as a new submission.
- Fix: logged-in visitors who kept a form open for more than about 20 minutes could get a "security check failed" page on submit. The automatic token renewal now runs as the logged-in user.
- Fix: forms on drafts, private pages and old revisions no longer accept submissions from visitors who cannot see those pages. Previewing a draft as its author still works.
- Fix: moving a form to a different page or into a template part could leave submissions pointing at the old place for a few minutes. The form index now notices removals and rebuilds itself once when a form cannot be found.
- Fix: the personal-data exporter and eraser (Tools → Export/Erase Personal Data) could stop early and miss submissions of a person who had sent more than 50.
- Fix: conditional rules now compare text the same way in the browser and on the server, including umlauts and trailing spaces from autofill.
- Fix: the notification email replies to the visitor's email address by default, also for forms that were never opened in the editor.
- Fix: German translation of the reply hint in the notification email no longer assumes the sender is a woman.
- Improvement: a field's error message disappears as soon as the field is corrected, the browser's duplicate error tooltip is gone, and error messages of two forms on the same page no longer get mixed up for screen readers.
- Improvement: on phones, form fields use at least 16px text, so iOS no longer zooms into the page when a field is tapped.
- Developer: new filter
flinkform_values_before_visibility for values the server derives before conditional logic runs (used by Flinkform Pro's calculation field).
1.14.2
- Fix (important): a submission could still be lost in one specific case introduced by 1.14.0. Leave a filled-in form in a background tab for twenty minutes and come back: the automatic token renewal also renewed the signed timestamp, and a submit within the next two seconds — exactly what returning to a finished form looks like — was treated as a bot and dropped silently. The timestamp is now written once, when the visitor reaches the form, and never moved again. The token keeps renewing as before.
- Fix: the German translation now covers the messages added in 1.14.0. On German sites, the "please send again" message and the no-JavaScript route showed English text. The new Site Health check is translated too.
1.14.1
- Fix: restores the plugin name, author and description in the plugin header. 1.14.0 shipped with a shortened name and a changed author by mistake, which is what your Plugins screen showed. No functional change.
1.14.0
- Performance: pages with a form can be cached again. Until now every page holding a Flinkform form told caching plugins not to cache it, because the form carried a spam token, a security nonce and a signed render time that are only valid for one request. On a site measured for this release that cost about 0.7 seconds of extra server time on every view of a form page - and those are usually the pages that matter most. Flinkform now loads those values in the background the moment a visitor first touches the form, so the page itself is plain, cacheable HTML.
- Spam protection is unchanged in strength. The same proof-of-work, the same signed single-use token, the same honeypot. The minimum-fill-time check actually gets more accurate: it now starts counting when the visitor reaches the form instead of when the page was rendered.
- Without JavaScript the form still works. Those visitors are offered a one-click link to an uncached version of the same page, which behaves exactly as before with the arithmetic question.
- Submissions that arrive before the background load finished are no longer lost. Everything typed is kept and the form comes back asking to send it again, instead of the request being dropped.
- New: Tools > Site Health reports whether your form pages are actually being cached, so this cannot quietly break again.
- Forms with a payment field (Pro) keep the previous behaviour and stay uncached, because the payment field brings request-specific data of its own.
- For developers: the old behaviour is one filter away -
add_filter( 'flinkform_render_challenge_inline', '__return_true' );.
1.13.3
- Fix: with the "Floating" label position, the resting label sat at the bottom edge of the field or slipped below it instead of sitting in the middle. It showed up wherever a field wrapper was taller than the input itself - a field with help text underneath, or a two-column row stretched to match a taller neighbour - because the label was centred on the whole field, not on the input. It is now anchored to the input, whatever else the field carries. The lifted state, the notch on the border, textareas, selects and date fields are unchanged.
1.13.2
- Fix: the Style panel cut its own option labels short. "Bordered / Soft / Underline / Minimal" and "Above / Beside / Floating / Hidden" were squeezed into a ~250px sidebar as segmented buttons and came out as "Borde… / Unde… / Minim…", so the setting could only be guessed at. Every setting with more than a couple of options is a dropdown now and reads in full, in every language. Nothing changes on the front end: the same values, the same defaults, existing forms render exactly as before.
- Reported by Eric Saner — thank you!
1.13.1
- Fix: closes a tiny timing gap in the 1.13.0 token refresh. For a fraction of a second right after the token renewed itself, the form briefly held a fresh token with no solution yet, and a submit landing in that window could still be dropped. The refresh now solves the new challenge before swapping it in, so the token and its solution are always written together and that window no longer exists.
1.13.0
- Fix (important): a submission could be lost without a trace. The anti-spam token is valid for 30 minutes; if a form sat open longer than that (a long multi-step form, a tab left open, an HTML cache serving an older page), submitting sent the visitor silently to the home page with no message and no email, and their entries were gone. A form that came from our own server is never a bot, so an expired or already-used token no longer drops the submission: the form re-renders with the entries kept and a clear "your session has expired, please send again" message, and the second attempt goes through. The no-JavaScript path is covered too.
- New: the token now refreshes itself in the browser before it can expire, so the situation above rarely arises in the first place. A small, cache-safe endpoint mints a fresh challenge; the form renews roughly ten minutes before expiry, when a tab regains focus, and when restored from the back/forward cache. Forms in a popup repair an expired token automatically and resend once, without the visitor retyping anything. The page itself may now be cached without breaking submissions.
- Fix: a double-click or a back-button resend no longer lands on the home page. The first submission is saved once, and a repeat shows the success page instead of being rejected.
Earlier versions
The complete release history is in
changelog.txt, shipped with the plugin and available at
https://github.com/dennisbuchwald/Flinkform/blob/main/changelog.txt