Skip to content
Gaurav TiwariChangelog

Plugin changelog

Core Forms

Build forms, collect submissions, and connect the actions your site needs.

Latest
4.12.1
Releases
88
Updated
October 15, 2026
  1. Stable

    4.12.1

    Fixed: With Core Support active, the Support request template keeps its confirmation email. Core Support emails customers only when an agent replies.

    Read full notes 3 changes
    • Fixed With Core Support active, the Support request template keeps its confirmation email. Core Support emails customers only when an agent replies.
    • Fixed With Core Support active, industry intake templates send their confirmation again instead of writing it into a ticket action.
    • Improved Support and intake templates send plain, readable HTML email.
  2. Stable

    4.12.0

    Added: Core Support integration. "Create Core Support ticket" appears under Support & Tickets in a form's Actions tab, and shows what to install when Core Support is not active.

    Read full notes 4 changes
    • Added Core Support integration. "Create Core Support ticket" appears under Support & Tickets in a form's Actions tab, and shows what to install when Core Support is not active.
    • Added Core Support tickets can run in the background with retries, like the other ticket actions.
    • Added The Support request template opens a Core Support ticket instead of sending its own confirmation email when Core Support is active.
    • Added The cf_queueable_action_types filter lets companion plugins run their actions from the background queue.
  3. Stable

    4.11.3

    Fixed: The form preview uses your Form Theme Customizer styling and shows a styled Rehearsal panel; fields after a grid keep their spacing.

    Read full notes 5 changes
    • Fixed The form preview uses your Form Theme Customizer styling and shows a styled Rehearsal panel; fields after a grid keep their spacing.
    • Fixed Duplicated forms render their own markup and shortcode, keep backslashes in patterns, and no longer inherit unread badges.
    • Fixed The forms list "Delete Permanently" bulk action, which only trashed forms, is now "Move to Trash"; restored forms keep their published status.
    • Fixed Row and bulk actions redirect with a confirmation and no longer repeat on refresh; entry counts exclude spam.
    • Improved A cleaner, aligned forms list with unread chips, a Last entry column, Trash row actions, and fewer row links.
  4. Stable

    4.11.2

    Fixed: Form Theme Customizer colors now apply to forms whose block turns the theme on while the form or global setting has it off.

    Read full notes 5 changes
    • Fixed Form Theme Customizer colors now apply to forms whose block turns the theme on while the form or global setting has it off.
    • Fixed The submit button hover shadow follows your button color instead of staying blue.
    • Fixed Skip-to-submit links for long forms, the empty message gap above themed forms, and notice spacing in the customizer preview.
    • Improved Front-end scripts load deferred, and the generated theme stylesheet is minified.
    • Added CFDS, GTDS, Tabler and WordPress presets, plus 13 new design options covering field background, buttons, type, width and depth.
  5. Stable

    4.11.1

    Core Forms 4.11.1 restores the complete All Submissions screen for users without saved views and improves the admin workflow introduced in 4.11.0.

    Read full notes 4 changes

    Update from 4.11.0 to resolve the submissions-screen error. Existing form and submission records are preserved.

    • Empty, malformed, and numeric saved-view keys are handled safely.
    • Spam stays in the submissions tabs; old bookmarks redirect correctly.
    • Delivery recovery has a clear empty state, contextual task cards, guided outcome confirmation, and guarded retries.
    • Form Theme Customizer adds wrapper padding, defaulting to 10px. Zero and CSS spacing values work consistently in the customizer, form preview, and frontend.
  6. Stable

    4.11.0

    Core Forms 4.11.0 adds reusable field groups in a searchable popup, team inbox assignments and private notes, workflow rehearsal, draft publishing, protected uploads and optional retention, and signed webhooks.

    Read full notes

    It also strengthens calculated prices, login and capacity checks, draft recovery, payment confirmation, fulfillment and refund recovery, attachment ownership, and concurrent editing.

    Existing-form authoring API mutations now require the current fingerprint. Historical renewal refunds with missing entitlement terms require administrator reconciliation. Retention remains off by default.

    Validated with 619 PHP tests, 75 JavaScript tests, WordPress/database checks, browser authoring, multipart downloads, and lifecycle cleanup checks.

  7. Stable

    4.10.2

    Core Forms 4.10.2 makes submissions easier to scan, actions easier to reuse, and Telegram easier to configure.

    Read full notes 10 changes

    Validation: 561 PHP tests, 61 JavaScript tests, PHPStan and browser checks on desktop and mobile.

    Re-released 4.10.2 with every form-table editor shortcut restored, including Actions, Analytics and Revisions.

    • Scan submissions with sender details, answer previews, local dates and a responsive inbox. Filter by status, form and date, or switch a form to All fields.
    • Import selected actions from another form through a searchable popover beside Active Actions. Review field warnings and save to keep the copies.
    • Set up Telegram with bot verification, chat and topic discovery, masked tokens, plain-text messages and sample-message testing. Group migrations recover automatically after a successful send.
    • New submissions no longer appear hours old on non-UTC sites. Date filters follow the site timezone, and submit buttons no longer appear as answer columns.
    • License & Updates shows the actual last successful release check, offers a direct upgrade when available, and includes changelog and support cards.
    • Action inputs use consistent sizing, removal controls are red buttons, and navigation and active editor tabs have clearer styling.
    • Job application upload help follows the current limit, donation pledges use honest button labels, required markers are not doubled, and saved unconfigured payment gateways remain selected.
    • Analytics uses consistent cards, distinct metric colors and proportional field-interaction bars. Single-day charts show visible points.
    • Separate Mailchimp API action with double opt-in, audience mapping and optional merge fields; the MC4WP-based action remains intact.
    • Native Forms overview with submission/accessibility sorting and 50-row pagination. Plugin-dependent actions remain visible with dependency tooltips.
  8. Stable

    4.10.1

    Core Forms 4.10.1 adds Intelligent Inserter and improves the action editor.

    Read full notes 6 changes

    Existing fields and submission keys are preserved. Typed unavailable integrations retain their settings.

    Update through WordPress with an active Core Forms license.

    Release details · Changelog

    • Search field presets with words such as website, mobile and surname. Contact fields arrive with meaningful names and browser autofill.
    • Use the same keyboard-accessible inserter at form level and inside containers.
    • Save actions repeatedly without accumulating blank or unknown cards.
    • Select action fields through compact searchable choosers, with cursor insertion, JSON-aware tokens and multi-field selection.
    • Copy exact hook and field values. FlowMattic hooks update with the selected scope; test samples use actual form fields and display the selected payload.
    • Edit recipient routes in a compact responsive table. Empty placeholder rows do not accumulate and variable chips are consistent.
  9. Stable

    4.10.0

    Core Forms 4.10 adds Service and Event products to Core Commerce, a fuller customer account, and fixes for survey submissions, fullscreen forms and poll results.

    Read full notes 14 changes

    Service scheduling and event attendance use the links you provide. A yearly license term does not create automatic recurring charges; the payment provider owns recurring collection.

    Read the release post · Full changelog

    • Core Commerce
    • Sell services and events with the right delivery fields and one-time plans, without issuing software license keys.
    • Give customers purchase history, order details, printable receipts, licenses, downloads, subscription terms and profile settings.
    • Build product galleries with the Product Gallery block or shortcode. Use virtual product URLs or connect your own content pages.
    • Configure new license key style, length, prefix and grouping while preserving existing keys.
    • Keep checkout pages separate from other installed stores, with compatibility checks and a repair action.
    • Forms and polls
    • Fixed submission details crashing when checkbox answers are arrays and the optional email is empty.
    • Restored field headings in per-form submission tables.
    • Fixed tall-form view tracking and clearly labeled capped historical start rates.
    • Fixed fullscreen navigation icons, dark choice contrast and scrolling for long steps.
    • Included Other write-in votes in admin, frontend and REST poll results.
    • Corrected the conditional-logic guide to match the current and older editors.
    • Updating: Update through WordPress with an active Core Forms license. Existing forms and license keys are preserved. Core Commerce activation is separate from the plugin update.
  10. Stable

    4.9.6

    Added

    Read full notes 11 changes
    • Added
    • Drag fields and containers onto step tabs to move them between steps without losing other fields.
    • Industry-focused multi-step templates with relevant form fields, local email actions, acknowledgement messages, and submission settings.
    • Guided variants of longer starter forms, with multi-step badges, layout filters, and interactive sample previews.
    • Improved
    • Poll creation uses a single-column editor with instant tabs that retain unsaved changes and keyboard shortcuts for adding answers.
    • Template category filters span the gallery width and wrap without clipping.
    • Core Forms and Core Polls appear when searching for cf in the WordPress block inserter.
    • Blank-template buttons retain readable hover and keyboard-focus colors.
    • Sample success messages distinguish requests and pledges from completed subscriptions, payments or bookings.
    • Sample forms retain their schema, settings, actions, and messages when created or applied in the builder.
  11. Stable

    4.9.5

    Added

    Read full notes 15 changes
    • Added
    • Unlocked Multi-Step Forms in the UI
    • Visual multi-step form editing with named steps, step ordering, a canvas for each step, and field movement between steps. Removing a step preserves its fields, and both save controls retain the layout through Visual/Code changes.
    • Fluent Support customer and ticket creation with inbox/product mapping, priority conversion, category context, and links between tickets and saved submissions.
    • Authenticated n8n webhooks with typed JSON mappings, explicit field selection, test/production URL checks, and an importable intake workflow.
    • Pipedrive person/organization matching, lead or deal creation, custom fields, pipeline/stage checks, and optional follow-up activities.
    • Zendesk tickets with requester mapping, tags, custom fields, and validated uploads belonging to the saved submission.
    • Resend transactional email with stable idempotency keys and signed, correlated delivery/bounce events.
    • FlowMattic Plugin Actions bridge with per-form/shared hooks and named field payloads.
    • Administrator-only action testing with editable sample data and inline results.
    • Fixed
    • Form previews load the complete form runtime and their own styles. Save & preview opens the latest edits with desktop/mobile widths; URL prefill no longer overwrites submission tokens.
    • Multi-step forms supply a final Submit button when none is defined, keep nested container groups out of the step list, and support keyboard step navigation with labeled progress.
    • Empty or unsigned Resend webhook requests return an authorization error even when WordPress supplies null headers or body.
    • Newly added action cards receive unique persistent identities and control IDs, including after another card is removed.
  12. Stable

    4.9.4

    Core Forms 4.9.4 fixes integration delivery, retries, field mapping, and provider compatibility.

    Read full notes 9 changes
    • Fixed
    • Unify action outcomes across submissions, paid fulfillment, testing, replay, and queued work; report transport/provider failures and missing handlers accurately.
    • Connect background delivery and transient retries to eligible actions, with saved-submission requirements, execution leases, and ActiveCampaign/Kit checkpoints.
    • Preserve unavailable integrations and validate field mappings; retain explicit unchecked settings.
    • Correct Notion title/property mapping, Airtable value types and metadata, FluentCommunity membership APIs, and raw WhatsApp webhook responses.
    • Replace the broken Sheets setup link with a maintained authenticated receiver and align integration descriptions with the implemented capabilities.
    • Integration setup
    • Airtable tokens require schema.bases:read and data.records:write for the selected base. Notion connections require read and insert access to the shared database or data source. These permissions let Core Forms match the destination schema and send correctly typed values.
    • Google Sheets has a maintained receiver with a shared-secret setting. Existing plain OK receivers remain supported; the new receiver must use the same secret as the form action.
  13. Stable

    4.9.3

    Core Forms 4.9.3 fixes wrapper-class data loss and redundant ARIA requirements, and improves the Support Request template with preconfigured email actions.

    Read full notes 8 changes
    • Improved
    • The Support Request template now includes an optional Site URL, category, priority, subject, and a six-row issue description, with an admin notification and submitter auto-responder configured using the site's email address.
    • Applying a template inside the visual builder now saves its action and message presets through both Save fields and Save Form.
    • Fixed
    • Classes and supported attributes on individual p/div/span field wrappers survive Code/Visual conversions without turning the wrapper into a container or hiding its input. Wrapper attributes remain separate from input attributes.
    • Recover the specific saved wrapper/container name collision produced by 4.9.2 when the original input is still present in the schema.
    • Native required fields no longer trigger a missing aria-required warning. Frontend enhancement, accessibility autofix, templates, and the legacy field generator no longer add redundant aria-required attributes alongside required.
    • Cached accessibility reports discard the retired warning while retaining other findings. Native required validation and explicitly authored ARIA remain intact.
  14. Stable

    4.9.2

    Core Forms 4.9.2 fixes field editing, rendering, and validation across the builder and front end.

    Read full notes 8 changes

    Validated with 385 PHP tests, 14 JavaScript regression tests, static analysis, and live audit forms on gauravtiwari.org.

    • Code and Visual mode preserve radio and checkbox groups, selected values, empty placeholders, option groups, nested layouts, helper HTML, descriptions, and custom attributes through repeated edits and saves.
    • Saving immediately after editing HTML keeps the latest fields. Duplicating or renaming nested fields updates their internal references and avoids duplicate choice values.
    • Name, Address, Rating, submit, and reset fields render usable controls. Named submit buttons retain their values in AJAX submissions.
    • Conditional fields support both colon and equals rules, checkbox dependencies, multiple conditions, and hidden required controls.
    • Required checkbox groups validate correctly when advancing multi-step forms. Inline validation preserves help text and recognizes selected radio groups.
    • Server validation checks field types, allowed choices, numeric and date limits, step values, and multiple email addresses while accepting zero as a valid value.
    • Calculated fields recognize both supported calculation attributes, and character counters load when their attribute is present.
    • Field and option settings have associated labels and retain explicit checked and selected defaults.
  15. Stable

    4.9.1

    Core Forms 4.9.1 fixes three form-builder issues:

    Read full notes 3 changes

    The stray settings badge has been removed from License & Updates.

    Quoted attribute values are escaped correctly in generated markup.

    Requires WordPress 6.4 or later and PHP 8.1 or later.

    • The p/div/span wrapper setting now applies to schema-backed forms and generated HTML.
    • Consent fields render as working checkboxes and keep their type when switching editor modes.
    • HTML imports retain autocomplete, inputmode, ARIA, data attributes, and other supported control attributes through saving and rendering.
  16. Stable

    4.9.0

    Core Forms 4.9.0 improves submission reliability, spam protection, payment validation, and the WordPress admin experience.

    Read full notes 7 changes

    Requires WordPress 6.4+ and PHP 8.1+. Tested with WordPress 7.1.

    Validation: 336 unit tests, PHPStan, JavaScript lint, generated-asset checks, package integrity and PHP syntax checks, plus local browser verification.

    Read the Core Forms 4.9 release post.

    • Fixes reCAPTCHA and math-captcha validation, draft-save protections, and sensitive template-field access.
    • Preserves form HTML when saving from other tabs and prevents submission deletion from touching unrelated post metadata.
    • Recomputes calculated payment amounts on the server, reports failed submission writes, and preserves uploads without JavaScript.
    • Makes activation safer, improves duplicate prevention and GDPR erasure, and adds submission indexes and diagnostic tools.
    • Adds searchable settings sections, accurate unsaved-change indicators, consistent borders and colors, and accessible copy controls.
    • Improves Commerce navigation and activity, form-builder toolbar states, and submissions filtering.
    • Repairs standalone URL-base changes and shows URL controls only when fullscreen mode and standalone publishing are enabled.
  17. Stable

    4.8.0

    Core Forms now ships minified CSS and JavaScript, and only loads them where a form actually renders.

    Read full notes 10 changes
    • Changed
    • All first-party stylesheets and scripts are served minified on the front end and in the admin. Across the library that is 716 KB of CSS/JS down to 553 KB. forms.css drops 48%, forms.js 48%, smart-forms.js 52%.
    • Readable sources still ship alongside the minified files. Define SCRIPT_DEBUG or use the new cf_use_minified_assets filter to serve them instead.
    • Assets that arrive already minified (the webpack admin bundle, vendored Prism) are served as-is rather than duplicated in the package.
    • Added
    • Core_Forms\Assets resolves an asset path to the file that should be served, with cf_use_minified_assets as the escape hatch.
    • npm run build:assets regenerates the minified files; build.sh fails the build when they are stale.
    • Fixed
    • Page-level form detection now also inspects reusable blocks, widget areas, and block-theme template parts, so a form placed outside post content gets its stylesheets in <head> instead of after first paint. The template-part scan is cached and flushed on part save, delete, or theme switch.
    • Full changelog:
  18. Stable

    4.7.5

    Core Forms 4.7.5 fixes duplicate field IDs and reworks MailerPress consent handling.

    Read full notes 3 changes
    • Schema-rendered field IDs are now unique per form instance, so labels and descriptions stay correctly associated when multiple forms appear on one page.
    • The MailerPress action defaults to double opt-in, preserves existing subscribers and suppressed contacts, and records form-level consent metadata. Confirmation is resent only when a pending or previously unsubscribed contact submits again.
    • The legacy FluentCart-to-MailerPress bridge no longer creates subscribed contacts when its settings are empty.
  19. Stable

    4.7.4

    Core Forms 4.7.4 fixes native FluentCRM double opt-in.

    Read full notes 2 changes
    • Contacts added as Pending now receive the configured confirmation email after list and tag assignment.
    • Existing subscribed or suppressed contacts are not force-resubscribed.
  20. Stable

    4.7.3

    Licensing and automatic updates now run through gauravtiwari.org, the home for every Core Forms license.

    Read full notes 3 changes

    Full changelog: https://core-forms.com/changelog/

    • Your existing license key keeps working. Sites re-register themselves on the first admin page load after updating, so there is nothing to re-enter.
    • If that automatic step cannot reach the server, the key is left untouched and a notice asks you to reactivate, rather than the license being cleared.
    • License checks now retry once on a timeout or server error, so a brief network problem no longer marks an active license invalid.
  21. Stable

    4.7.2

    Core Forms 4.7.2 adds per-form Skeleton CSS control without forcing a visual theme.

    Read full notes 3 changes
    • Choose the global default, always load forms.css, or always skip it for each form.
    • Keep the form-editor preview aligned with the frontend’s resolved Skeleton CSS and form-theme settings.
    • Preserve existing form behavior until a per-form override is selected.
  22. Stable

    4.7.1

    Fixed

    Read full notes 6 changes
    • Fixed
    • Standalone and fullscreen form pages no longer fall back to browser-default controls when the global or per-form built-in theme is disabled.
    • Standalone routes now always load the complete Core Forms design baseline and generated theme-token overrides because these pages do not render the active WordPress theme.
    • Changed
    • The default form theme now depends on the core form stylesheet so its layout primitives are always present.
    • Added regression coverage for standalone asset loading.
  23. Stable

    4.7.0

    Core Forms 4.7.0 is the admin, design, migration, and Core Commerce release.

    Read full notes 16 changes

    Full public changelog: https://core-forms.com/changelog/

    • Highlights
    • Unified Core Forms, Submissions, Core Commerce, and Settings under one compact, responsive navigation.
    • Added a dedicated Form Theme Customizer with presets, live desktop/mobile preview, accessibility checks, and generated cache-versioned CSS.
    • Added selective portable JSON backup and restore for forms, submissions, polls, settings, analytics, and complete Core Commerce data.
    • Rebuilt Core Commerce around next actions, product readiness, customers, licenses, orders, and storefront publishing.
    • Added case-insensitive customer records with order, license, activation, and site metadata.
    • Added copy-ready product blocks and shortcodes plus single-product-page publishing guidance.
    • Replaced the all-submissions card grid with a searchable sortable table and improved responsive controls throughout the plugin.
    • Fixed starter-template previews, preview/frontend theme drift, Warm preset styling, LTR select arrows, checkbox alignment, and help text sizing.
    • Compatibility
    • WordPress 6.4 or newer
    • Tested through WordPress 6.8
    • PHP 8.1 or newer
    • Integrity
    • SHA-256: 9c4974ebe162f16790e7fc7c8927458473ca894b7abc2a57b20f13b9be537c4b
    • ZIP size: 1,097,202 bytes
  24. Stable

    4.6.3

    Core Forms 4.6.3 improves validation, licensing reliability, headless submissions, and the Core Forms admin experience.

    Read full notes 6 changes
    • Renames the Forms dashboard to Core Forms, adds the installed version badge, and renames Products & Licensing to Core Commerce.
    • Fixes schema and legacy-form validation, same-name choice groups, empty select placeholders, and invalid-submission rate-limit accounting.
    • Fixes headless REST error statuses, nonce-enforced submissions, array-field normalization, and canonical field descriptions.
    • Fixes Emailit v2 sends and contact subscriptions being marked failed after a valid HTTP 200 response.
    • Makes activation records self-healing, retries transient license requests, and preserves the local key when remote deactivation fails.
    • Removes the redundant one-page Core Commerce footer and misplaced card treatment.
  25. Stable

    4.6.2

    A public Storefront API for headless storefronts, plus a block editor and builder preview that finally look like the real form.

    Read full notes 12 changes

    Note: 4.6.1 was prepared but never published, so its changes are folded into this release and no v4.6.1 tag exists.

    Requires: WordPress 6.4+ · PHP 8.1+ · Tested up to WordPress 6.8

    • Added
    • Added a public, read-only Storefront REST API for static sites and external product embeds, exposing active-only product and plan data with resolved icons, hosted checkout URLs, filters, pagination, CORS, caching, and ETags.
    • The form skeleton (forms.css) and default theme (form-theme.css) now load inside the Block Editor canvas, so the Core Form block preview matches the published page instead of rendering unstyled.
    • Changed
    • The License Issuing Server no longer takes over an existing /checkout/ page it does not own. When that slug is already taken it provisions /core-checkout/ instead, leaving WooCommerce and hand-built checkout pages untouched.
    • Replaced every DOING_AJAX constant check with wp_doing_ajax(), which is filterable and the supported API.
    • Removed the orphaned AllSubmissionsTable::forms_dropdown() and ::date_filters() methods.
    • Fixed
    • Fixed the form builder preview pane painting unstyled before restyling itself. Its stylesheets were enqueued from a wp_head callback at priority 10, after core prints styles at priority 8, so they only ever reached the footer's late-style pass.
    • Fixed the form builder preview request not being recognised as containing a form, which let the unused-asset cleanup dequeue the preview's own stylesheets.
    • Corrected several inaccurate PHPDoc return types reported to callers and tooling, and declared Form::$id as the read-only alias __get() already served.
    • The licensing maintenance cron callback no longer returns its summary array to do_action().
  26. Stable

    4.6.0

    Core Forms 4.6.0 connects forms, payments, digital products, and software licensing in one native WordPress workflow.

    Read full notes 8 changes

    Requires WordPress 6.4+ and PHP 8.1+.

    • Rebuilt Products & Licensing around searchable product, license, and order tables, product workspaces, setup checks, operational alerts, activity timelines, and validated plugin or theme release ZIPs.
    • Added product icons, sample-product generation, and optional purchase and renewal form generation for every active plan.
    • Added currency-to-gateway routing with multiple compatible gateways and a preferred gateway for each currency, plus native product checkout without a stored Core Form.
    • Expanded purchase templates for Stripe, PayPal, Razorpay, and Polar with optional business, tax, billing, phone, website, and order-note fields.
    • Added permissioned commerce REST endpoints and WordPress 6.9+ MCP-discoverable abilities for products, plans, releases, orders, licenses, subscriptions, downloads, gateways, and sample data.
    • Added blocks and shortcodes for product catalogs, product lists, single products, prices, buy buttons, checkout, and the customer dashboard, grouped in the Core Forms block category.
    • Removed customer emails and full license keys from newly generated renewal and package URLs, added enumeration-safe dashboard access requests, and recorded non-secret commerce activity events.
    • Corrected the plugin and installation-documentation product URL to core-forms.com.
  27. Stable

    4.5.0

    Core Forms 4.5.0 makes standalone forms easier to share and stops unrelated pages from paying the CSS cost of features they do not use.

    Read full notes 11 changes

    The licensed updater serves the immutable 4.5.0 package with SHA-256 fc8759e85d4a841556311a2c670e1de7c4e4bd42dcc0e684449acc7cadd3f2d5.

    • Highlights
    • Add clean, configurable standalone URLs such as /collect/form-slug/, while preserving legacy ?cf-form links.
    • Load frontend assets from each rendered form’s actual capabilities; basic forms no longer load Smart Forms CSS.
    • Support native Post/Redirect/Get submissions when AJAX is disabled.
    • Add global and per-form analytics controls, explicit partial-entry capture, consent filtering, runtime diagnostics, and form-usage discovery.
    • Fix SQLite activation migrations, poll-cookie scope, and AJAX validation responses.
    • Verification
    • 190 PHPUnit tests / 386 assertions
    • PHPStan and ESLint clean
    • WordPress Studio clean activation and upgrade tests on WordPress 7.0.2, PHP 8.2, SQLite
    • Playwright coverage for AJAX success/error, asset gating, calculations, native submissions, and no-form pages
  28. Stable

    4.4.3

    Fixed

    Read full notes 4 changes
    • Fixed
    • Send Email, Auto-Responder, and Emailit action cards now show variables for the current form fields on the Actions tab.
    • Field variables are rendered server-side instead of depending on Fields-tab JavaScript.
    • Added regression coverage for named, array, duplicate, and internal field handling.
  29. Stable

    4.4.2

    See CHANGELOG.md for the full release history.

    Read full notes 8 changes
    • Security
    • Enforces the 254-character email limit and each field's declared maxlength on the server.
    • Rejects nested form values and encoded submission metadata above 60 KiB before hooks, storage, or notifications.
    • Keeps uploaded file bytes outside that metadata ceiling; upload size remains controlled by the field and PHP limits.
    • Fixed
    • Restores single and multiple multipart file uploads by normalizing PHP's $_FILES data into the submission pipeline.
    • Prevents invalid and spam submissions from moving files or persisting temporary upload paths.
    • Fixes per-form rate-limit settings, hourly expiry, and AJAX error visibility.
  30. Stable

    4.4.1

    Fixed the Gutenberg Core Form block preview taking about 60 seconds to load on busy editor screens by replacing the generic WordPress server-render request with a focused Core Forms preview endpoint, a summary-only form selector, and shared…

    Read full notes 2 changes
    • Fixed
    • Fixed the Gutenberg Core Form block preview taking about 60 seconds to load on busy editor screens by replacing the generic WordPress server-render request with a focused Core Forms preview endpoint, a summary-only form selector, and shared request caching.
  31. Stable

    4.4.0

    Core Forms 4.4.0 includes the complete feature set originally planned for roadmap versions 4.4 and 4.5.

    Read full notes 37 changes
    • Added
    • Added inline Stripe Payment Element checkout with server-owned product pricing, idempotent PaymentIntent creation, and signed webhook confirmation.
    • Added first-class Razorpay hosted checkout with payment-link, captured-payment, failure, cancellation, and refund handling.
    • Added one-click importers for Ninja Forms and Formidable Forms alongside the existing CF7, Gravity Forms, WPForms, and Fluent Forms migration tools.
    • Added WP-CLI commands for form import/export/listing, submission maintenance, product and plan administration, license reporting, order reporting, and expiry maintenance.
    • Added native actions for WooCommerce, Easy Digital Downloads, SureCart, WP Simple Pay, MemberPress, LearnDash, Paid Memberships Pro, Groundhogg, Jetpack CRM, WP-CRM System, and SureContact.
    • Added AutomatorWP, Uncanny Automator, and OttoKit triggers and actions with form and submission payloads.
    • Added signed inbound WhatsApp webhooks for Meta Cloud API and Twilio, including reply correlation and delivery-state history in submission conversations.
    • Added a multi-product licensing and lightweight ecommerce system with products, plans, orders, subscriptions, customer accounts, activation limits, refunds, renewals, and audited signed downloads.
    • Added a dedicated customer dashboard for orders, masked/revealable keys, product downloads, activated sites, and subscription controls.
    • Added free, Stripe, Razorpay, and renewal license-form templates with complete payment and fulfillment actions.
    • Added a default Sample Product with free, USD annual, and INR annual plans on new and upgraded sites.
    • Added native Bricks and Elementor integrations plus a per-form WCAG 2.2 audit and conservative one-click repairs.
    • Changed
    • The form editor now renders only the active tab instead of executing every tab's PHP, JavaScript, analytics, and REST requests on every page load.
    • The visual builder now boots from server-rendered form and schema data, removing its two blocking initial REST requests.
    • Builder saves now persist markup and schema atomically through one endpoint with a bounded timeout and a standard form-post fallback.
    • Tab-specific saves merge with existing form settings, preserving payment and action configuration when saving Fields, Messages, or other individual tabs.
    • Licensing actions are always visible under a dedicated Commerce & Licensing category instead of disappearing when the public activation API is disabled.
    • Product and plan slugs are generated automatically, normalized, and made unique; manually entered slugs remain supported.
    • Plan prices are entered in customer-facing major units such as 49.00 instead of minor units such as 4900.
    • Product packages use the WordPress Media Library picker and uploader instead of requiring an attachment ID.
    • The licensing backend now includes catalog statistics, quick-start guidance, direct Add plan/Add package links, and file names instead of raw attachment IDs.
    • The existing core-forms.com CF Licenser client, option keys, 32-character key format, six-hour heartbeat, and update hooks remain separate from and compatible with the new merchant licensing subsystem.
    • Fixed
    • Fixed the Fields builder remaining on an indefinite loading spinner when either initial REST request stalled.
    • Fixed inactive Analytics requests and form-builder assets loading on unrelated form tabs.
    • Fixed paid plans being fulfillable from a non-payment form or before verified payment confirmation.
    • Fixed payment fulfillment accepting a mismatched paid amount or currency when validation is enabled.
    • Fixed free plans being incorrectly coupled to a payment requirement.
    • Fixed action-variable references showing a permanent Loading message when the Fields builder was not present.
    • Fixed stale admin asset caches by versioning the main admin stylesheet and licensing script from their file modification times while keeping the plugin version at 4.4.0.
    • Security
    • License fulfillment is idempotent per submission and product selection, preventing duplicate orders or keys during webhook retries.
    • Signed package links expire, verify the stored SHA-256 digest before streaming, and record downloads in an audit table.
    • Verified refunds disable issued licenses and cancel related subscriptions.
    • Inbound messaging and payment webhooks require provider signatures before they can change submission, payment, or fulfillment state.
  32. Stable

    4.3.8

    New - Field names accept uppercase. The builder's Name field no longer force-lowercases input (HTML name/id are case-sensitive). Illegal characters are still sanitized. - Textarea options: Rows (height), Resize behaviour (default /…

    Read full notes

    New - Field names accept uppercase. The builder's Name field no longer force-lowercases input (HTML name/id are case-sensitive). Illegal characters are still sanitized. - Textarea options: Rows (height), Resize behaviour (default / vertical / horizontal / both / none), and a live character counter that shows "used / limit" when a Max length is set. An explicit Rows value now wins over the 5-line default height. - Phone (tel) value limits: new Min length, Max length, and Pattern controls to constrain accepted values.

    Fixed - The builder's HTML generator silently dropped textarea min/max-length and conditional-logic attributes on save, so those validations were lost. The textarea output now matches the server-side renderer.

  33. Stable

    4.3.7

    Bug-fix release.

    Read full notes 1 change

    PHPStan had originally flagged this; the error had been suppressed in phpstan-baseline.neon rather than fixed. That stale baseline entry is now removed.

    • Fixed critical error after plugin, theme, or core updates and rollbacks. The upgrader_process_complete migration callback was registered under the plugin namespace (Core_Forms\_cf_on_upgrader_complete), but that function is defined in the global namespace, so it was an invalid callback that triggered a fatal TypeError whenever WordPress finished an update or rollback. It surfaced as "There has been a critical error on this website" on the update/rollback screen. The callback is now registered with the correct name, so updates complete cleanly.
  34. Stable

    4.3.6

    This release is about making the default Core Form accessible by default — not "accessible if the author remembers to opt in." Whether you load only the skeleton (forms.css), only the themed stylesheet (form-theme.css), or both, the floor…

    Read full notes 10 changes

    🤖 Generated with Claude Code

    • Accessibility floor for every Core Form (and Core Poll) input. This release is about making the default Core Form accessible by default — not "accessible if the author remembers to opt in." Whether you load only the skeleton (forms.css), only the themed stylesheet (form-theme.css), or both, the floor holds.
    • What's in
    • 44 × 44 CSS px touch target on every form control. WCAG 2.5.5 AAA target size. Applied to every text-type input, select, textarea, and button in both stylesheets so the rule survives whether the theme is loaded, disabled, or partially overridden.
    • Windows High Contrast Mode-safe keyboard focus. The themed :focus-visible state used to be outline: none + coloured box-shadow — HCM strips the box-shadow and the ring vanishes. Now :focus-visible pairs the box-shadow with a transparent 2px outline; HCM forces the transparent outline to the system focus colour, so keyboard users on HCM still see a ring.
    • Accessibility baseline in forms.css. Authors who disable the form theme used to drop back to a bare browser stylesheet. The skeleton now ships a tiny accessibility section at the top — 44px target, currentColor focus outline, prefers-reduced-motion transition kill-switch — so disabling the theme doesn't disable accessibility.
    • Textareas are 5 lines tall by default. Browsers ship rows="2" which is comically short for paragraph answers. Both stylesheets now set min-height: calc(5lh + 22px) (with a 140px px fallback for older browsers) — textareas grow with the host theme's line-height instead of being pinned to a px value.
    • Asset loading
    • Form and poll stylesheets now print at the bottom of <head>. Enqueue priority bumped from 20 → 99 so wp_enqueue_style calls land after the host theme's. WordPress prints in enqueue order → Core Forms styles cascade over theme styles cleanly, no !important, no specificity arms race.
    • Poll CSS is back in <head>. poll-frontend.css used to enqueue inside render_poll_shortcode() during the_content — after wp_head had already printed — so it landed in the footer. PollFrontend::maybe_enqueue_detected_poll_assets() now pre-scans for core-forms/poll blocks and [cf_poll] shortcodes at wp_enqueue_scripts priority 99 and pre-enqueues the stylesheet. Lands in <head> on poll pages, omitted entirely everywhere else.
    • Upgrading: Just update. If a textarea on a live form previously sat awkwardly between 2 and 4 lines, it'll now be a comfortable 5; everything else is non-visual or strictly additive.
  35. Stable

    4.3.5

    If you've been running 4.3.3 or 4.3.4 and noticed the Core Forms block in the editor showing a generic blue "CF" square icon and a single dropdown — no live preview, no inspector panels — this release fixes it.

    Read full notes 8 changes

    src/admin/class-admin.php was still enqueuing a legacy assets/js/gutenberg-block.js (a pre-4.0 hand-written registerBlockType call) on enqueue_block_editor_assets. That script registered core-forms/form first, so every modern block-form.js bundle — with ServerSideRender, inspector controls, and the correct form icon — was shipping in every zip but never actually loading in the editor.

    The legacy wp_enqueue_script() call also passed no version argument, which is why network-tab diagnostics showed gutenberg-block.js?ver=7.0 (the WP core version) instead of the plugin version. Thanks to the user who reported this from their network tab — that's what pinpointed it.

    🤖 Generated with Claude Code

    • Hotfix release — restores the Gutenberg block editor experience.
    • Root cause: If you've been running 4.3.3 or 4.3.4 and noticed the Core Forms block in the editor showing a generic blue "CF" square icon and a single dropdown — no live preview, no inspector panels — this release fixes it.
    • Changes
    • Removed the enqueue_block_editor_assets listener and enqueue_gutenberg_assets() method from class-admin.php.
    • Deleted the orphan assets/js/gutenberg-block.js.
    • block.json now owns the entire editor lifecycle — register_block_type(__DIR__ . '/block.json') loads assets/js/build/block-form.js with the modern Edit component, and the version: "4.3.5" field cache-busts it against CORE_FORMS_VERSION.
    • Reverted the 4.3.4 form-picker label change back to Title (slug) so forms sharing a base title stay distinguishable in the dropdown.
    • Upgrading: Just update. Hard-refresh the editor once (Cmd/Ctrl+Shift+R) to clear the cached gutenberg-block.js?ver=7.0 from your browser — after that the modern block editor UI is back.
  36. Stable

    4.3.4

    Two performance memoisations and three UX improvements layered on top of the 4.3.3 bug fixes. No breaking changes, no migrations.

    Read full notes 18 changes
    • Performance
    • cf_get_form() is request-scoped memoised. The same form requested multiple times per page (block render, get_html, action loop, analytics tracker) no longer re-fetches the post + meta and rebuilds the settings/messages arrays. Each call returns a clone so future callers can't poison the cached instance with property mutations. Invalidation: save_post_core-form (always) and *_post_meta hooks gated on get_post_type() so other CPT meta touches don't trash the cache.
    • cf_count_form_submissions() is request-scoped memoised. The forms list table called this per-row — a 50-form admin issued 50 COUNT(*) queries; now it issues one per (form_id, is_spam) pair and the rest are cache hits. Invalidated on cf_submission_inserted.
    • UX
    • Block-editor preview skeleton. The Gutenberg block preview shows an animated shimmer skeleton (title bar → input rows → submit button) while ServerSideRender is fetching, instead of a bare spinner. Respects prefers-reduced-motion.
    • Cleaner form picker. The block's form-picker dropdown shows just the form title instead of \"Title (slug)\" — much cleaner when titles are distinct. The slug is still surfaced via the Edit Form deep link beneath the picker.
    • / keyboard shortcut on the forms list. Press / or s to focus the search box. Standard list-UI shortcut (GitHub, GitLab, Linear, every modern dashboard). Skipped when an input, textarea, or contenteditable already has focus so it never hijacks typing.
    • 4.3.3 fixes are intact
    • The wp_cf_submission_replies table self-heal and the un-spam action-replay parity from 4.3.3 are untouched — verified 10 call sites still wired.
    • Upgrade notes
    • No data or schema migrations.
    • No breaking API changes.
    • The cache-invalidation hooks are guarded with function_exists('add_action') to match the existing convention in functions.php, so the file remains autoload-safe for standalone test environments.
    • Verified
    • 151 unit tests pass.
    • PHPStan reports no errors.
    • Production zip ships at 815 KB with no test framework, no PHPStan, no composer.json.
    • block-form.js rebuilt; bundle still contains wp.serverSideRender and the new cf-block-skeleton styles.
  37. Stable

    4.3.3

    Bug-fix release.

    Read full notes

    Fixed: fatal "Table 'wp_cf_submission_replies' doesn't exist" when opening a submission. The reply-history feature queried a table that no installer or migration ever created. The table is now created on activation, on new-blog insert, and on multisite activation, and existing installs are backfilled by a 4.3.3 migration so they self-heal on update.

    Fixed: submissions-table "Not Spam" bulk action did not fire form actions. Moving a submission out of spam from the submissions table now replays the form's success and configured actions (notifications, integrations) that were skipped at submit time, matching the behavior of the spam-page single and bulk paths. The replay is centralised in cf_replay_submission_actions() so the three un-spam paths can't drift apart.

  38. Stable

    4.3.2

    Zip SHA-256: 1eb8f317ed899596f1df041fa84e501e72a191c9367b4a9adb4c4487557cc052

    Read full notes 4 changes

    Zip SHA-256: 1eb8f317ed899596f1df041fa84e501e72a191c9367b4a9adb4c4487557cc052

    • Optimized frontend asset loading so forms.js, accessibility.js, analytics.js, and form styles load only when a Core Forms block or shortcode is present.
    • Removed redundant Core Form block viewScript metadata because rendered forms enqueue the runtime directly.
    • Added tests for form asset detection, including a poll-only case.
    • Synced release requirements to WordPress 6.4+ and PHP 8.1+.
  39. Stable

    4.3.0

    Stable release. Marks the end of the v4.3 beta cycle (beta1 → beta6).

    Read full notes 12 changes

    Stable release. Marks the end of the v4.3 beta cycle (beta1 → beta6).

    Vote integrity rewrite: every vote stores a voter_hash (poll + IP + UA + cookie + user) and dedupe queries that one column regardless of mode. Cookie set on render with SameSite=Lax; Secure, persists across AJAX. vote_limit=user rejects anonymous voters at submit. Honeypot on by default, per-IP rate limiter (12/minute).

    Scheduling (start date + hourly cf_poll_auto_close cron), change-vote window, Gutenberg block (core-forms/poll) with picker + display-mode, opt-in live results (15s, pauses on hidden tab), bar / columns / percent result styles, container-query-driven adaptive layout, REST API (/cf/v1/polls, /polls/{id}/results public, /polls/{id}/analytics auth), per-poll analytics screen + CSV export.

    Accessibility: <fieldset><legend>, role="progressbar" with aria-valuenow, role="status" aria-live="polite", focus moves to result heading on submit, prefers-reduced-motion honored. jQuery removed from poll JS.

    Schema migration (cf_db_version → 4.3.0) is additive with backfill so historical dedupe keeps working.

    All three plug into the existing Core Forms → Import page via a new cf_import_sources filter + cf_import_render_section action exposed by CF7Migration, with shared helpers in a BaseMigration abstract class.

    • Polls — full rework: Tabbed editor (Question / Settings / Schedule / Embed / Results), drag-to-reorder options, "Other" write-in toggle, Duplicate row action.
    • Importers — three new sources
    • Gravity Forms — GFAPI-driven, ~14 field types, notifications → Email actions with per-recipient conditions, confirmations → success message / redirect, conditional logic → data-show-if / data-hide-if. Field IDs resolve through a per-form name map so condition references stay valid.
    • WPForms (Lite + Pro) — Decodes the form JSON, maps notifications, optional entry import from wp_wpforms_entries (Pro) into wp_cf_submissions so admin history survives the cutover.
    • Fluent Forms — Reads wp_fluentform_forms + wp_fluentform_form_meta directly (no plugin dependency), maps fields, notifications, webhooks, and conditional logic.
    • Send Email — conditional emails (per recipient): New "Recipient routes" repeater on the Send Email action. Each route has a field + operator + value + recipient address; the first matching route's recipient overrides the default To. The existing action-level conditions block keeps working — that gates whether the action runs at all; routes only re-target where it sends.
    • Forms list: Fix for the Duplicate row action: it used to drop the user into the editor for the original form because the URL carries a form_id and the overview page short-circuited into the editor before the list table's single-row handler could run.
    • Build & CI: ESLint inheritance cleared (~80 prettier autofixes + targeted eqeqeq / no-unsafe-wp-apis / no-noninteractive-element-interactions fixes); PHPStan baseline regenerated at level 5; PHP 8.1 / 8.2 / 8.3 unit tests green.
    • Upgrade notes
    • Migration is automatic on next admin pageload (or on plugin update via upgrader_process_complete).
    • New WP-Cron hook cf_poll_auto_close is scheduled hourly; unscheduled on deactivation.
    • New post meta keys for importer provenance: _cf_gf_source_id, _cf_wpforms_source_id, _cf_fluent_source_id — useful for debugging or re-import workflows.
  40. Beta

    4.3.0-beta6

    Pre-release. Bug-fix pass on the beta5 importers and conditional emails.

    Read full notes 6 changes

    Install on staging only. Real installs stay on 4.2.10 until stable 4.3.0.

    • Fixes
    • Per-recipient conditions never actually filtered the recipient. The three new migrators (Gravity, WPForms, Fluent) were saving conditions on Email actions using op / is / isnot, but cf_evaluate_action_conditions() consumes operator / equals / not_equals. Empty-operator rows were being skipped entirely, so every recipient match returned true and every notification fired regardless of the source plugin's conditional logic. Now writes the keys/vocab the engine actually understands.
    • Gravity / WPForms conditional logic referenced nonexistent field names. Both plugins reference fields in their rules by numeric ID. Our import was naively emitting field_<id> references while the rendered HTML used sanitize_key(label) names — so the data-show-if attributes pointed at fields that didn't exist on the page. Each migrator now builds a per-form field-id → rendered-name map up front and translates references through it.
    • Rendered field names collided when two source fields shared a label. sanitize_key('First Name') → firstname for every field labelled "First Name". Names now always carry an _<id> suffix so duplicates stay distinct (and empty labels still get field_<id>).
    • data-show-if attribute syntax was wrong. The runtime parser (in assets/js/forms.js) expects field:value, not field=value, and uses data-hide-if to express inversion rather than != inline. BaseMigration::build_conditional_attr() now emits the syntax the runtime actually parses and flips show↔hide when the rule is negated.
    • WPForms entry count now shows in the success notice. The importer was redirecting back with entries_total in the URL but nothing rendered it. The CF7 importer page now shows "(N entries imported too)" alongside the "Imported X forms" notice.
  41. Beta

    4.3.0-beta5

    Pre-release. Ships the four "Shipping now / v4.3" items from the public roadmap.

    Read full notes 7 changes

    Install on staging only. Real installs stay on 4.2.10 until stable 4.3.0.

    • What's new
    • Gravity Forms importer: Reads forms via GFAPI, converts fields (text/email/phone/url/number/date/textarea/select/multiselect/radio/checkbox/file/name/address/consent and friends) to HTML. Every notification becomes a Send Email action — and when the source notification had its own conditional-logic block, that block carries across as per-recipient conditions on the Email action. The default confirmation maps to the success message or redirect URL. Field-level conditional logic carries across as data-show-if / data-hide-if attributes. Source Gravity Forms data is never modified.
    • WPForms importer (Lite + Pro): Decodes the form JSON stored in wp_wpforms.post_content, converts the field map to HTML, turns each notification into an Email action (with per-recipient conditions when applicable). When the Pro wp_wpforms_entries table is present, optionally imports stored entries into wp_cf_submissions so admin history isn't lost during the cutover.
    • Fluent Forms importer: Reads wp_fluentform_forms + wp_fluentform_form_meta directly — no Fluent API dependency, so the importer also works on sites where the source plugin is deactivated but its data is still in the database. Converts the field map to HTML (recursing into Fluent's container columns), walks the notifications meta_key for Email actions, picks up webhook-shaped meta_keys as Trigger Webhook actions, and maps the form's default confirmation to the success message / redirect URL.
    • Conditional emails (per recipient): New Recipient routes repeater under the Send Email action. Each route has a field + operator + value + recipient address; the first matching route wins, otherwise the default "To" address is used. The existing action-level conditions block keeps working — that decides whether the action runs at all; routes only re-target where it sends.
    • Importer extension point: CF7Migration's source picker is no longer hardcoded. Added cf_import_sources filter + cf_import_render_section action so third-party migrators can plug into the existing Core Forms → Import page. The three new migrators use these hooks via a shared BaseMigration abstract class.
    • Carried over from earlier 4.3 betas: Polls rework (tabbed editor, vote-integrity rewrite, Gutenberg block, REST, live results, analytics + CSV, accessibility pass, adaptive container-query layout). Duplicate row action fix on the forms list.
  42. Beta

    4.3.0-beta4

    Pre-release. Visual + layout pass on the polls rework.

    Read full notes 2 changes

    Container-driven adaptive layout. Dropped the fixed 560px max-width for width: 100% + container queries. Padding, border radius, and type scale tune to the actual container width (cqi units + clamp), so a sidebar poll on a 4K monitor stays compact and a full-width poll on a phone collapses to a stacked footer. Viewport @media fallback for browsers without container query support.

    Options auto-flow. Short option lists like "WordPress / Wix" now sit side-by-side when there's room (auto-fit, minmax(min(240px, 100%), 1fr)); forced single-column inside the bars layout so each bar gets full width.

    Layout bug. The radio/checkbox was dropping the option label to a second line on the front-end because the label was display: block with a display: flex child. The label itself is now flex.

    Visual polish. Pill result bars (10px instead of 24px), softer card shadow, larger submit hit area with active-state feedback, refined focus rings.

    Install on staging only. Real installs stay on 4.2.10 until stable 4.3.0.

    • Changes vs beta3: Editor preview now matches the front of the site. The poll stylesheet only enqueued on the public side, so Gutenberg's ServerSideRender preview fell back to browser-default form styling. Registered the CSS as both style and editor_style on the block so editor and frontend use identical visuals.
    • Carried over from earlier betas: Tabbed editor, drag-to-reorder, "Other" write-in, vote-integrity rewrite (voter_hash dedupe, cookie-on-render with SameSite=Lax; Secure, user-mode anon rejection, honeypot, per-IP rate limit), hourly auto-close cron, Gutenberg block, REST endpoints, live results, change-vote window, bar/columns/percent styles, analytics screen + CSV export, accessibility pass, jQuery removed, schema migration with backfill.
  43. Beta

    4.3.0-beta3

    Pre-release. Same scope as beta2 + one access fix.

    Read full notes 3 changes

    Install on staging only. Real installs stay on 4.2.10 until stable 4.3.0.

    • Fix vs beta2
    • Poll analytics page returned "Sorry, you are not allowed". The hidden analytics screen registered under the core-forms parent and then called remove_submenu_page() to hide the menu entry — but removing from \$submenu also strips the slug from WP's URL allowlist, so user_can_access_admin_page() rejected everyone except super-admins. Switched to an empty parent slug; the page now resolves at admin.php?page=cf-poll-analytics&poll=X and honors the per-page edit_posts cap.
    • Polls rework (carried over): Tabbed editor, drag-to-reorder, "Other" write-in, vote-integrity rewrite (voter_hash dedupe, cookie-on-render with SameSite=Lax; Secure, user-mode anon rejection, honeypot, per-IP rate limit), hourly auto-close cron, Gutenberg block, REST endpoints, live results, change-vote window, bar/columns/percent styles, analytics screen + CSV export, accessibility pass, jQuery removed, schema migration with backfill.
  44. Beta

    4.3.0-beta2

    Pre-release. Same scope as v4.3.0-beta1 but pinned to the commit where CI is green (ESLint + PHPStan + PHP 8.1/8.2/8.3 unit tests all pass).

    Read full notes 11 changes

    Install on staging only. Real installs stay on 4.2.10 until stable 4.3.0.

    • What's new vs beta1
    • ESLint clean: ~80 prettier formatting issues autofixed, eqeqeq != null → explicit !== undefined && !== null, @wordpress/no-unsafe-wp-apis and jsx-a11y/no-noninteractive-element-interactions silenced where intentional.
    • Polls rework (carried over from beta1)
    • Tabbed editor (Question / Settings / Schedule / Embed / Results), drag-to-reorder options, Duplicate row action, "Other" write-in toggle.
    • Vote integrity rewrite: voter_hash dedupe, cookie set on render (and persisted from AJAX), vote_limit=user rejects anon at submit, honeypot, per-IP rate limit, hourly auto-close cron.
    • Gutenberg block core-forms/poll + REST endpoints (/cf/v1/polls/{id}/results public, list/single/analytics auth).
    • Live results polling (opt-in, 15s, pauses while tab hidden), change-vote window, bar/columns/percent result styles.
    • Per-poll analytics screen + CSV export of raw votes.
    • Accessibility <fieldset><legend>, role="progressbar" + aria-valuenow, aria-live status region, focus management, prefers-reduced-motion.
    • jQuery removed from poll frontend and admin JS.
    • Schema migration (cf_db_version → 4.3.0) with backfill so historical dedupe keeps working.
  45. Beta

    4.3.0-beta1

    Pre-release. Real installs continue to update to 4.2.10 — opt in to this beta only on staging.

    Read full notes 26 changes
    • Polls rework: Schema migration (cf_db_version → 4.3.0), tabbed editor, Gutenberg block, REST API, analytics screen, CSV export, hourly auto-close cron, accessibility pass, and a full vote-integrity rewrite.
    • Editor
    • Tabbed editor (Question / Settings / Schedule / Embed / Results) replaces the metabox screen
    • Drag-to-reorder options, Duplicate row action, "Other" write-in toggle, dedicated type selector (single vs. multiple)
    • Vote integrity
    • Every vote now stores a voter_hash (poll + IP + UA + cookie + user) and dedupe queries against that single column regardless of mode
    • Cookie set on render with SameSite=Lax; Secure; HttpOnly; AJAX requests persist a fresh cookie too (was previously broken because admin-ajax doesn't fire send_headers)
    • vote_limit=user rejects anonymous voters at submit (was silently letting them vote unlimited times)
    • Honeypot field on by default; per-IP rate limit (12 votes/minute) covers both real submits and honeypot trips
    • Hourly cf_poll_auto_close cron flips status to closed once the end time passes
    • Frontend & block
    • core-forms/poll Gutenberg block (no-build, vanilla JS) — picker dropdown + display-mode (auto / results-only / form-only); server-render shares code with the shortcode
    • Result styles: bar (default), columns, percent-only
    • Optional live results polling (15 s, opt-in per poll; pauses while tab is hidden)
    • Optional change-vote window (per-poll, in minutes) — re-renders the form pre-checked
    • Accessible markup: <fieldset><legend>, role="progressbar" with aria-valuenow, role="status" aria-live="polite", focus moves to result heading on submit, respects prefers-reduced-motion
    • Results & analytics
    • REST: GET /cf/v1/polls/{id}/results (public), GET /cf/v1/polls and /polls/{id} and /polls/{id}/analytics (auth)
    • Per-poll analytics screen with totals, unique voters, 30-day SVG line chart, option breakdown
    • CSV export of raw votes (option label, value, voter_hash, IP, user, voted_at, referrer)
    • JS
    • Removed jQuery from the poll frontend and admin scripts
    • Schema migration: Adds type, starts_at, allow_other, post_close_behavior, redirect_url, enable_live_results, change_vote_window to wp_cf_polls. Adds option_value, voter_hash, referrer to wp_cf_poll_votes plus a (poll_id, voter_hash) composite index. Existing rows are backfilled so historical dedupe keeps working.
    • Known follow-ups for stable 4.3.0
    • Donut style currently falls back to bar rendering (CSS hook exists)
    • Image-option polls / NPS / rating types are deferred to 4.4.0
  46. Stable

    4.2.10

    Duplicate row action now duplicates the form. Clicking Duplicate on the forms list used to drop the user into the editor for the original form because the duplicate URL carries a form_id and the overview page short-circuited into the editor…

    Read full notes 2 changes
    • Fixes
    • Duplicate row action now duplicates the form. Clicking Duplicate on the forms list used to drop the user into the editor for the original form because the duplicate URL carries a form_id and the overview page short-circuited into the editor before the list table could run its single-row action handler. The overview now processes action=duplicate_single first, clones the form, and redirects back to the list with ?duplicated=1.
  47. Stable

    4.2.9

    Also: fixes two pre-existing PHPStan warnings that were blocking the release pipeline.

    Read full notes 5 changes
    • Container builder polish
    • Add Field popover redesigned. Fixed 360px width with a 4-column icon grid, header bar, and a dedicated close button. Dismisses on outside-click or Escape.
    • Containers default to a single column. New Containers ship as plain wrappers; opt into a grid via the Layout panel when you actually want one.
    • Column changes preview in real time. The canvas duplicates the .cf-row grid rules locally, so editing column counts updates the preview immediately.
    • Better drop-target affordance. Empty containers and group bodies show a dashed outline at rest and a solid blue highlight while dragging.
  48. Stable

    4.2.8

    Selecting a Container on the Fields tab now reveals a Layout section in the inspector sidebar with the column controls. Three column-count inputs (desktop / tablet / mobile, 1–6 each) plus a free-text gap field. Tablet and mobile inherit…

    Read full notes 4 changes
    • Patch: Container field column controls in the inspector sidebar: Selecting a Container on the Fields tab now reveals a Layout section in the inspector sidebar with the column controls. Three column-count inputs (desktop / tablet / mobile, 1–6 each) plus a free-text gap field. Tablet and mobile inherit from the next breakpoint up when left blank.
    • Settings persist on the field and emit as inline CSS variables (--cf-cols, --cf-cols-t, --cf-cols-m, --cf-gap) on the saved .cf-row wrapper, so the runtime form picks them up via the existing rules in forms.css.
    • The canvas now applies the same CSS variables to the container's drop area, so the drag-and-drop preview mirrors the runtime grid instead of stacking fields vertically.
    • New Containers ship with cols_desktop: 2, cols_mobile: 1, gap: 1rem by default — a useful starting point you can override per breakpoint.
  49. Stable

    4.2.7

    "Core Polls" no longer registers its own top-level menu item. Polls now live as two submenu entries (Polls + Add Poll) under the Core Forms menu, so the admin sidebar reads as one product instead of two side-by-side icons.

    Read full notes 4 changes
    • Patch: Polls moved under the Core Forms admin menu: "Core Polls" no longer registers its own top-level menu item. Polls now live as two submenu entries (Polls + Add Poll) under the Core Forms menu, so the admin sidebar reads as one product instead of two side-by-side icons.
    • PollAdmin::add_admin_menu() switched from add_menu_page to two add_submenu_page calls under the core-forms parent.
    • admin_menu hooked at priority 20 so Admin::menu() (default priority 10) has already registered the parent slug before Polls tries to attach.
    • New parent_file filter keeps the Core Forms top-level item highlighted (and selects the right submenu sub-item — Polls list vs Add Poll) while editing, creating, or listing polls. Without it, the WP post-type screens would blank out the sidebar's active state.
  50. Stable

    4.2.6

    The Preview button that landed on the Add Form gallery in 4.2.4 now also appears on the template picker that opens inside the per-form Fields tab (the React visual builder).

    Read full notes 4 changes
    • Patch: preview button on the per-form template chooser: The Preview button that landed on the Add Form gallery in 4.2.4 now also appears on the template picker that opens inside the per-form Fields tab (the React visual builder).
    • Each non-blank card carries a "Preview" pill in its top-right corner. Hovering or focusing the card reveals it; clicking it opens the same iframe modal the Add Form gallery uses. event.stopPropagation stops it from also firing the parent "select template" click.
    • The preview modal moved from inline page markup into Admin::render_template_preview_modal, hooked on admin_footer for every Core Forms admin screen. Click handling is delegated — any element with data-cf-preview="{slug}" (anywhere on a Core Forms page) fires it. window.CoreFormsAdmin.openTemplatePreview(id, label) is exposed for programmatic triggers.
    • Localized cfFormTemplates entries now carry a preview_url so the React builder (or any other JS) doesn't have to re-derive the admin-ajax URL.
  51. Stable

    4.2.5

    Three fixes / one-line connections that were missing in 4.2.4.

    Read full notes 5 changes
    • Patch: template preview + Create Comment surface + default actions: Three fixes / one-line connections that were missing in 4.2.4.
    • Template preview iframe now actually loads. The wp_ajax_cf_template_preview action was being registered on the Admin class constructor, which is gated behind ! DOING_AJAX — so the AJAX handler was never wired during AJAX requests. WP's admin-ajax fell through to its default "0" output and the iframe showed a blank page. Registered the handler in the AJAX branch separately with a lazy-constructed instance.
    • Create Comment action now appears in the Actions tab picker. The action class registered fine via cf_available_form_actions, but the WordPress category in tab-actions.php didn't list create_comment in its types array — so the grouped grid skipped it. Now slotted in next to create_user/create_post with an admin-comments dashicon.
    • Every starter template lands with a default Email action wired. Previously a brand-new form had no actions at all — submissions saved to the inbox but never emailed anyone. process_create_form() now appends a default "Email the admin" action when the template doesn't ship its own. Templates that DO ship actions (product_review → Create Comment, payment templates → providers) keep their wiring untouched.
    • Product review + Lightweight comment templates ship with Create Comment pre-wired. Field mappings — NAME → comment author, EMAIL → author email, REVIEW/COMMENT → content, RATING → rating meta — plus a default Email notification. Open the form, pick a target post on the action, save — done.
  52. Stable

    4.2.4

    This release adds a proper review/comment workflow (star rating field + a Create Comment action that writes to WordPress comments with aggregate rating meta), five new starter templates with a sandboxed preview iframe on the Add Form…

    Read full notes 20 changes
    • Star ratings, comments, and a much richer admin: This release adds a proper review/comment workflow (star rating field + a Create Comment action that writes to WordPress comments with aggregate rating meta), five new starter templates with a sandboxed preview iframe on the Add Form gallery, a column-layout container with responsive breakpoints, real-time preview sync in code mode, and a bunch of admin clarity fixes.
    • Star rating + comments
    • New .cf-rating field type — radio-based 1–5 star picker with CSS-mask icons inlined as data URIs (works whether or not the form theme is loaded). Keyboard-reachable with per-star screen-reader labels. Reverse-ordered radios + the adjacent-sibling cascade fill stars to the left of hover/check.
    • New Create Comment / Review action — posts the submission as a WordPress comment against a target post (numeric id, [field] reference, or auto-detected via referer URL). When a rating field is configured, stores the value as comment meta rating and recomputes the target post's cf_rating_average + cf_rating_count post meta — Schema-rich-snippet plugins read these keys by convention. Status flips (pending → approved) trigger a recompute via transition_comment_status.
    • Code-mode toolbar gains Insert star rating + Insert columns row buttons.
    • Five new starter templates: | Template | Use | |---|---| | Product review | Star rating + headline + comment, paired with the Create Comment action | | Lightweight comment form | AJAX-submitted drop-in for the native WP comment form | | NPS / satisfaction survey | 0–10 scale + reason + optional email | | Bug report | Severity, browser, steps, attachment — two-column layout | | Product waitlist | Email + company + source, two-column layout |
    • Template preview iframe: Every non-blank template card on the Add Form gallery now has a Preview button that opens a modal iframe loading the markup via wp_ajax_cf_template_preview. Capability-gated to edit_forms, loads the same forms.css + form-theme.css a real form would use, submit-disabled so nothing fires.
    • Columns layout container (.cf-row): CSS helper driven by inline CSS variables — --cf-cols, --cf-cols-t, --cf-cols-m, --cf-gap — sets desktop / tablet (≤1024px) / mobile (≤640px) column counts up to 6 each. Variable chaining means setting only the desktop count cascades to tablet and mobile. Code-mode inserter prompts for the three numbers and drops the wrapper in.
    • Real-time preview sync: Code-mode textarea now pushes its current markup to the preview iframe on every keystroke (180ms debounce) via postMessage. The iframe replaces #cf-preview-root innerHTML in place. Origin- and form-id-scoped so a cross-form iframe can't be poisoned.
    • Form editor preview honours the global stylesheet toggles: The admin asset enqueue now conditionally loads forms.css and form-theme.css (with cf_form_theme_tokens overrides) when you're on a form-edit screen, so the visual builder canvas and code-mode iframe both render with the same stack the front-end uses. Previously the editor preview was unstyled even with the theme on globally.
    • Settings clarity
    • Skeleton CSS vs Default form theme — both options renamed with explicit descriptions of what they load. Skeleton (forms.css, ~1.5 KB, structural only — labels, error states, button alignment, the new column-row helper). Theme (form-theme.css, opinionated visual layer — colors, radii, focus rings, typography). Choices are "Load / Skip".
    • After Submission — clearer two-way choice ("Show success message" / "Redirect to a URL"). Contextual help appears with the selection. The redundant "Redirect to a page" option was removed; the URL field already covers that case.
    • Per-form Settings tab now opens with only the first accordion (Submissions) — previously two opened simultaneously.
    • "Add-ons" → "Extras" in Settings + Messages section labels.
    • Action merge: CreatePost + CreateArticle: The richer CreateArticle (title/content/excerpt mapping, taxonomies, ACF, featured image, author lookup) now claims the canonical create_post slug and the label "Create Post / Article / CPT". Forms saved with the old create_article type are forwarded to the merged handler at runtime — no migration.
    • Bug fixes / hardening
    • vendor/autoload.php require is now file_exists()-guarded so a partial extraction during an in-place plugin upgrade can't fatal the site. Clear admin notice surfaces on the next page load if vendor/ is genuinely missing.
    • Template preview wp_die() calls now pass HTTP codes via the response arg instead of as the title. Unauthorized hits actually return 403/400/404.
    • CreateComment recompute only fires when a valid in-range rating actually landed as comment meta; out-of-range values skip the recompute.
  53. Stable

    4.2.3

    Adds a CF_DEMO_MODE wp-config constant guard so the public demo build at core-forms.com/demo can be safely handed out via token-gated R2 — the plugin self-disables anywhere except playground.wordpress.net subdomains. No-op for production…

    Read full notes

    Adds a CF_DEMO_MODE wp-config constant guard so the public demo build at core-forms.com/demo can be safely handed out via token-gated R2 — the plugin self-disables anywhere except playground.wordpress.net subdomains. No-op for production sites.

  54. Stable

    4.2.2

    Patch release. Hot-fix for the headless embed.

    Read full notes 3 changes

    Patch release. Hot-fix for the headless embed.

    Applied to both success and error code paths.

    • What was wrong: The bundled embed.js (served from /wp-json/core-forms/v1/embed.js) was rendering result.data.message directly into the success card. But the form processor returns it as an object — { type: 'success', text: '...' } — not a string. JavaScript stringified the object to literal [object Object], so every successful headless submission ended with that string in the success card. Same shape bug in the error path.
    • What's fixed: Added a pickText() helper that: - Plucks .text when the message is an object. - Returns the value when it's already a string (for forward-compat). - Falls back to a sensible default (Thanks! / Submission failed.) when the field is missing.
    • Who's affected: Anyone running the drop-in embed widget (the `
  55. Stable

    4.2.1

    Patch release.

    Read full notes 4 changes
    • Patch release.
    • Per-form spam view routes correctly: ?page=core-forms&view=spam&form_id=X&tab=submissions now opens the form-edit screen on the Submissions tab in spam-filter mode instead of falling through to the all-forms list. The router branched on view=edit; it now branches on the presence of form_id so any view value (spam / all / inbox) routes correctly.
    • Submissions list — visual cleanup: Dropped the 3px blue / red inset left border on new and spam rows and the muted grey text on spam rows. Status is communicated entirely by the badge in the STATUS column (New / Read / Replied / Spam) — much cleaner against WP's native striped table.
    • Dashicon alignment fix for WP < 7.0: Buttons that pair a dashicon with text (Documentation, Refresh, Open, copy buttons in the Headless tab) had the icon glyph sitting ~2px above the text baseline on WordPress 6.9.x and earlier. WP 7.0 normalized this natively; for older WP a high-specificity rule scoped to Core Forms admin screens applies vertical-align: middle, line-height/font-size resets, and :has(.dashicons) inline-flex centering to match.
  56. Stable

    4.2.0

    Stable release. Consolidates eleven betas (v4.2.0-beta through v4.2.0-beta11) into one shipping version.

    Read full notes 31 changes

    Stable release. Consolidates eleven betas (v4.2.0-beta through v4.2.0-beta11) into one shipping version.

    Both Cloud API and Twilio sends log through Email Logs. The cf_form_redirect_url filter now fires on every successful submission and receives the Submission as a 4th argument.

    • WhatsApp, three ways: Three new actions cover the full range of WhatsApp delivery models — pick whichever fits your existing stack.
    • WhatsApp Cloud API action. Send template messages and free-form text (24-hour window) via Meta's Graph API. Free tier covers 1,000 conversations per month. Credentials live globally under Settings → WhatsApp Cloud API with per-action override; a "Test connection" button reports the verified business name + quality rating.
    • Twilio WhatsApp action. For shops already on Twilio — reuses your Account SID / Auth Token, posts to the whatsapp: channel, supports approved Content Template SIDs.
    • Click-to-WhatsApp redirect. Generates a wa.me deep link with the submission pre-filled into the chat draft, used as the post-submit redirect.
    • Contact Form 7 → Core Forms migration tool: New page under Core Forms → Import that scans every wpcf7_contact_form post, converts shortcode markup to plain HTML (14 tag types covered), maps the CF7 mail template to a Send Email action, and carries messages overrides across as cf_message* post meta. Per-row preview lets you sanity-check before committing. Gravity Forms, WPForms, Fluent Forms, Ninja Forms, Formidable previewed as "Coming soon" cards.
    • Per-form analytics dashboard: New Analytics tab on every form-edit screen, powered by the existing cf/v1/analytics/* REST API: - One "Funnel" postbox with views, starts, submissions, spam. - SVG daily-activity chart with all three series overlaid. - Field interactions panel (where users focus/fill). - Top sources panel (UTM attribution with referrer-domain fallback). - Auto-generated recommendations — high spam rate, low completion, drop-off hotspots. - Date-range presets (7d / 30d / 90d / 1y) + custom from/to.
    • Form versioning + change history: The core-form post type now declares 'supports' => […, 'revisions', …]. cf_settings, _cf_hidden_columns, and every cf_message override persist alongside each revision. Settings-only or messages-only saves still create a revision (we force wp_save_post_revision_check_for_changes to false for core-form). New Revisions* tab lists each snapshot with author, timestamp, and a diff signal — restore drops back into the Core Forms admin with a flash and copies meta back automatically.
    • Security hardening — 14 audit findings fixed
    • CSRF on by default (existing installs preserved via 4.2.0 migration).
    • Submission mass-assignment closed via markup-derived allowlist.
    • Headless API key header-only; new CORS allowlist textarea.
    • Workflow /actions/test bumped to manage_options.
    • Webhook SSRF guard: cf_is_safe_outbound_url() rejects loopback / RFC1918 / link-local / IPv6 ULA / non-HTTP schemes.
    • Email header CRLF injection closed via cf_esc_email_header().
    • Custom CSS `` escape closed.
    • process_save_form inline cap+nonce check.
    • Two ghost wp_ajax_* handlers removed.
    • Polls trust REMOTE_ADDR only.
    • Draft saves rate-limited (30/IP+form/min).
    • File upload blocklist extended (html/htm/xhtml/xml/xsl/xslt).
    • Honeypot returns opaque success.
    • Admin redesign — WordPress-native everything
    • New plugin icon (Font Awesome Pro pen-field) across admin menu, block inserter, and editor placeholder.
    • Analytics + Revisions tabs use native WP chrome end-to-end — .postbox, .wp-list-table widefat striped, .tablenav top, .row-actions, native .notice variants.
    • Button styling unified — removed the .button-primary glow override that broke consistency.
    • Fullscreen / Typeform-style display mode promoted to its own top-level card on Settings.
    • WhatsApp actions surfaced in Add Action picker under new "Messaging & SMS" category.
    • Per-form Template picker unified with Add-New-Form gallery — all 12 templates available everywhere.
    • Headless [CF_REFERRER_URL] fix: Cross-origin Referer headers are stripped to the bare origin by browsers. The submit endpoint now reads _cf_page_url from the JSON body and substitutes it into $_SERVER['HTTP_REFERER'] for the duration of Forms::process(). Bundled embed.js forwards window.location.href automatically.
    • Build pipeline: Production builds run through bash build.sh which executes composer install --no-dev so dev-only autoload entries can't leak. 148 unit tests pass; PHPStan clean against regenerated baseline; production zip 741KB.
    • Upgrade: Download the attached zip and upload via Plugins → Add New → Upload. Existing data, settings, and forms are preserved. The 4.2.0 migration runs automatically on first admin pageload after upgrade.
  57. Beta

    4.2.0-beta11

    Template picker on the per-form builder now reads from the same cf_get_form_templates() registry the Add-New-Form gallery uses — all 12 templates available everywhere instead of just 5. Button styling unified: removed the .button-primary…

    Read full notes

    Template picker on the per-form builder now reads from the same cf_get_form_templates() registry the Add-New-Form gallery uses — all 12 templates available everywhere instead of just 5. Button styling unified: removed the .button-primary brand-blue + glow override on Core Forms admin pages, so Save Form now matches Refresh, Restore, and every other native .button on the same screen.

  58. Beta

    4.2.0-beta10

    Postbox header padding bumped from WP's tight default (8px/12px) to 14px/16px on the Analytics and Revisions tabs. Same WordPress chrome, just with breathing room.

  59. Beta

    4.2.0-beta9

    Pre-release. Polish pass on beta8 based on visual feedback.

    Read full notes 6 changes

    Pre-release. Polish pass on beta8 based on visual feedback.

    ` for the chart-empty and recommendations-empty cases.

    Carries over everything from v4.2.0-beta8.

    • What changed
    • Stat boxes restructured: Beta8 left the four funnel stat numbers in individual postboxes — each one carried an empty postbox-header bar at top, wasting vertical space and not matching anything else in WP admin. Replaced with one Funnel postbox containing a 4-column grid of label / number / hint (matches the "At a Glance" dashboard widget pattern).
    • Empty states no longer use .notice: The .notice notice-info inline empty states inside postbox bodies brought their own colored left bar — which read as a UI element nested inside another UI element. Replaced with plain `
    • Recommendations now render as real .notice rows: Each recommendation is now a native .notice .notice-success / .notice-warning / .notice-info — so the colored left bar is WordPress's own variant rather than a plugin-flavored tint.
    • Revisions: dropped the "Live" pill badge: Replaced the custom badge with plain Live version text. No more custom badge colors.
    • Deployed and verified: Live on gatilab.com — plugin active at 4.2.0-beta9.
  60. Beta

    4.2.0-beta8

    Pre-release. Builds on v4.2.0-beta7.

    Read full notes 11 changes

    Pre-release. Builds on v4.2.0-beta7.

    No more rounded custom panels, no oversized stat numbers, no plugin-flavored colors. The tabs blend with the rest of WP admin.

    Carries over everything from v4.2.0-beta7 (WSOD fix, analytics/revisions bugfixes, security hardening, WhatsApp, CF7 migration).

    • What changed: Rewrote the Analytics + Revisions tabs to use standard WordPress admin chrome instead of custom card panels. They now look at home in the WP admin alongside the rest of the post-edit screens.
    • Native patterns now used
    • .postbox / .postbox-header / .hndle / .inside containers — the same primitives WP uses for dashboard widgets and post-edit metaboxes.
    • .wp-list-table widefat striped for the field-interactions, top-sources, and revisions history tables.
    • .tablenav top for the analytics date-range toolbar.
    • .row-actions (View diff | Restore) on revision rows, mirroring the Posts list pattern.
    • .notice notice-info inline / .notice notice-warning inline for empty states.
    • .column-primary + data-colname on revision rows for native responsive behavior.
    • Native .button / .button-primary for date-range presets.
    • Plugin polish kept: Only the bits that genuinely have no native equivalent: - Severity-tinted left-bar recommendations (a list of typed alerts has no built-in WP component). - The daily-activity SVG line chart. - A small "Live" pill badge on the current-version revision row.
    • Deployed and verified: Live on a test install — plugin active at 4.2.0-beta8, frontend 200.
  61. Beta

    4.2.0-beta7

    Pre-release. Hot-fix for the WSOD that affected beta5 and beta6.

    Read full notes 3 changes

    Pre-release. Hot-fix for the WSOD that affected beta5 and beta6.

    The namespaced callback string resolved to nothing, and at init time WordPress fataled with \"function not found\" — taking the admin (and depending on cache state, the whole site) down.

    Beta6's function_exists('add_action') guard helped CLI tools (PHPUnit, PHPStan, dump-autoload) load functions.php without fataling, but never addressed the runtime fatal. Sites running beta5 or beta6 still saw the WSOD.

    Verified on a live install: - Plugin active at 4.2.0-beta7 - Frontend 200 - Admin 302 (login redirect — no fatal) - php -r 'require autoload.php; var_dump(function_exists(\"_cf_wire_revisions\"));' → bool(true)

    Everything else from the beta5/beta6 release notes (analytics tab, revisions tab, CF7 migration, WhatsApp actions, security hardening) is intact and unchanged.

    • What was wrong: Beta5 added an init-action callback registered as 'Core_Forms\_cf_wire_revisions'. But src/functions.php doesn't declare a namespace — every function in it (cf_get_form, cf_get_settings, _cf_wire_revisions, etc.) lives in the global namespace despite the use Core_Forms\Form; at the top of the file.
    • What's fixed: The init callback is now registered as plain '_cf_wire_revisions'.
    • Upgrade strategy: If you tested beta5 or beta6 and hit a blank screen, this is your fix. Download the attached zip and upload via Plugins → Add New → Upload — WordPress will replace your existing install.
  62. Beta

    4.2.0-beta6

    Pre-release. Critical fix on top of v4.2.0-beta5.

    Read full notes 15 changes

    Pre-release. Critical fix on top of v4.2.0-beta5.

    The registration is now wrapped in function_exists( 'add_action' ) so functions.php is safe to load standalone.

    • ⚠️ Critical — fixes a WSOD some users hit on beta5: beta5 added a top-level add_action() call at the bottom of src/functions.php that fired during composer's files-autoload step. Inside a WordPress request that was fine — plugin.php (which defines add_action) loads before plugins. But outside WP — PHPUnit, PHPStan, custom CLI tools, or any other plugin that requires our vendor/autoload.php before WP's plugin loader runs — add_action was undefined and the plugin fataled at autoload, taking the whole site down.
    • This was the root cause of the WSOD reported on test sites running beta5.
    • Analytics tab bugfixes
    • Field-interactions table reads the interactions column the Dashboard actually returns (was reading count, so every row showed 0).
    • Top-sources panel maps the Dashboard's {utm_sources, referrers} shape correctly (was reading the non-existent top_sources). Falls back to referrer-domain rows when no UTM tags are in use.
    • Recommendations substitute the value (e.g. completion-rate %) into the printf-style message template instead of showing the literal %s%%.
    • Revisions tab bugfixes
    • Restore redirects back to Core Forms admin (?page=core-forms&view=edit&form_id=X&tab=revisions&restored=1) instead of WordPress's native post.php editor, which doesn't render Core Forms' custom UI. A success flash confirms the restore.
    • Meta-only saves create revisions. wp_save_post_revision_check_for_changes is set to false for core-form, so settings-only or messages-only saves snapshot a revision instead of being silently dropped by WP's content-diff check.
    • Revision-meta filter is now version-agnostic. wp_post_revision_meta_keys passes the parent in WP 6.4+ but earlier patches may have passed the revision; the callback resolves a parent id defensively so the check matches on both.
    • Build pipeline
    • Regenerated phpstan-baseline.neon (previous baseline was stale after the beta CSRF default flip — enable_nonce shape change broke ignore patterns).
    • Build script now exits clean: 148 unit tests pass, PHPStan analyse clean.
    • Production zip (738KB) ships without phpstan, phpunit, tests, or composer.json — all dev deps stripped via composer install --no-dev in the build step.
    • Use bash build.sh for releases. Never rsync the dev vendor directly — that's how dev-only autoload_files entries (phpstan/bootstrap.php) ended up in the deployed autoloader earlier today.
  63. Beta

    4.2.0-beta4

    Pre-release. Quick UI consistency fix on top of v4.2.0-beta3.

    Read full notes 1 change

    Pre-release. Quick UI consistency fix on top of v4.2.0-beta3.

    The Import page's custom .cf-import__flash flash variants were also swapped for native .notice .notice-success / .notice-warning, and the orphaned CSS rules removed.

    Carries over everything from v4.2.0-beta3 (WhatsApp picker, headless referer fix, Import page redesign, prominent Display mode card).

    • What changed: Removed the body.toplevel_page_core-forms .notice CSS override in design-system.css that gave admin notices on Core Forms screens a rounded 4px-left-bar look. Notices now match WordPress's native styling exactly — squared corners, native left border, no plugin-flavored variation.
  64. Beta

    4.2.0-beta3

    Pre-release. Iterating on v4.2.0-beta2 based on tester feedback.

    Read full notes 10 changes

    Pre-release. Iterating on v4.2.0-beta2 based on tester feedback.

    Cross-origin Referer headers are stripped to the bare origin (https://example.com) by browsers under the default strict-origin-when-cross-origin policy, so without this [CF_REFERRER_URL], [CF_REFERRER_HOST], [CF_REFERRER_PATH], and [CF_POST_ID] were resolving to the WP REST endpoint's own URL on every embed.

    • What changed
    • WhatsApp actions now show in the per-form Add Action picker: All three v4.2.0 WhatsApp actions (Cloud API, Twilio WhatsApp, Click-to-WhatsApp redirect) live under a new Messaging & SMS category alongside Twilio SMS. They show up regardless of whether global WhatsApp Cloud credentials have been configured — credentials can be filled per-action when no global ones exist. Previously the picker only surfaced actions present in the static category map, so the three new actions were silently hidden.
    • Headless [CF_REFERRER_URL] etc. now resolve correctly: The headless submit endpoint now reads _cf_page_url from the JSON body and substitutes it into $_SERVER['HTTP_REFERER'] for the duration of Forms::process(). The bundled embed.js automatically forwards window.location.href; the native-fetch snippet in the Headless tab now shows this pattern too.
    • Import page redesigned
    • Renamed in the sidebar from "Import (CF7)" to Import — this page will house migration paths from multiple form plugins.
    • New source-picker card grid: Contact Form 7 (active), plus Gravity Forms, WPForms, Fluent Forms, Ninja Forms, and Formidable as visibly muted "Coming soon" cards.
    • CF7 form list rebuilt as a custom card-style layout below the picker rather than a wp-list-table.
    • Replaced the WP-native red-bar notice-error with a clean inline empty state.
    • Typeform-style mode is prominent: Promoted from a buried row inside the "Add-ons" accordion at the bottom of the Settings tab to a dedicated Display mode card at the top, with a marketing-style pitch panel explaining what Fullscreen mode is for. Card auto-opens when the form is already in fullscreen.
    • Carried over from earlier betas: See v4.2.0-beta for the WhatsApp / CF7 migration / 14 security fixes changelog, and v4.2.0-beta2 for the new Core Forms icon.
  65. Beta

    4.2.0-beta2

    Pre-release. Builds on v4.2.0-beta.

    Read full notes 9 changes

    Pre-release. Builds on v4.2.0-beta.

    Single visual language across every touchpoint:

    viewBox is normalised to a square 640×640 so the natural 640×512 glyph reads balanced at small render sizes. Menu fill stays black so WordPress's color-scheme stylesheet can tint it for active/hover states; block icons use currentColor for Gutenberg's hover/selected states.

    See v4.2.0-beta release notes for the full v4.2.0 changelog.

    • What's new: Replaced the abstract circular "C" admin-menu icon and the generic clipboard block-inserter icon with pen-field from Font Awesome Pro 7.2 — a square frame containing an input row and a pen.
    • WP admin sidebar menu
    • Gutenberg block inserter
    • In-editor Placeholder state (shown when no form is selected)
    • Carried over from v4.2.0-beta
    • WhatsApp Cloud API, Twilio WhatsApp, and Click-to-WhatsApp redirect actions
    • CF7 → Core Forms migration tool (forms + messages, with preview)
    • WhatsApp activity logging through Email Logs
    • 14 security audit findings fixed (CSRF default-on, headless API key header-only, headless CORS allowlist, webhook SSRF guard, email header CRLF injection, custom CSS &lt;/style&gt; escape, polls/drafts hardening, file upload blocklist extended, honeypot returns opaque success, and more)
  66. Beta

    4.2.0-beta

    Pre-release. Distribution channel for testers before 4.2.0 GA.

    Read full notes 29 changes

    Pre-release. Distribution channel for testers before 4.2.0 GA.

    The cf_form_redirect_url filter now fires on every successful submission (not just when a per-form Redirect URL is set) and receives the Submission as a 4th argument. Existing 3-arg handlers keep working.

    Each row in the importer table has a "Preview converted HTML" disclosure so you can sanity-check before committing. CF7 stays installed and untouched — run both side-by-side during cutover. Flamingo submission import is out of scope.

    Full commit: b37bfae

    • WhatsApp, three ways
    • WhatsApp Cloud API action. Meta Graph API. Template + free-form modes. Global creds (Settings → WhatsApp Cloud API) with per-action override. Includes a Test connection button that pings /v21.0/{phone_number_id} and reports verified business name + quality rating.
    • Twilio WhatsApp action. Reuses your existing Twilio SID/token; posts to the whatsapp: channel. Optional Content Template SID for business-initiated outreach.
    • Click-to-WhatsApp redirect. Generates a wa.me deep link with the submission pre-filled into the chat draft and injects it as the post-submit redirect.
    • Contact Form 7 → Core Forms migration: New page at Core Forms → Import (CF7). Scans every wpcf7_contact_form post and converts: - Shortcode markup → plain HTML (text, email, tel, url, number, date, hidden, textarea, select, checkbox, radio, acceptance, file, submit, recaptcha) - CF7 mail template → Core Forms Send Email action - _messages meta → cf_message_* post meta (so your custom success/validation/spam copy carries over)
    • Operational polish
    • WhatsApp activity in Email Logs. Both Cloud API and Twilio sends log through the existing cf_email_logs table. The Type column labels them; Resend is suppressed for non-email rows (which would otherwise try to wp_mail a phone number).
    • cf_log_email() now switches between sanitize_email and sanitize_text_field based on action type.
    • Security hardening (14 audit findings fixed)
    • CSRF default flipped on. New installs get enable_nonce=1. Existing installs are preserved at 0 via a 4.2.0 migration that writes the prior value explicitly into stored settings. Sites that have always cached aggressively can keep nonces off; sites that haven't been should turn them on.
    • Submission mass-assignment closed. Forms::process() intersects POST keys with field names declared in the form markup. Filterable via cf_allowed_field_names.
    • Headless API key is header-only. The ?cf_key= query-string fallback is gone (leaked into logs/history/Referer).
    • Headless CORS allowlist. New textarea at Settings → Headless → Allowed origins. Empty preserves 4.1 behavior with an admin warning.
    • Workflow /actions/test requires manage_options. No longer a wp_mail / wp_remote / paid-SMS-anywhere primitive in editor-level hands.
    • Webhook SSRF guard. New cf_is_safe_outbound_url() helper rejects loopback, RFC1918, link-local, IPv6 unique-local, and non-HTTP schemes. Webhook auth header name/value also strip CR/LF.
    • Email header CRLF injection closed. New cf_esc_email_header() sanitizer replaces strip_tags on every header substitution in Email, Emailit, and Autoresponder actions.
    • Custom CSS &lt;/style&gt; escape closed. The previous regex pattern didn't consume the closing &gt;. Now strips every &lt; from custom CSS at both save and render time.
    • process_save_form gains inline cap+nonce check (defense in depth — matches the existing guard on process_create_form).
    • Two ghost wp_ajax_* handlers removed (registered methods that didn't exist; calling them returned a fatal).
    • Polls trust REMOTE_ADDR only. HTTP_CLIENT_IP and HTTP_X_FORWARDED_FOR no longer honored by default. Opt back in via cf_poll_trust_forwarded_for for sites behind a trusted reverse proxy.
    • Draft saves rate-limited to 30 new drafts per IP+form per minute (filterable via cf_draft_save_rate_limit).
    • File upload blocklist extended with html, htm, xhtml, xml, xsl, xslt. Closes a stored-XSS path where nginx (which ignores the uploads .htaccess) served uploaded HTML as text/html on the WP origin.
    • Honeypot returns opaque success on missing/populated field instead of WordPress's silent 0 response — bots can no longer distinguish "rejected" from "accepted but never processed."
    • Upgrade notes
    • Backwards-compatible: the CSRF migration only writes enable_nonce=0 into installs that had no explicit value before, so existing form-bearing cached pages keep working.
    • Behavior changes worth knowing:
    • Webhooks pointing at 127.0.0.1, 192.168.*, 10.*, etc. will now fail. Local dev environments needing the loopback can override via the cf_is_safe_outbound_url filter.
    • Forms with JS-injected fields not present in the static markup will have those keys dropped. Use the cf_allowed_field_names filter to opt them in.
    • Editor-role users with edit_forms can no longer test arbitrary actions via the REST endpoint — they can still test by saving the action first.
  67. Stable

    4.1.0

    Five months of beta cooking, condensed into one release: payments on submission, headless / cross-origin REST, six new payment-ready templates, a full admin redesign, and a bootstrap hardening that protects the site during plugin upgrades.

    Read full notes 31 changes

    New submission statuses (pending_payment, paid, payment_failed, refunded), atomic CAS on the paid-state transition so concurrent webhook retries can't double-fire the action loop, return-URL signing with 2-hour expiry to stop replay.

    | Template | Provider | Pricing | |---|---|---| | One-time payment | Stripe | Fixed $19 | | Donation | PayPal | Donor-entered via [AMOUNT] | | INR payment | Razorpay | Fixed ₹999 | | FluentCart product | FluentCart | Variation-driven, with address fieldset | | Subscription | FluentCart Pro | Variation-driven, recurring | | Event ticket | Stripe | Tier select drives [TIER] |

    Templates registry gained settings and messages callbacks alongside markup. Every starting point — payment and non-payment — now ships with a context-appropriate success message ("Redirecting to PayPal…", "Booking received…") instead of the generic "We will be in touch soon."

    • Payments on submission: Five providers, all bundled, all webhook-verified.
    • Stripe Checkout — hosted Checkout Sessions, test + live keys side-by-side
    • PayPal — Orders API, fixed or donor-driven amounts via [field] references
    • Razorpay — UPI / cards / wallets via Razorpay Checkout
    • Polar.sh — Standard Webhooks signature verification
    • FluentCart — hosted-checkout handoff. Free + Pro, one-time + subscriptions. Address fields prefilled into FluentCart's checkout (and its tax engine). Order paid → submission paid via fluent_cart/order_paid_done; refunds round-trip.
    • Headless / cross-origin REST: External sites — Astro, Next.js, Vue, Svelte, plain HTML — can now render and submit Core Forms over REST. Same validation, captcha, action loop and payment redirect machinery runs server-side; the headless site just submits JSON.
    • GET /wp-json/core-forms/v1/forms/{id} — schema + rendered HTML
    • POST /wp-json/core-forms/v1/forms/{id}/submit — runs the full pipeline
    • GET /wp-json/core-forms/v1/embed.js — drop-in vanilla JS widget
    • Single API key per site (Settings → Headless), per-form opt-in toggle
    • Snippets in three flavours: widget, native fetch, cURL — each pre-filled with your actual submit URL + active key
    • New "Keeping the API key private" guidance card with copy-paste server-side proxy templates for Cloudflare Workers / Pages Functions, Next.js App Router, and Astro server endpoints
    • Six new payment-ready starting points: Each ships with a provider preselected so the form lands one configuration step away from working:
    • Admin redesign
    • Per-form Settings, Messages, Payment, Headless tabs converted to native &lt;details&gt;/&lt;summary&gt; accordions with state badges (rate-limit count, schedule "window set", honeypot on/off, FluentCart variation price/type/subscription summary, custom CSS/JS indicators, headless On/Off, configured/not-configured per gateway).
    • Per-form Submissions list rebuilt: Inbox / Spam / All view tabs with live counts (no more bouncing to global Spam to triage one form), redesigned table with status badges (New / Read / Replied / Archived / Paid / Pending payment / Refunded / Payment failed / Spam), row stripes for new/spam, per-row actions, relative dates with absolute on hover, varied empty states per view.
    • All Submissions page rebuilt for WordPress 7.0: toolbar split into a filter card (form picker + date range + Filter + Clear) and a search card. Consistent control heights so taller WP 7.0 native dates don't stagger the row. Side-fix: filter inputs are now in their own GET form so form_id / date_from / date_to actually land in the URL — previous version had them inside the bulk-actions POST form so filtering silently did nothing.
    • WordPress Screen Options dropdown hidden across all Core Forms admin screens.
    • Persistent "Akismet spam protection is active" banner removed from form-edit pages — status info doesn't belong as a banner on screens unrelated to it.
    • New cf_get_form_submissions / cf_count_form_submissions is_spam argument; new bulk_mark_spam per-form action.
    • Bootstrap hardening
    • vendor/autoload.php require now guarded with file_exists() so a mid-extraction race during a WordPress in-place plugin upgrade can't fatal the site. The upgrader replaces the plugin directory non-atomically; a hard require in that window kills every PHP request including wp-login.php. Now falls through cleanly and surfaces an admin notice on the next page load if vendor/ is genuinely missing.
    • Modernisation
    • Minimum requirements: PHP 8.1, WordPress 6.4
    • Schema\Field and Schema\FormSchema properties typed, declare(strict_types=1)
    • CI matrix runs PHP 8.1 / 8.2 / 8.3
    • prefers-reduced-motion respected throughout; logical-property RTL fixes
    • Fullscreen multi-step forms expose aria-current="step" + a polite live region for step changes
    • New filters + actions: cf_payments_orchestrator, cf_payment_completed, cf_form_default_settings, cf_form_templates. Full upgrade guide at docs/getting-started/upgrade-to-4.1.md.
    • Upgrading: Drop-in compatible from 4.0.x. The vendor-autoload guard means in-place WP upgrades from 4.0.x → 4.1.0 won't fatal even on slow filesystems. Database migrations run automatically on activation / via upgrader_process_complete.
  68. Beta

    4.1.0-beta7

    A new "Keeping the API key private" accordion on every form's Headless tab walks through the three patterns that actually keep the site-wide API key out of the browser bundle.

    Read full notes 1 change

    Threat-model framing comes first — honest, not moralizing. The key only authorises form submissions on headless-enabled forms; the worst case is spam on those forms (no account access, no billing, no data exfil). But spam is annoying, so:

    Server-side proxy templates — copy-paste, with the form's actual submit URL pre-filled: - Cloudflare Pages Functions / Workers (wrangler secret put) - Next.js App Router route handler (process.env, never NEXT_PUBLIC_*) - Astro server endpoint (import.meta.env, never PUBLIC_*)

    Captcha note: Turnstile / reCAPTCHA on the WP install verifies on every submission through the same pipeline — headless or not. Links straight to the global settings.

    Defense-in-depth checklist at the proxy: Origin allowlist, body size cap, User-Agent sanity, and an explicit "don't add a honeypot at the proxy" warning (browser autofill on field names like url / company / phone silently drops real submissions — the plugin has its own honeypot upstream).

    "If you must put the key in client code" — pragmatic close: not the end of the world, rotate when abused, watch the per-form Spam tab.

    • Headless tab — API key security guidance: A new "Keeping the API key private" accordion on every form's Headless tab walks through the three patterns that actually keep the site-wide API key out of the browser bundle.
  69. Beta

    4.1.0-beta6

    WP 7.0's taller native form controls (especially date inputs) caused the old toolbar to wrap onto four lines — bulk actions, then the form filter, then dates, then pagination, each on its own row. New layout:

    Read full notes 6 changes

    Consistent min-height: 36px across selects, date inputs, and buttons so the taller WP 7.0 dates don't stagger the row vertically. Stacks under 900px viewport.

    AllSubmissionsTable::extra_tablenav is now a no-op for the same reason (the WP_List_Table hook fires inside the wrong form).

    • Submissions page rebuilt for WP 7.0: WP 7.0's taller native form controls (especially date inputs) caused the old toolbar to wrap onto four lines — bulk actions, then the form filter, then dates, then pagination, each on its own row. New layout:
    • Filter card (top): form-picker + date range + Filter button + Clear link, in one row
    • Search card (right of the same row): search input + Search button
    • Bulk-actions row (under): bulk action select + Apply on the left, item count + pagination on the right
    • Cards grid below
    • Bonus fix: The previous markup had the filter inputs nested inside the bulk-actions POST form, so the "Filter" button never actually wrote form_id / date_from / date_to to the URL — and the listing reads $_GET. Filtering now uses an independent GET form, so query-string state survives the round trip.
  70. Beta

    4.1.0-beta5

    Templates registry gained a messages callback alongside markup and settings. Every template now ships with a context-appropriate Success message instead of the generic "We will be in touch soon":

    Read full notes 13 changes

    cf_get_template_messages() helper feeds the preset into cf_message_* post meta on form creation.

    • FluentCart fixes
    • Address fields collected on the form. FluentCart's checkout requires billing address by default. Beta4's templates didn't collect it, so users hit a half-empty checkout. The FluentCart product + subscription templates now include a billing fieldset (address line 1/2, city, state, postcode, country) named to match FluentCart's checkout schema.
    • Form fields prefill FluentCart checkout. The gateway maps submission data into cart-&gt;checkout_data['form_data'] so FluentCart auto-fills its inputs and TaxManager picks up country/state for tax. Two-pass mapping: billing_* / shipping_* keys forward verbatim; common aliases (NAME, EMAIL, COUNTRY, etc.) map to FluentCart equivalents.
    • Test/Live badge now reads FluentCart's own mode. The per-form Payment tab no longer shows the global Core Forms test/live badge for the FluentCart provider (which it doesn't gate). Instead reads FluentCart\Api\CurrencySettings's order_mode and renders "FluentCart: Live" / "FluentCart: Test" with a tooltip linking to the FC store settings.
    • FluentCart hidden when not installed. The gateway only registers when FluentCart's PHP classes exist. The "FluentCart product" and "Subscription" starter templates are filtered out of the Add Form gallery on the same condition.
    • Provider-switch resilience. FluentCart templates ship with a fallback payment_amount + currency so swapping to Stripe/PayPal/Razorpay later doesn't trip the gateway's "amount must be greater than zero" guard.
    • Per-template submission messages: Templates registry gained a messages callback alongside markup and settings. Every template now ships with a context-appropriate Success message instead of the generic "We will be in touch soon":
    • Payment templates — "Redirecting to PayPal…", "Welcome aboard…", etc. + payment-specific error copy
    • Contact — "Your message is on its way"
    • Newsletter — "You're on the list. Check your inbox"
    • Support — "Support ticket received. We'll reply within one business day"
    • Booking — "Booking received. You'll get a confirmation email"
    • (and so on for the rest)
  71. Beta

    4.1.0-beta4

    Six new templates in the Add Form gallery, each pre-configured with a payment provider so the form lands one step away from collecting money:

    Read full notes 5 changes

    | Template | Provider | Pricing | |---|---|---| | One-time payment | Stripe | Fixed $19 | | Donation | PayPal | Donor-entered amount via [AMOUNT] | | INR payment | Razorpay | Fixed ₹999 | | FluentCart product | FluentCart | Variation-driven | | Subscription | FluentCart Pro | Variation-driven, recurring | | Event ticket | Stripe | Tier select drives [TIER] amount |

    Templates registry now supports a settings callback alongside markup — new cf_get_template_settings() helper feeds the preset into the new form's _cf_settings meta on creation. Payment-category templates carry a blue "Payment ready" badge instead of the default "Accessible" one.

    • Payment-ready starting points: Six new templates in the Add Form gallery, each pre-configured with a payment provider so the form lands one step away from collecting money:
    • UI fixes
    • Global Payments settings: gateway accordions collapsed by default, not auto-opened on unconfigured gateways. Less visual noise; expand the one you're configuring.
    • Screen Options hidden: the WordPress Screen Options dropdown is suppressed across all Core Forms admin pages — All Forms, Add New, Settings, Spam, plus the per-form editor and submissions views.
    • Akismet banner removed: dropped the persistent "Akismet spam protection is active" notice on every form edit page. Status info doesn't belong as a banner on screens unrelated to it.
  72. Beta

    4.1.0-beta3

    Tested live against gauravtiwari.org's FluentCart 1.3.27 — beta2's correlation path was wrong:

    Read full notes 13 changes

    New UI primitives: - Pill-style Yes/No radios with hover/checked state - Number inputs with trailing unit hints (e.g. "submissions / IP / hour") - From → To range pairs for date and time - Day-of-week segmented picker — checked days fill blue - Monospace inset-shadow code textareas for Custom CSS/JS - Tightened form-table spacing inside accordions - Stacks to single column under 1100px viewport

    • FluentCart correlation fixes: Tested live against gauravtiwari.org's FluentCart 1.3.27 — beta2's correlation path was wrong:
    • Cart model uses cart_hash as its primary key, not id. Beta2 referenced $cart-&gt;id (always null), so the metadata-fallback path could never run. Removed it.
    • Order → Cart link goes through wp_fct_order_operations.cart_hash, not a direct $order-&gt;cart_id (no such column). The order_paid_done listener now walks Order → orderOperation → cart_hash → Cart and reads checkout_data['core_forms']['submission_id'].
    • Variations have no per-row currency; FluentCart is single-currency. Currency is now read from FluentCart\Api\CurrencySettings.
    • Per-form preview chip formats price using FluentCart's currency sign + position, surfaces subscription billing summary, trial days, and physical-fulfillment hints.
    • Form settings UI redesign: Six sections in the Settings tab now use &lt;details&gt;/&lt;summary&gt; accordions matching the Payment and Headless tabs. Each summary carries useful at-a-glance state:
    • Submissions — "rate limit 60/h" or "not stored" badges
    • After submission — confirmation type badge; redirect URL row only renders when redirect is selected
    • Anti-spam — honeypot on/off badge
    • Save & resume — on/off badge
    • Scheduling — "window set" / "always open" badge
    • Advanced — CSS / JS badges when custom code is present
    • Messages tab redesign: Same accordion pattern. Four core messages grouped under "Submission outcomes" with an explanatory header. Extension-injected &lt;tr&gt; rows get their own accordion when present, otherwise the section is omitted entirely.
  73. Beta

    4.1.0-beta2

    External sites (Astro, Next.js, plain HTML, anywhere) can now render and submit Core Forms over REST.

    Read full notes 18 changes
    • Headless / REST API: External sites (Astro, Next.js, plain HTML, anywhere) can now render and submit Core Forms over REST.
    • New endpoints under /wp-json/core-forms/v1:
    • GET /forms/{id} — schema (HTML + structured fields)
    • POST /forms/{id}/submit — runs the same validation/captcha/action pipeline as on-site submissions
    • GET /embed.js — drop-in vanilla JS widget
    • Site-wide API key (Settings → Headless) gates submissions; per-form Headless tab toggles exposure on/off and shows copy-paste snippets (widget, native fetch, cURL) pre-filled with the actual key.
    • Reveal/generate/copy controls on the API key field, status banners on the per-form tab.
    • CORS reflected per-origin; captcha is force-recommended since cross-origin submits can't use WP nonces.
    • FluentCart integration: Hosted-checkout handoff via FluentCart's own checkout — works on free + Pro, one-time + subscriptions.
    • New FluentCart payment gateway slots into the existing payments orchestrator alongside Stripe/PayPal/Razorpay/Polar.
    • Per-form Variation ID picker with live preview (title, price, payment type, link to FluentCart).
    • Listens to fluent_cart/order_paid_done to mark submissions paid and fire the post-payment action loop. order_status_changed_to_refunded syncs refunds back.
    • Pricing/currency come from the FluentCart variation — the form's Pricing fields are bypassed when this provider is selected.
    • Subscription variations work transparently on FluentCart Pro (FluentCart owns the recurring billing).
    • UI polish
    • Per-form Payment tab sections converted to native &lt;details&gt;/&lt;summary&gt; accordions matching the global Payments gateway list.
    • New Headless tab in the form editor with status banners, monospace code blocks, floating copy buttons, color-coded HTTP method tags.
    • Same-site gateways (FluentCart) skip the irrelevant Webhook URL row in global settings and explain why no credentials are needed.
  74. Beta

    4.1.0-beta1

    What's Changed

    Read full notes 6 changes
    • What's Changed
    • Add payment gateway integration (Stripe, PayPal, Razorpay, Polar)
    • Improvements
    • Convert per-form Payment tab (Provider / Pricing / After payment) to native &lt;details&gt;/&lt;summary&gt; accordions, matching the global Payments gateway list
    • Fixes
    • Fix undefined $form_id in submissions list tab (use $form-&gt;ID)
  75. Stable

    4.0.3

    Dashboard navigation, dashboard chrome, submissions polish, and updated documentation links.

    Read full notes 10 changes

    Stat tiles recoloured to the same restrained palette (32×32 icon chip, 18px/600 number, 12px label).

    .cf-btn family tightened to native WordPress scale: 7×14 padding, 13px/500, no brand shadow, no lift transform. .cf-btn--secondary uses the standard WP secondary palette so buttons sit comfortably next to native admin chrome.

    Extensible via the cf_action_value_labels filter. Applied in the per-form submissions table and the All Submissions cards.

    Strip action from new submissions — action is now in the default cf_ignored_field_names, so future submissions never store the AJAX router key. Existing rows still resolve through the friendly-label map.

    Hide column — the Data Management extension grows a non-destructive Hide Column toggle alongside Rename Column and Delete Column. Hidden columns are persisted per-form in _cf_hidden_columns post meta and merged with WordPress's get_hidden_columns(). Rename and Delete handlers keep that meta in sync.

    • Navigation
    • New shared views/admin-subnav.php — a tab bar (Forms · Add New · Submissions · Settings · Spam) included from every Core Forms dashboard page, with dashicons and an active-tab underline.
    • Old breadcrumb markup hidden via CSS so legacy includes degrade silently.
    • Page chrome — Form Theme Customizer card style: .cf-page-hero rebuilt as a clean white card matching the Form Theme Customizer: - 1px solid #dcdcde, 8px radius, subtle 0 1px 2px rgba(0,0,0,.04) shadow. - No gradients, no eyebrow pill, no chrome competing with the content. - Heading scales back to 18px / 600 / #1d2327; sub-text 13px / #50575e.
    • Submissions: Friendly action labels — new cf_friendly_action_label() helper maps stored WordPress AJAX action keys to human-readable labels: - cf_form_submit → Form Submission - cf_save_draft → Form Draft Saved
    • Documentation links: All in-app docs links now point to gauravtiwari.org/course/core-forms-training/ (the previous /core-forms/ subdirectory was defunct). The /product/core-forms/ landing page is reserved for marketing CTAs only.
    • Upgrade notes
    • No data or schema migrations.
    • Pure UI / chrome refresh plus opt-in column hiding — fully backwards compatible.
    • Existing submissions that already contain the action field stay intact and now render as friendly labels.
  76. Stable

    4.0.2

    Visual refresh — the admin dashboard and the default front-end form theme now share the design language of core-forms.com, with no webfonts loaded anywhere.

    Read full notes 13 changes

    Visual refresh — the admin dashboard and the default front-end form theme now share the design language of core-forms.com, with no webfonts loaded anywhere.

    New components: - .cf-page-hero — gradient page header with eyebrow pill, heading, sub-text, CTA row - .cf-btn family — primary / secondary / ghost in sm / lg sizes, with the marketing-site shadow + lift-on-hover - .cf-stat — KPI tile with brand-tinted icon chip

    WordPress chrome inside Core Forms pages picks up the new look: - .wp-list-table, .form-table inputs, .button-primary, .tablenav, .subsubsub, .notice - Brand-blue 4-step focus ring, 8px corner radii, layered shadow scale

    • Admin design system: New assets/css/design-system.css declares the brand / ink / surface / radius / shadow tokens lifted directly from the marketing site, scoped to Core Forms admin pages so other plugins are untouched.
    • Page redesigns
    • Forms overview opens with the hero plus four KPI stat cards (active forms, total submissions, submissions today, caught as spam) before the forms list.
    • Settings gets the same hero treatment with a Documentation CTA.
    • Default front-end form theme: Rewrote form-theme.css against the same tokens: - Brand-blue submit buttons with lift-on-hover and the marketing-site shadow (0 4px 12px rgba(47,99,245,.25)) - 8px input radii, hover state on inputs, brand-blue focus border with 4-step focus ring - Soft-tint success / error / warning messages with proper border colors - Secondary buttons for multi-step \"back\" - Dashed brand-tinted drop-zone styling for &lt;input type=\"file\"&gt; - Headings get proper letter-spacing and weight scale
    • No webfonts
    • The admin design system uses the WordPress system stack (-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, …).
    • The front-end form theme sets --cf-font: inherit, so each form picks up the host theme's font.
    • No fonts.googleapis.com requests anywhere.
    • Upgrade notes
    • No data or schema migrations.
    • Pure CSS / template chrome refresh — fully backwards compatible.
    • Custom form theme tokens (cf_form_theme_tokens option) keep working unchanged.
  77. Stable

    4.0.1

    Polish release on the 4.x line.

    Read full notes 8 changes

    Submission source - [CF_REFERRER_URL], [CF_REFERRER_HOST], [CF_REFERRER_PATH] - [CF_POST_ID], [CF_POST_TITLE], [CF_POST_URL] (resolved via url_to_postid() on the referrer)

    Logged-in user - [CF_USER_ID], [CF_USER_LOGIN], [CF_USER_EMAIL], [CF_USER_DISPLAY_NAME]

    Submission & timing - [CF_SUBMISSION_ID], [CF_DATE], [CF_TIME] (formatted with the site's date/time format)

    Site - [CF_SITE_NAME], [CF_SITE_URL], [CF_ADMIN_EMAIL]

    Click any [TOKEN] to insert it at the cursor of the most recently focused input or textarea inside the Actions tab. Brief green pulse confirms the insert. Works on the per-action help text codes too.

    • Actions tab — clean card redesign: Every configured action is now a single, unified .cf-action-card: - Icon sits inside the header where it belongs (no more orphan icon stranded to the left of the panel). - Header is a real button with aria-expanded; click to toggle, chevron rotates. - Remove action with confirmation; first card opens by default if there's only one. - Replaces the old dual chrome (PHP ::before blue title bar + JS-wrapped .cf-accordion) with a single source of truth rendered directly by PHP. - Works uniformly across all 28 action types (email, twilio_sms, slack, mailchimp, webhook, notion, airtable, autoresponder, hubspot, etc.).
    • New template variables for actions: cf_replace_data_variables() now resolves:
    • Click-to-insert in the variables reference: The Actions tab → "Available Variables" panel is now four columns (Form Fields, Submission Source, User & Session, Form & Site) with a tooltip on every token.
    • Per-action help lines updated: Email, Emailit and Autoresponder now document the most useful new tokens ([CF_REFERRER_URL], [CF_POST_TITLE], [CF_USER_EMAIL] / [CF_SITE_NAME]).
    • Upgrade notes
    • No data or schema migrations.
    • Pure UI / template-variable additions — fully backwards-compatible.
    • If a third-party extension still emits the legacy .cf-accordion markup around an action, it will keep rendering as before (no-op transitional CSS rule kept).
  78. Stable

    4.0.0

    First stable release on the 4.x line.

    Read full notes 13 changes
    • Highlights
    • Stylesheet bug fix. The Gutenberg block no longer auto-loads form-theme.css regardless of settings. The block now respects the global "Default form theme" toggle and the per-form override, matching the shortcode behavior. (Cause: style field in block.json was force-enqueueing the theme stylesheet on any page that used the block.)
    • Block inspector overhaul. New panels in the block sidebar:
    • Form — pick a form, jump to its admin editor.
    • Header — toggle to show the form title as a heading, choose H1–H6.
    • Layout — alignment toolbar (left/center/right), max-width (px/em/rem/%/ch), HTML anchor id, custom CSS class.
    • Stylesheets — per-block overrides ("use form/global setting", "force load", "force disable") for both form-theme.css and forms.css.
    • Stable version. Bumped from 4.0.0-b9 → 4.0.0 across the plugin header, block.json, package.json, and readme.txt.
    • Upgrade notes
    • No schema or data migrations.
    • If you previously relied on the block always loading form-theme.css, make sure your global "Default form theme" setting is enabled, or use the new per-block "Force load" override.
    • The max-width block attribute is validated against a strict CSS-length regex (px, em, rem, %, ch, vw, vh); other values are ignored.
    • Files changed: block.json, render.php, assets/js/src/blocks/form/edit.js, assets/js/build/block-form.js, core-forms.php, package.json, readme.txt.
  79. Beta

    4.0.0-b9

    Added

    Read full notes 7 changes
    • Added
    • Added a form template gallery and an accessibility report for saved form markup.
    • Added controls for form theme colors, spacing, typography, and field appearance.
    • Added a manual update check under License & Updates.
    • Fixed
    • Corrected submission-detail links after viewing, editing, or replying to an entry.
    • Made per-form theme settings respect the global default unless explicitly overridden.
  80. Beta

    4.0.0-b5

    Schema-backed Form Engine - JSON form schema with versioning, migration from legacy HTML - Visual ↔ Code bidirectional sync (edit HTML, updates visual builder and vice versa)

    Read full notes 4 changes

    Visual Form Builder - React-based 3-column layout: inserter | canvas | inspector - 25+ field types, drag-and-drop reordering, container/fieldset nesting - 6 starter templates, inline preview, fullscreen preview modal

    Smart Form Features - Multi-step forms with progress bar and step validation - Save & resume via tokenized draft links - Field calculations (safe parser, no eval) - Form scheduling (date/time/day-of-week windows) - Conditional logic with 14 operators and grouped AND/OR rules - Inline validation with accessible error messages

    21 Integrations - Notifications: Email, Autoresponder, Slack, Discord, Telegram, Twilio SMS - Marketing/CRM: Mailchimp, ConvertKit, ActiveCampaign, Brevo, Drip, MailerLite, HubSpot, FluentCRM - Data: Google Sheets, Notion, Airtable - Automation: Webhooks, Zapier, Make - WordPress: Create User, Create Post, Create Article/CPT with ACF mapping

    Workflow Automation - Async action queue with background processing - Automatic retries with exponential backoff - Action logs with structured execution tracking - Webhook HMAC-SHA256 signatures

    Analytics - Form views, starts, submissions, abandonments tracking - Field-level drop-off analysis - UTM and referrer attribution - Auto-generated recommendations

    Native Block Editor - ServerSideRender live preview in editor - Form picker with InspectorControls - Shortcode transform, block variations - Spacing and alignment supports

    Security - 50+ bugs found and fixed across 6 audit rounds - Upload hardening (MIME validation, 30+ blocked extensions) - PHPUnit (114 tests), PHPStan level 5, ESLint - ABSPATH guards, input sanitization, output escaping

    Documentation - 61 markdown files, 11,000+ lines - Getting started, form builder, smart forms, integrations, workflows, analytics, developer docs

    • What's New: Schema-backed Form Engine - JSON form schema with versioning, migration from legacy HTML - Visual ↔ Code bidirectional sync (edit HTML, updates visual builder and vice versa)
    • Requirements
    • WordPress 6.0+
    • PHP 7.4+
  81. Stable

    3.5.0

    Full CRUD REST API for submissions at cf/v1 namespace

    Read full notes 27 changes
    • What's New
    • REST API
    • Full CRUD REST API for submissions at cf/v1 namespace
    • Collection endpoints with pagination, filtering by status/spam/date/search
    • Status validation returns proper 400/404 errors
    • Submission Status Tracking
    • New status field: new, read, replied, archived
    • Auto-marks submissions as "read" when viewed
    • Auto-marks as "replied" after sending a reply
    • Bulk status actions in the submissions table
    • Status badges in the global submissions view
    • Conditional Actions
    • Run form actions only when field conditions are met
    • Operators: equals, not equals, contains, does not contain, is empty, is not empty
    • AND logic — all conditions must match for the action to fire
    • Spam Protection
    • Akismet whitelist keywords — bypass spam checks for trusted submissions
    • Configurable in Settings → Spam Protection
    • Quality of Life
    • One-click form duplication from the forms list
    • Status column included in CSV exports
    • Polls database tables now created on activation/migration
    • Consistent border-radius across admin UI
    • Security Fixes
    • Escaped all HTML name attributes in condition row output (XSS)
    • Added capability check to form duplication handler
    • REST API validates status values on update
  82. Stable

    3.4.0

    Send Email via Emailit — New action to send form notification emails through the Emailit API instead of wp_mail()

    Read full notes 13 changes
    • What's New
    • Emailit Integration
    • Send Email via Emailit — New action to send form notification emails through the Emailit API instead of wp_mail()
    • Emailit Subscribe — Add contacts to Emailit audiences on form submission, with multi-audience support and custom field mapping
    • Settings — Emailit API key configuration in global settings
    • Data Variable Fixes
    • Fixed [all:label] — was silently broken (never implemented). Now renders all submission fields with human-readable labels extracted from form HTML
    • Fixed [all], [CF_FORM_ID], [CF_FORM_TITLE] — also previously non-functional
    • Rewrote cf_replace_data_variables() with clean switch-based implementation
    • Auto-Fill Action Defaults
    • All actions (Email, Autoresponder, MailerPress, Emailit, Emailit Subscribe) now auto-detect field names from form HTML markup when first created
    • No more manually typing [EMAIL], [FIRST_NAME], etc. — fields are pre-populated
    • Full Changelog
  83. Stable

    3.3.2

    Fixed

    Read full notes 2 changes
    • Fixed
    • Changed license API communication to POST requests for license verification and update checks.
  84. Stable

    3.2.2

    Added

    Read full notes 5 changes
    • Added
    • Bundled extensions for file uploads, webhooks, submission limits, login requirements, notifications, and submission management.
    • Added hooks before and after fullscreen forms, plus head and footer hooks for customizing standalone form pages.
    • Fixed
    • Updated fullscreen form support and release packaging.
  85. Stable

    3.1.7

    This version packages Core Forms for WordPress with HTML-authored forms, Block Editor and shortcode embedding, AJAX submissions, email notifications, stored entries, and CSV export.

    Read full notes 1 change
    • Release Overview: This version packages Core Forms for WordPress with HTML-authored forms, Block Editor and shortcode embedding, AJAX submissions, email notifications, stored entries, and CSV export.
  86. Stable

    3.3.1

    Fix: Remove PrismJS syntax highlighting overlay that caused cursor position mismatch in code editor

    Read full notes 2 changes
    • Fix Remove PrismJS syntax highlighting overlay that caused cursor position mismatch in code editor
    • Replace with clean dark-themed textarea editor
  87. Stable

    3.3.0

    New: MailerPress integration - subscribe form submitters to MailerPress lists with field mapping, tag assignment, and double opt-in support

    Read full notes 3 changes
    • New MailerPress integration - subscribe form submitters to MailerPress lists with field mapping, tag assignment, and double opt-in support
    • New Fluent Cart + MailerPress integration - automatically add customers to MailerPress when a Fluent Cart order is paid
    • Both integrations load conditionally only when the partner plugins are active
  88. Stable

    3.0.0

    Complete rebrand from HTML Forms to Core Forms

    Read full notes 8 changes
    • Complete rebrand from HTML Forms to Core Forms
    • All premium features now included in core plugin
    • Updated namespace to Core_Forms
    • Updated function prefix to cf_
    • Updated shortcode to [cf_form]
    • Updated block to core-forms/form
    • New Features
    • Performance improvements and code cleanup