Title: Effortless Multisite Form Creator
Author: domclic
Published: <strong>July 4, 2026</strong>
Last modified: July 4, 2026

---

Search plugins

![](https://s.w.org/plugins/geopattern-icon/effortless-multisite-form-creator.svg)

# Effortless Multisite Form Creator

 By [domclic](https://profiles.wordpress.org/domclic/)

[Download](https://downloads.wordpress.org/plugin/effortless-multisite-form-creator.7.5.28.zip)

 * [Details](https://wordpress.org/plugins/effortless-multisite-form-creator/#description)
 * [Reviews](https://wordpress.org/plugins/effortless-multisite-form-creator/#reviews)
 *  [Installation](https://wordpress.org/plugins/effortless-multisite-form-creator/#installation)
 * [Development](https://wordpress.org/plugins/effortless-multisite-form-creator/#developers)

 [Support](https://wordpress.org/support/plugin/effortless-multisite-form-creator/)

## Description

**Effortless Multisite Form Creator** is a lightweight, powerful WordPress plugin
that lets you create unlimited contact forms using the Gutenberg block editor. Each
form can be displayed inline or as a popup modal with smooth animations.

#### Key Features

 * **Gutenberg-Ready** – Build forms directly in the block editor with HTML
 * **AJAX Submission** – No page refresh needed
 * **Popup or Inline** – Display forms as popups or embedded in your content
 * **Fieldset Support** – Full support for fieldset and legend elements with beautiful
   styling
 * **Flexible Width Options** – Container width (default), narrow, default, or wide
   layouts
 * **Dual Email System** – Send to admin and user copy automatically
 * **SMTP Support** – Optional SMTP configuration for reliable email delivery
 * **Per-Form Customization** – Each form can have unique messages and settings
 * **Theme Button Support** – Uses your theme’s button styles by default (optional
   custom styling)
 * **Fully Translatable** – All messages configurable per form (no hardcoded text)
 * **Multisite Compatible** – Works seamlessly on WordPress multisite networks
 * **Responsive Design** – Mobile-friendly popups and forms with optimized spacing
 * **Simple Math Captcha** – Optional spam protection with automatic renewal
 * **Enhanced Radio & Checkbox** – Card-style radio buttons and highlighted terms
   checkbox
 * **Save Submissions** – Optional storage as custom post type with custom slug
 * **Configurable Retention** – Optionally auto-delete stored submissions after 
   a set number of days
 * **Privacy Tools Integration** – Submissions are included in WordPress’s built-
   in personal data export/erase tools
 * **Page Builder Compatible** – Works with Elementor, Beaver Builder, Divi, and
   Gutenberg blocks
 * **No Dependencies** – Uses native WordPress functions and jQuery

#### Use Cases

 * Contact forms
 * Support request forms
 * Quote request forms
 * Newsletter signup forms (with consent & storage)
 * Subscription forms with plan selection
 * Feedback forms
 * Registration forms
 * Any custom form you need!

#### Form Width Options

Choose how your inline forms should display:

 * **Container Width (Default)** – Uses 100% of the parent container width
 * **Narrow** – Maximum 450px width, centered
 * **Default** – Maximum 720px width, centered
 * **Wide** – Maximum 1080px width, centered

#### Email Configuration

 * Send to site admin email
 * Send to specific WordPress user
 * Send copy to form submitter (if email field exists)
 * Optional SMTP configuration for better deliverability
 * Customizable email subjects and messages per form

#### Styling Features

 * Card-style radio button options with hover effects
 * Highlighted terms and conditions checkbox container
 * Proper fieldset and legend styling with nested support
 * Consistent spacing throughout forms
 * Custom or theme button styling options
 * Visual width preview in admin settings

### External services

This plugin can optionally connect to a third-party service to reduce spam. It is
off by default and only activates when Akismet is installed and configured.

**Akismet**

If the Akismet plugin is installed, active, and configured with an API key on your
site, this plugin sends each form submission’s author name, email, message text,
IP address, user agent, and referrer to Akismet’s comment-check endpoint (`https://
REST.akismet.com/1.1/comment-check`) to determine whether the submission is spam.
This only happens if Akismet is already active on your site; if it is not, no data
is sent to Akismet.

This service is provided by Automattic: [Terms of Service](https://akismet.com/tos/),
[Privacy Policy](https://automattic.com/privacy/).

### Additional Information

#### Configuration Keys

You can customize these messages per form using hidden input fields:

 * `elmfc_submit_text` – Submit button text
 * `elmfc_sent_text` – Button text after successful submission
 * `elmfc_cancel_message` – Cancel/Reset button text
 * `elmfc_success_message` – Success message after submission
 * `elmfc_error_message` – Error message on failure
 * `elmfc_validation_message` – Validation error message
 * `elmfc_sending_message` – Text shown while submitting
 * `elmfc_captcha_error` – Captcha error message
 * `elmfc_captcha_message` – Captcha question label
 * `elmfc_captcha_answer` – Captcha answer placeholder
 * `elmfc_admin_subject` – Admin email subject
 * `elmfc_admin_message` – Admin email intro text
 * `elmfc_user_subject` – User copy email subject
 * `elmfc_user_message` – User copy email intro text
    **Note:** The redirect URL
   is configured in the Appearance Settings sidebar for each form (stored as post
   meta). It cannot be set via a hidden input field — any client-submitted value
   is ignored.
 * `popup_width` – Popup width in pixels (default: 500)

#### Example Form HTML

    ```
    `html
    ```

 Contact Information

 Your Name *

 Your Email *

 Message *

 How did you hear about us?

 Search Engine

 Social Media

 I agree to the [Terms and Conditions](https://wordpress.org/terms?output_format=md)*

 Send Message
 Reset

    ```
    `
    ```

#### Support

For support, feature requests, or bug reports, please visit the plugin’s support
forum on WordPress.org or contact the developer.

#### Credits

Developed by domclic with ❤️ for the WordPress community.

## Blocks

This plugin provides 1 block.

 *   ELMFC Form

## Installation

 1. Upload the plugin files to `/wp-content/plugins/effortless-multisite-form-creator/`
 2. Activate the plugin through the ‘Plugins’ menu in WordPress
 3. Go to Forms > Add New Form
 4. Build your form using HTML in the Gutenberg editor
 5. Configure settings in the sidebar meta boxes
 6. Use shortcode `[elmfc id="123"]` or `[elmfc name="your-form-slug"]`
 7. Add `popup="true"` to display as popup: `[elmfc id="123" popup="true"]`

## FAQ

### How do I create a form?

 1. Go to Forms > Add New Form
 2. Add your form HTML in the editor (use fieldset, input, textarea, select, etc.)
 3. Configure email settings, captcha, and appearance in the sidebar
 4. Publish and copy the shortcode

### How do I add fieldsets?

Use standard HTML fieldset and legend tags:
 `html <fieldset> <legend>Section Title
</legend> <label>Field Name</label> <input type="text" name="field_name" required
> </fieldset>

### How do I display the form as a popup?

Add `popup="true"` to your shortcode:
 [elmfc id=”123″ popup=”true”]

### How do I make the form full width?

By default, forms use their container’s full width. To explicitly control width:

 1. Edit your form
 2. Go to Appearance Settings sidebar
 3. Select “Container” for full width, or choose Narrow/Default/Wide for specific max-
    widths

### Can I customize the button text?

Yes! Add hidden input fields in your form:
 `html <input type="hidden" name="elmfc_submit_text"
value="Send Message"> <input type="hidden" name="elmfc_success_message" value="Thanks
for contacting us!">

### How do I enable SMTP?

 1. Edit your form
 2. In Email Settings sidebar, check “Use SMTP”
 3. Enter your SMTP host, port, encryption, username, and password
 4. Save the form

### Does it work with page builders?

Yes! The plugin includes CSS overrides for:
 * Elementor * Beaver Builder * Divi*
Gutenberg blocks * Generic row/column layouts

### How do I save form submissions?

 1. Edit your form
 2. In Storage Settings sidebar, check “Save submissions to CPT”
 3. Enter a CPT slug (e.g., “newsletter”, “contact-requests”)
 4. Submissions will appear as a submenu under Forms

### How is stored submission data handled for privacy (GDPR)?

If you enable “Save submissions to CPT” for a form, submitted data (name, email,
message, and any other field) is stored in your site’s database indefinitely by 
default. You can set “Auto-delete submissions after (days)” in Storage Settings 
to have the plugin permanently delete submissions older than that automatically (
checked once daily); leave it at 0 to keep them forever.

Stored submissions are also included in WordPress’s built-in personal data tools(
Tools  Export Personal Data / Erase Personal Data), so you can fulfil a visitor’s
data request without manually searching the database.

### Can I translate form messages?

Absolutely! All messages can be customized per form using hidden input fields. Check
the documentation for the full list of available configuration keys.

## Reviews

There are no reviews for this plugin.

## Contributors & Developers

“Effortless Multisite Form Creator” is open source software. The following people
have contributed to this plugin.

Contributors

 *   [ domclic ](https://profiles.wordpress.org/domclic/)

[Translate “Effortless Multisite Form Creator” into your language.](https://translate.wordpress.org/projects/wp-plugins/effortless-multisite-form-creator)

### Interested in development?

[Browse the code](https://plugins.trac.wordpress.org/browser/effortless-multisite-form-creator/),
check out the [SVN repository](https://plugins.svn.wordpress.org/effortless-multisite-form-creator/),
or subscribe to the [development log](https://plugins.trac.wordpress.org/log/effortless-multisite-form-creator/)
by [RSS](https://plugins.trac.wordpress.org/log/effortless-multisite-form-creator/?limit=100&mode=stop_on_copy&format=rss).

## Changelog

#### 7.5.28 – 2026-07-04

 * Dev: Added bin/smoke-test.php, a WP-CLI script (`wp eval-file bin/smoke-test.
   php`) that exercises file-upload handling, the privacy exporter/eraser, and the
   daily cleanup cron directly against a live install, cleaning up all test data
   it creates. Not part of the plugin’s runtime; excluded from PHPCS scanning in
   phpcs.xml since it’s CLI-only output, not web-facing.

#### 7.5.27 – 2026-07-04

 * Added: GDPR/Privacy Tools integration — form submissions are now included in 
   WordPress’s built-in Export Personal Data / Erase Personal Data tools (Tools  
   Export/Erase Personal Data), matched by the requester’s email address across 
   every submission CPT. Suggested privacy policy language is also registered via
   wp_add_privacy_policy_content().
 * Added: Configurable submission retention — a new “Auto-delete submissions after(
   days)” field in Storage Settings, enforced by a new daily cron job. Leave at 
   0 (default) to keep submissions forever, matching prior behavior.
 * Security: Form file attachments are now uploaded into a dedicated `wp-content/
   uploads/elmfc-attachments/` directory with a deny-all `.htaccess`/`index.php`,
   instead of the standard public year/month uploads folder, since they may contain
   sensitive user-submitted documents. Cleanup of these files (and the multisite
   blog-switch restore) is now guaranteed via try/finally even if a hook throws 
   mid-request.
 * Security: Rate-limit rows written directly to wp_options (for atomicity) are 
   now purged once expired by the new daily cron, instead of accumulating indefinitely.
 * Security: Email subject lines are now run through sanitize_text_field() before
   being handed to wp_mail(), as defense-in-depth against control-character/header
   injection regardless of how the underlying setting was populated.
 * Fix: `wp_die( 'Unauthorized' )` in the CSV export handler now uses `esc_html__()`
   like every other message in the plugin.
 * Fix: `uninstall.php` now also removes the `elmfc_recaptcha_captcha_fixed` migration-
   tracking option and the daily cleanup cron event.
 * Cleanup: The shortcode’s KSES allowlist is now memoized (built once per request)
   instead of being rebuilt on every form render.
 * Docs: Clarified the security trade-offs of the `ELMFC_TRUST_PROXY` constant in
   its doc comment.

#### 7.5.26 – 2026-07-03

 * Security: The submissions admin page now validates the `cpt` query parameter 
   against the plugin’s own list of managed submission post types before rendering
   or listing anything, closing a gap that let any user with the broad `edit_posts`
   capability browse/export posts of an arbitrary post type through this screen.
 * Security: Deleting a submission (single or bulk) now also checks `current_user_can('
   delete_post', $id )` for that specific post, not just the broad `edit_posts` 
   capability.
 * Fix: The honeypot field label now uses `esc_html__()` instead of an unescaped`
   __()` call.
 * Fix: The one-time “my_form”  “elmfc_form” CPT migration now clears the WordPress
   post cache for every renamed post, so sites using a persistent object cache (
   Redis/Memcached) don’t keep serving stale cached posts under the old post type
   after the rename.

#### 7.5.25 – 2026-07-03

 * Fix: The one-time “my_form”  “elmfc_form” CPT migration now also runs immediately
   after switch_to_blog() in cross-site rendering/submission code paths, not just
   on init. Previously, a source site reached only via switch_to_blog() (never visited
   directly since upgrading) would keep rejecting valid cross-site submissions as“
   Invalid form”.
 * Fix: Forms that had Google reCAPTCHA enabled with the math captcha explicitly
   turned off now automatically get the math captcha re-enabled on upgrade, instead
   of silently ending up with no CAPTCHA at all after reCAPTCHA was removed. Stale
   reCAPTCHA postmeta is cleaned up at the same time.
 * Fix: Submission detail view no longer shows the literal text “Array” for multi-
   value fields (e.g. checkbox groups); values are now joined into a readable comma-
   separated list.
 * Fix: Submission detail view field ordering now matches the previous case-insensitive
   sort instead of PHP’s case-sensitive default.
 * Fix: Admin asset loading now matches the submissions page by its exact registered
   hook suffix instead of a substring match on the screen ID.
 * Cleanup: Removed a dead, unreachable branch left over from the reCAPTCHA removal
   in the settings import handler, and a redundant duplicate merge pass in the shortcode’s
   KSES allowlist builder.

#### 7.5.24 – 2026-07-03

 * Code quality: Removed ~45 unnecessary phpcs:ignore/disable suppressions across
   the codebase (verified empirically that the underlying code already satisfied
   WordPress Coding Standards without them). Replaced a raw SQL query with get_post_meta()
   in the submission detail view, used $wpdb->esc_like() instead of a hand-escaped
   LIKE wildcard, and sanitized a couple of previously-unwrapped $_SERVER/$_FILES
   reads directly instead of suppressing the warning. No functional changes.

#### 7.5.23 – 2026-07-03

 * Removed: Google reCAPTCHA v3 integration entirely (settings UI, verification,
   footer script). Forms now rely solely on the built-in, self-hosted math captcha
   plus honeypot and rate limiting — no external CAPTCHA service or data leaves 
   your site.

#### 7.5.22 – 2026-07-03

 * Fix: Renamed the “my_form” custom post type to the prefixed “elmfc_form” to avoid
   naming collisions with other plugins/themes. Existing forms are migrated automatically(
   one-time rename on the first admin request per site); no action needed.
 * Cleanup: Removed AI-assistant planning/spec files from the shipped plugin (docs/
   superpowers/); added them to .gitignore.

#### 7.5.21 – 2026-07-02

 * Fix: Enqueue Google reCAPTCHA and admin/submissions meta-box JS via wp_enqueue_script()/
   wp_add_inline_script() instead of printing inline `<script>` tags.
 * Fix: Use wp_handle_upload() instead of move_uploaded_file() for form file attachments.
 * Fix: Apply a form-aware KSES allowlist to shortcode-rendered form content as 
   defense-in-depth escaping.
 * Docs: Document Google reCAPTCHA and Akismet as external services in the readme.

#### 7.5.20 – 2026-06-30

 * Update: Confirmed compatibility with WordPress 7.0.

#### 7.5.19 – 2026-06-30

 * Update: Tested up to WordPress 7.0.

#### 7.5.18 – 2026-06-30

 * FEATURE: Shortcode pre-fill — pass any field’s name= attribute directly in the
   shortcode to pre-populate text inputs, textarea, radio buttons, checkboxes, and
   selects. Example: [elmfc id=”123″ plan=”premium” firstname=”John”]. Comma-separated
   values pre-check multiple checkboxes in a group (name=”field[]”). Reserved attributes(
   id, name, popup) are not treated as field names.

#### 7.5.17 – 2026-06-30

 * FIXED: User copy email never sent when the form’s email input had any name other
   than “email” — the handler hardcoded $data[’email’] with no way to configure 
   it. Added “Email field name” setting (defaults to “email”) in Email Settings 
   so any field name works. Also fixes Reply-To on admin emails for the same reason.

#### 7.5.16 – 2026-06-30

 * UX: Fixed popup close animation — overlay now fades out correctly instead of 
   snapping off instantly; replaced display:none toggle with pointer-events/visibility
   so CSS transitions run on both open and close.
 * UX: Scroll to first invalid field on validation failure — page now smoothly scrolls
   to and focuses the first field that failed validation, not just the error banner.
 * UX: Submit button loading spinner — button shows a CSS spinner while the AJAX
   request is in flight; text goes transparent so button size stays stable.
 * UX: SMTP password field show/hide toggle — added a reveal button (dashicons-visibility)
   next to the password input in the email settings meta box.
 * UX: Stats column now shows impressions  submits (conversion %) instead of two
   separate raw-number columns; tooltip gives full label text.

#### 7.5.15 – 2026-06-30

 * REFACTOR: elmfc_get_config_keys() and elmfc_get_skip_fields() now use static 
   caching — arrays are built once per request instead of on every call.
 * FIXED: Removed duplicate elmfc_captcha_answer and elmfc_redirect_url entries 
   from elmfc_get_skip_fields() — both keys are already included via elmfc_get_config_keys().
 * REFACTOR: Removed trivial get_skip_fields() proxy method from ELMFC_Email_Handler—
   extract_form_fields() calls elmfc_get_skip_fields() directly.
 * REFACTOR: Removed dead $plain parameter from ELMFC_Email_Handler::format_html_email()—
   the plain-text body was passed in but never used inside the method.
 * REFACTOR: Extracted duplicated main-site ID resolution in the shortcode into 
   a single pre-computed variable — the ms_gpt_source_site / get_main_site_id() 
   lookup was previously copy-pasted in both the id= and name= fallback paths.
 * DOCS: Added return type hint :array to elmfc_default_texts() and elmfc_get_config_keys();
   improved docblock for elmfc_get_config_keys().

#### 7.5.14 – 2026-06-29

 * SECURITY: Rate limiter no longer bypassed on sites running a persistent object
   cache (Redis/Memcached) — counter rows are now written directly to the options
   table via $wpdb->replace() instead of set_transient(), so the atomic SQL UPDATE
   always finds the rows it needs.
 * SECURITY: Math captcha tokens now include the form_id in the transient key (‘
   elmfc_cap_{form_id}_{token}’) — a token solved on one form can no longer be replayed
   against a different form in the network.
 * SECURITY: AJAX nonce is now scoped to the specific form_id (‘elmfc_form_submit_{
   id}’) — a nonce obtained from form A can no longer be used to target form B on
   any site in the network.
 * SECURITY: Email subject and intro text are now read from post meta, not from 
   $_POST — an attacker can no longer spoof the admin notification email’s subject
   line or opening sentence.
 * FIXED: form_title and form_url are now saved to CPT submissions as ‘elmfc_form’
   and ‘elmfc_url’ meta keys — the rename block was previously dead code because
   it ran after array_diff_key() had already stripped those keys.
 * FIXED: Akismet API key now read with get_site_option() before switch_to_blog()—
   cross-site form submissions on multisite no longer bypass the spam check when
   Akismet is network-activated (key stored in sitemeta, not per-site options).
 * FIXED: elmfc_rl_limit and elmfc_rl_window added to the canonical elmfc_get_skip_fields()—
   these internal rate-limit config keys are no longer forwarded to external webhook
   payloads; local duplicates removed from email handler and CPT storage.

#### 7.5.13 – 2026-06-29

 * REFACTOR: reCAPTCHA v3 verification extracted to shared elmfc_verify_recaptcha()
   helper — AJAX and REST handlers no longer duplicate the secret-fetch, HTTP call,
   and score-check logic.
 * REFACTOR: Rate-limit config reading extracted to shared elmfc_get_rate_limit_config()
   helper — eliminates duplicated get_post_meta() calls in both submission handlers.
 * REFACTOR: DISTINCT postmeta scan for submission meta keys extracted to shared
   elmfc_get_submission_meta_keys() helper — list table and CSV export now share
   the same cached query; fetch_meta_keys() delegates to it.
 * FIXED: Webhook payload builder now uses elmfc_get_skip_fields() instead of a 
   partial hand-rolled list, ensuring elmfc_cc, elmfc_bcc, and any future skip-list
   additions are excluded from outgoing webhook payloads.
 * IMPROVED: elmfc_default_texts() now memoizes its return value with a static variable,
   avoiding array reconstruction on every call.
 * IMPROVED: elmfc_is_valid_blog() now returns true for blog ID 1 on single-site
   installations instead of always returning false.
 * DOCS: readme.txt Additional Information section corrected — elmfc_redirect_url
   is configured in the Appearance Settings sidebar (post meta), not via a hidden
   form field.
 * DOCS: REST endpoint now has a clear note that file uploads are not supported;
   the AJAX handler should be used for forms with file fields.
 * DOCS: docs/ directory added to .gitignore and excluded from distributable zip.

#### 7.5.12 – 2026-06-29

 * SECURITY: reCAPTCHA v3 — omitting the token or leaving the secret unconfigured
   now rejects the submission instead of silently skipping verification (previously
   bypassed both reCAPTCHA and math captcha simultaneously).
 * SECURITY: Rate-limit guard now distinguishes a DB error (false) from zero rows
   affected (0) — a transient DB failure no longer resets the window and bypasses
   the limit.
 * FIXED: Cross-site multisite — redirect URL after submit now read from source 
   blog postmeta before restore_current_blog(); previously always returned empty
   on cross-site forms (AJAX and REST).
 * FIXED: Email handler get_skip_fields() now delegates to the global elmfc_get_skip_fields()
   so future additions to the skip list are automatically inherited.
 * FIXED: send_emails() now returns true when no email routes are configured, preventing
   a false “Error sending email” response after a successful CPT save.
 * FIXED: Impression and submit stat counters — on the very first submission a concurrent-
   insert race could leave the counter at 1 instead of N; retry logic ensures no
   increment is lost.
 * IMPROVED: fetch_meta_keys() in the submissions list table is now cached in a 
   60-second transient (invalidated on new submission), eliminating a full postmeta
   DISTINCT scan on every page load.
 * IMPROVED: “Send to specific user” dropdown raised from 200 to 500 users; sites
   with more than 500 users now see an inline notice with the total count.

#### 7.5.11 – 2026-04-28

 * SECURITY: elmfc_redirect_url is no longer emitted as a hidden form field — it
   is now read directly from post meta by the AJAX and REST handlers, eliminating
   any possibility of client-side tampering with the post-submission redirect destination.

#### 7.5.10 – 2026-04-27

 * SECURITY: REST endpoint now enforces the same captcha stack as the AJAX handler—
   math captcha (token/transient) and reCAPTCHA v3 are both checked before processing
   REST submissions.
 * SECURITY: reCAPTCHA v3 secret key and webhook signing secret are now encrypted
   at rest using AES-256-CBC (same scheme as SMTP password). Existing plain-text
   values are decrypted transparently via the enc: prefix detection.
 * SECURITY: Duplicate-form action now uses object-level capability check (edit_post
   + post ID) instead of the broad edit_posts capability.
 * SECURITY: Single-submission delete action now validates the post type with elmfc_is_plugin_cpt()
   before calling wp_delete_post().
 * FIXED: JSON form import no longer allows overwriting the CPT slug (_elmfc_cpt_slug)—
   changing the slug via import could silently rename the submission table.
 * FIXED: wp_die() strings in admin actions are now translatable.

#### 7.5.9 – 2026-04-27

 * FIXED: Form field labels, placeholder text, and other text inside core/html blocks
   is now translated. Registers the ms_gpt_translate_html_block filter (added in
   auto-translate 3.2.31) for my_form posts so GPT receives and translates the raw
   HTML content.

#### 7.5.8 – 2026-04-27

 * FIXED: Forms now translate correctly — removed the filter that was telling the
   auto-translate plugin to skip all block content for my_form posts.
 * FIXED: The elmfc/form Gutenberg block now registers ms_gpt_remap_block_attrs 
   so its formId attribute is remapped to the destination site’s translated form
   when a page is translated.
 * FIXED: my_form slugs are now preserved on translated sites (ms_gpt_preserve_post_slug)
   so [elmfc name=”…”] shortcodes continue to work.
 * FIXED: [elmfc id=…] shortcode now falls back to the source site when the translated
   form doesn’t exist yet on the destination site.

#### 7.5.7 – 2026-04-26

 * FIXED: Resolved final two PHPCS warnings — reworded inline comment in email handler
   that was flagged as commented-out code; corrected operator alignment in shortcode
   file.

#### 7.5.6 – 2026-04-27

 * SECURITY: REST endpoint redirect URL now validated with wp_validate_redirect()(
   parity with AJAX handler).
 * SECURITY: [elmfc_submissions] shortcode now validates the cpt attribute against
   plugin-owned slugs via elmfc_is_plugin_cpt() — prevents listing arbitrary CPT
   content.
 * FIXED: CPT slug save in meta boxes now rejects slugs that belong to built-in 
   or third-party post types (post, page, my_form, etc.) to prevent form submissions
   being inserted as regular WordPress posts.

#### 7.5.5 – 2026-04-26

 * SECURITY: Rate limit counter is now atomic (SQL UPDATE + expiry JOIN) — eliminates
   TOCTOU race that allowed bypass under concurrent requests.
 * SECURITY: REST endpoint now uses elmfc_get_client_ip() (proxy-aware) instead 
   of bare $_SERVER[‘REMOTE_ADDR’] for rate limiting.
 * SECURITY: Copy-to-site handler validates target blog ID with elmfc_is_valid_blog()
   before switch_to_blog().
 * SECURITY: Resend-email AJAX handler verifies the submission belongs to a plugin-
   owned CPT via new elmfc_is_plugin_cpt() helper.
 * SECURITY: Bulk delete and CSV export now validate the ?cpt= slug is a plugin-
   owned CPT before acting.
 * SECURITY: Bulk delete verifies each post ID belongs to the expected CPT before
   deleting.
 * SECURITY: Redirect URL after submission is validated with wp_validate_redirect()
   to enforce same-origin policy.
 * SECURITY: File upload rename() return value is now checked — failed rename discards
   the temp file instead of attaching a phantom path.
 * SECURITY: CPT submission meta keys are sanitized with sanitize_key() and private-
   meta prefix (_) is rejected in elmfc_save_to_cpt().
 * SECURITY: Settings import rejects files larger than 512 KB before calling file_get_contents().

#### 7.5.4 – 2026-04-26

 * SECURITY: Fixed DOM-based XSS in showMessage() — replaced .html() with safe DOM
   construction; captcha question update now uses .text() via new .elmfc-captcha-
   question span.
 * SECURITY: REST endpoint (/wp-json/elmfc/v1/submit) now enforces the same per-
   form, per-IP rate limiting as the AJAX handler.
 * SECURITY: SMTP password no longer passed through sanitize_text_field() which 
   was silently corrupting passwords containing <, >, or &.
 * SECURITY: Server-side blocklist of executable extensions (php, phar, asp, sh,
   etc.) applied to file uploads regardless of admin-configured allowlist.
 * SECURITY: elmfc_source_site POST/REST parameter is now validated against real
   network blog IDs before switch_to_blog() is called.
 * SECURITY: reCAPTCHA v3 verification is now fail-closed — network errors reject
   the submission instead of silently passing it.
 * FIXED: elmfc_submissions_shortcode now escapes get_the_title() output and requires
   edit_posts capability.
 * FIXED: Cross-site block in main shortcode wrapped in try/finally so restore_current_blog()
   always runs on exception.
 * FIXED: Resend email AJAX handler now checks current_user_can(‘edit_post’, $form_id)
   to prevent cross-form access.
 * FIXED: Copy-to-site handler now verifies nonce before capability check (correct
   security gate order).
 * FIXED: Duplicate admin notices now only display on my_form screens.
 * FIXED: Settings import now applies type-appropriate sanitizers (URL, int, float,
   email) instead of blanket sanitize_text_field for all values.
 * FIXED: CPT registration (elmfc_register_all_dynamic_cpts) now caches results 
   in a transient, eliminating the per-request DB query.
 * FIXED: Submissions badge no longer runs N+1 DB queries on every admin page load—
   uses elmfc_sub_counts transient.
 * FIXED: get_users() in email settings now limited to 200 results to prevent memory
   issues on large networks.
 * IMPROVED: Centralized skip-field list via elmfc_get_skip_fields() used across
   CPT storage.
 * IMPROVED: Uninstall transient cleanup now uses $wpdb->prepare() consistently.

#### 7.5.2 – 2026-03-04

 * FIXED: Remaining PHP Deprecated warnings — `str_replace(null)` caused by `get_edit_post_link()`
   returning null for non-public CPT in duplicate handler; replaced with `admin_url('
   post.php?...')`.
 * FIXED: `preg_replace()` null return (on PCRE error) propagating as null `$form_content`
   in shortcode; cast result to string.
 * FIXED: Forms not rendering for visitors — deprecation warnings output before 
   form HTML disrupted page structure; null guards now applied before `$post` is
   accessed in asset enqueue.

#### 7.5.1 – 2026-03-04

 * FIXED: PHP Deprecated warnings — `strpos(null)` and `str_replace(null)` — caused
   by `$post->post_content` being null on some post types; cast to string before
   passing to `has_shortcode()` and `apply_filters('the_content', ...)`

#### 7.5.0 – 2026-03-04

 * ADDED: Conditional logic — wrap any field(s) in a container with `data-show-if-
   field`, `data-show-if-value`, and optional `data-show-if-operator` (equals/not_equals/
   contains/not_empty/empty) to show/hide fields dynamically; hidden fields excluded
   from validation (M1)
 * ADDED: Multi-step wizard — add `<div class="elmfc-step">` sections to any form;
   Previous/Next navigation and an animated progress bar are injected automatically;
   each step validates before advancing (M2)
 * ADDED: Google reCAPTCHA v3 per-form — enable in Security Settings with Site Key,
   Secret Key, and score threshold; replaces the math captcha when active; script
   loaded automatically in footer (M3)
 * ADDED: Custom From name and email address per form in Email Settings — leave 
   empty to use the WordPress default sender (M4)
 * ADDED: Per-field inline error messages — add `data-error="Your message"` to any
   required field; the custom message appears below the field on validation failure(
   M5)
 * ADDED: Akismet integration — when Akismet is active and an API key is configured,
   spam submissions are silently swallowed before emails are sent (M6)
 * ADDED: Copy form to site (multisite only) — “Copy to site” row action; admins
   with manage_sites capability can duplicate a form to any other site in the network(
   M7)
 * ADDED: Resend email button in the submission detail view — reconstructs the email
   from stored meta and sends again; updates email status and time (M8)
 * ADDED: Webhook/Zapier integration — configure a webhook URL per form; payload
   is POSTed as JSON on each submission; optional HMAC-SHA256 X-ELMFC-Signature 
   header for payload verification (M9)
 * ADDED: Form analytics — Impressions and Submits counters on the Forms list; impression
   incremented each time the shortcode renders; submit incremented on each successful
   send; atomic DB updates (M10)

#### 7.4.9 – 2026-03-04

 * ADDED: File upload support — add `<input type="file">` to any form; uploaded 
   files attach to the admin email; configurable max size (MB) and allowed extensions
   per form (Q1)
 * ADDED: Native Gutenberg block `elmfc/form` — form picker dropdown + popup toggle
   in the block inspector; server-side rendered; no shortcode typing needed (Q2)
 * FIXED: Required checkbox validation — unchecked required checkboxes (e.g. terms
   acceptance) now highlight in red, matching existing radio and text field behaviour(
   Q3)
 * IMPROVED: Popup forms auto-focus the first visible input field when the popup
   opens (Q4)
 * FIXED: Cancel button fully restores form state — re-enables all fields, restores
   submit button label, and shows the button row even after a successful submission(
   Q5)
 * ADDED: Submission counter in the Shortcode meta box — shows total count for this
   form with a direct link to the Submissions page when CPT storage is enabled (
   Q6)

#### 7.4.8 – 2026-03-03

 * SECURITY: SMTP password now encrypted at rest using AES-256-CBC (AUTH_KEY-derived
   key); legacy plain-text passwords continue to work transparently (S2)
 * SECURITY: SMTP password field never echoed back to the browser — shows “(saved)”
   placeholder when a password is stored; leave blank to keep existing password
 * FIXED: `_elmfc_email_sent` explicitly unset from CPT meta before wp_insert_post(
   defensive — already excluded by skip list) (N27)
 * FIXED: CSV export now includes Email Status and Email Time columns from the delivery
   log (N28)
 * FIXED: Test emails bypass `elmfc_field_value` filter so raw field data is always
   shown in test output (N29)
 * ADDED: “Save the form before testing” note below the test email button (N30)
 * ADDED: Submission detail view — click any submission title to see all fields 
   in a full-page table with delete action (A1)
 * ADDED: HTML email template with site branding header, field table, and plain-
   text AltBody fallback (E1)
 * ADDED: REST API endpoint `POST /wp-json/elmfc/v1/submit` — mirrors AJAX handler,
   supports all form fields, honeypot, before_send filter, and CPT storage (D1)
 * ADDED: Export / Import Settings meta box — export all form settings to JSON (
   password excluded), import from a JSON file with key whitelisting (D4)

#### 7.4.7 – 2026-03-03

 * SECURITY: Proxy IP headers (X-Forwarded-For, CF-Connecting-IP, X-Real-IP) are
   now opt-in via define(‘ELMFC_TRUST_PROXY’, true) in wp-config.php — prevents 
   rate-limit bypass by IP header spoofing on non-proxied servers
 * FIXED: elmfc_rl_limit and elmfc_rl_window added to email body and CPT storage
   skip lists
 * FIXED: .elmfc-input-small scoped to .elmfc-settings-section — no longer risks
   affecting other plugins
 * ADDED: “Send test email” button in Email Settings — sends a sample submission
   to the currently logged-in admin’s email, respecting SMTP settings
 * ADDED: Email delivery log — each CPT submission now stores _elmfc_email_status(
   sent/failed) and _elmfc_email_time; status shown as ✓/✗ in the Submissions table
   Email column

#### 7.4.6 – 2026-03-03

 * FIXED: Rate limiter now runs after captcha validation — wrong captcha answers
   no longer consume a submission attempt
 * FIXED: Rate limiter resolves real client IP through Cloudflare, X-Forwarded-For,
   and X-Real-IP headers before falling back to REMOTE_ADDR
 * FIXED: Rate limit key is now per-form (elmfc_rl_{form_id}_hash) — different forms
   no longer share the same counter
 * FIXED: Cache invalidation hook skips autosave and all built-in WordPress post
   types; only clears on actual submission CPT writes
 * FIXED: Submission count cache is only rebuilt when the transient is missing or
   expired — no redundant DB queries on each page load
 * FIXED: Copy button double-click race condition — existing reset timer is cancelled
   before starting a new countdown
 * FIXED: Copy button original label restored correctly after timeout even if clicked
   multiple times
 * ADDED: Per-form rate limit configuration in Security Settings — set max submissions
   and time window (defaults: 5 per 10 min)
 * IMPROVED: uninstall.php now removes all elmfc_* transients with a single wildcard
   query

#### 7.4.5 – 2026-03-03

 * FIXED: Shortcode meta box copy buttons now work correctly (data-copy attribute
   was misnamed data-clipboard-text)
 * FIXED: Copy buttons in shortcode meta box now show “Copied!” feedback text and
   icon, consistent with list buttons
 * FIXED: Submission count batch preload moved from pre_get_posts to current_screen—
   get_current_screen() is now reliably available
 * FIXED: Last submission date is now included in the batch preload — no per-row
   query for dates
 * FIXED: elmfc_sub_counts transient invalidated immediately on save_post/delete_post
   for any submission CPT
 * FIXED: elmfc_duplicated URL parameter removed from browser address bar via history.
   replaceState after redirect
 * FIXED: elmfc_after_email action already received filtered $data (confirmed correct—
   no code change needed)
 * ADDED: Rate limiting — maximum 5 submissions per IP per 10 minutes; returns a
   clear error message when exceeded
 * IMPROVED: uninstall.php also cleans up rate-limit transients (elmfc_rl_*) and
   the sub_counts transient

#### 7.4.4 – 2026-03-03

 * FIXED: `elmfc_redirect_url`, `elmfc_cc`, `elmfc_bcc` excluded from email body
   and CPT submission meta
 * FIXED: Duplicating a form no longer copies CPT storage — flag reset to off, slug
   cleared to prevent two forms writing to same storage
 * FIXED: `elmfc_before_send` returning false now sends a silent success response
   instead of a confusing email error
 * FIXED: `elmfc_before_send` filter is now applied in the AJAX handler (not inside
   the email class) so cancellation has full context
 * FIXED: Shortcode meta box shows “Save the form first” prompt instead of empty
   slug shortcodes on unsaved forms
 * IMPROVED: Submission count/last-date columns now use a preloaded batch cache —
   one query set per page load instead of N
 * ADDED: Admin notice confirms duplicate success (with CPT storage reminder) or
   reports failure
 * ADDED: Character counter for textarea fields with a `maxlength` attribute (turns
   red at 90% of limit)

#### 7.4.3 – 2026-03-03

 * ADDED: Redirect URL after submit — set in Appearance Settings or via hidden field`
   elmfc_redirect_url`
 * ADDED: Duplicate form — row action on the Forms list clones the form and all 
   its settings as a draft
 * ADDED: Submission count + last submission date columns on the Forms list (linked
   to Submissions page)
 * FIXED: Reply-To header now set consistently — admin emails reply to submitter,
   user copy emails reply to site admin
 * ADDED: CC and BCC fields in Email Settings sidebar (per-form)
 * ADDED: `elmfc_before_send` filter — return `false` to cancel submission programmatically
 * ADDED: `elmfc_field_value` filter — transform or suppress individual field values
   before email/storage
 * IMPROVED: Array field values (multi-select, checkbox groups) — empty strings 
   filtered out before storage

#### 7.4.2 – 2026-03-03

 * IMPROVED: Frontend CSS/JS now loads only on pages that contain an [elmfc] or [
   elmfc_submissions] shortcode (no longer global)
 * ADDED: Late-enqueue fallback in shortcode for page builders (Elementor, Divi,
   etc.) that bypass wp_enqueue_scripts
 * ADDED: Shortcode meta box in the form editor sidebar — shows all four shortcode
   variants with one-click copy buttons
 * ADDED: Submission count badge on the “All Submissions” admin menu item
 * ADDED: Honeypot anti-spam field — silent discard when a bot fills the hidden 
   field
 * ADDED: uninstall.php — full cleanup of forms, submission CPTs, and captcha transients
   on plugin deletion (multisite-aware)

#### 7.4.1 – 2026-03-03

 * FIXED: Fatal error “Class WP_List_Table not found” — require_once for class-wp-
   list-table.php moved to file top, before class declaration

#### 7.4.0 – 2026-03-03

 * ADDED: Dedicated “All Submissions” admin page under Forms menu (WP_List_Table)
 * ADDED: Submissions overview listing all forms with CPT storage — shows submission
   count per form
 * ADDED: Dynamic columns — all submitted field names auto-detected from saved meta
   and shown as columns
 * ADDED: Sortable Date and Identifier columns, search, pagination (25 per page)
 * ADDED: Single-row delete with confirmation, bulk delete
 * ADDED: Export selected to CSV, Export all to CSV (UTF-8 BOM for Excel, CSV injection
   protection)
 * ADDED: Form name (elmfc_form) and source URL (elmfc_url) now saved as submission
   meta for full context
 * CHANGED: Submission CPTs no longer appear as individual submenus — replaced by
   the unified Submissions page
 * CHANGED: Dynamic CPTs now registered as non-public/hidden (storage only) — data
   unaffected

#### 7.3.8 – 2026-03-03

 * REFACTOR: Consolidated admin asset loading into a single admin_enqueue_scripts
   hook using get_current_screen() — replaces fragile hook+global checks
 * REFACTOR: Extracted copy-button JS into assets/js/elmfc-admin.js (was inline 
   in PHP)
 * REFACTOR: Extracted copy-button CSS into elmfc-admin.css (was inline in PHP)
 * ADDED: Frontend elmfc.css now loaded on the post editor screen so form HTML is
   styled correctly in the Gutenberg editor
 * FIXED: CSS version comments updated to match plugin version

#### 7.3.7 – 2026-03-03

 * ADDED: Clipboard copy buttons on the Forms list — ID column copies [elmfc id=”
   X”] shortcode, Slug column copies [elmfc name=”slug”] shortcode
 * ADDED: Visual confirmation feedback (“Copied!”) after clicking copy button

#### 7.3.6 – 2026-03-03

 * ADDED: Multisite cross-site form resolution — [elmfc name=”slug”] automatically
   falls back to the main site when the form is not found on the current site
 * ADDED: Source site ID passed in form POST (elmfc_source_site) so the AJAX handler
   queries the correct site’s DB tables and meta
 * CHANGED: Captcha transients now use set_site_transient/get_site_transient (network-
   wide) to remain accessible regardless of blog context during AJAX
 * FIXED: elmfc_source_site excluded from emails and CPT meta storage

#### 7.3.5 – 2026-03-03

 * SECURITY: Captcha solution no longer sent to client — replaced hidden solution
   field with server-side transient token (one-time use, 1h TTL)
 * FIXED: Required radio button groups now correctly flagged as invalid when nothing
   is selected
 * FIXED: flush_rewrite_rules() now only runs when the CPT slug actually changes,
   not on every form save
 * FIXED: SMTP phpmailer_init hook now removed after wp_mail() to prevent accumulation
   across multiple emails
 * FIXED: elmfc_form_width_type excluded from hidden form fields (layout-only setting,
   not needed in POST)
 * REMOVED: Stale duplicate files in includes/ root and root-level JS/CSS

#### 7.3.3 – 2025-11-18

 * ADDED: Full container width support by default
 * ADDED: Four width options: Container (full), Narrow (450px), Default (720px),
   Wide (1080px)
 * ADDED: Complete fieldset and legend styling support
 * ADDED: Card-style radio button options with hover effects
 * ADDED: Highlighted terms and conditions checkbox container
 * IMPROVED: Form spacing and layout consistency
 * IMPROVED: Admin UI with visual width preview
 * IMPROVED: Page builder compatibility (Elementor, Beaver Builder, Divi)
 * IMPROVED: Mobile responsive design
 * FIXED: Forms now properly fill container width
 * FIXED: Reduced excessive spacing between form elements

#### 7.3.2 – 2025-11-18

 * ADDED: Width settings for inline forms
 * IMPROVED: Better form spacing

#### 7.3.1 – 2025-11-17

 * FIXED: CPT submissions now appear as submenu under Forms with form title
 * IMPROVED: Better CPT menu organization

#### 7.3.0 – 2025-11-17

 * ADDED: Custom Post Type storage for form submissions
 * ADDED: Configurable CPT slug per form
 * ADDED: Submissions shortcode `[elmfc_submissions cpt="your-slug" limit="10"]`

#### 7.2.6 – 2025-11-17

 * FIXED: …

## Meta

 *  Version **7.5.28**
 *  Last updated **12 hours ago**
 *  Active installations **Fewer than 10**
 *  WordPress version ** 5.0 or higher **
 *  Tested up to **7.0**
 *  PHP version ** 7.4 or higher **
 * Tags
 * [ajax](https://wordpress.org/plugins/tags/ajax/)[contact form](https://wordpress.org/plugins/tags/contact-form/)
   [form](https://wordpress.org/plugins/tags/form/)[gutenberg](https://wordpress.org/plugins/tags/gutenberg/)
   [multisite](https://wordpress.org/plugins/tags/multisite/)
 *  [Advanced View](https://wordpress.org/plugins/effortless-multisite-form-creator/advanced/)

## Ratings

No reviews have been submitted yet.

[Your review](https://wordpress.org/support/plugin/effortless-multisite-form-creator/reviews/#new-post)

[See all reviews](https://wordpress.org/support/plugin/effortless-multisite-form-creator/reviews/)

## Contributors

 *   [ domclic ](https://profiles.wordpress.org/domclic/)

## Support

Got something to say? Need help?

 [View support forum](https://wordpress.org/support/plugin/effortless-multisite-form-creator/)