Title: Double Opt-In for Contact Form 7 – Secure, GDPR-Compliant Email Verification
Author: Forge12 Interactive GmbH
Published: <strong>2022 年 12 月 16 日</strong>
Last modified: 2026 年 10 月 15 日

---

搜索插件

![](https://ps.w.org/double-opt-in/assets/banner-772x250.png?rev=3723055)

![](https://ps.w.org/double-opt-in/assets/icon-256x256.png?rev=3134993)

# Double Opt-In for Contact Form 7 – Secure, GDPR-Compliant Email Verification

 作者：[Forge12 Interactive GmbH](https://profiles.wordpress.org/forge12/)

[下载](https://downloads.wordpress.org/plugin/double-opt-in.5.14.0.zip)

 * [详情](https://cn.wordpress.org/plugins/double-opt-in/#description)
 * [评价](https://cn.wordpress.org/plugins/double-opt-in/#reviews)
 *  [安装](https://cn.wordpress.org/plugins/double-opt-in/#installation)
 * [开发进展](https://cn.wordpress.org/plugins/double-opt-in/#developers)

 [支持](https://wordpress.org/support/plugin/double-opt-in/)

## 描述

**Double Opt-In** adds a mandatory email verification step to your Contact Form 
7 forms.
 When a visitor submits your form, the original mail is **not** sent immediately.
Instead, the plugin:

 1. Stores the submission in a secure database table.
 2. Sends a confirmation email with a unique, time-limited link.
 3. Only after the visitor clicks that link is the original form mail delivered.

This ensures:

 * Only **valid, verified email addresses** reach your inbox.
 * **GDPR / DSGVO requirements** are met with proper consent tracking, IP logging,
   and data retention.
 * Your database stays **clean and reliable** — no fake or mistyped addresses.
 * The form mail **arrives after the confirmation** — every action that runs after
   the click is recorded, and temporary failures are retried automatically.

Out-of-the-box support for **Contact Form 7**. Additional form systems — Avada, 
Elementor, Gravity Forms, WPForms — are available as separate addon plugins.

#### How It Works

 1. A visitor fills out your Contact Form 7 form and clicks submit.
 2. The plugin intercepts the submission, stores the form data, and generates a unique
    hash.
 3. A confirmation email is sent to the visitor’s email address containing a verification
    link.
 4. The visitor clicks the link. The plugin verifies the hash, marks the opt-in as 
    confirmed, and sends the original form mail (as if the form was just submitted).
 5. The confirmed opt-in is logged in the admin dashboard with timestamps and IP addresses
    for full GDPR compliance.

#### Quick Start

After activation, a setup wizard asks for the sender, the forms that should ask 
for confirmation, the confirmation email and the page visitors see after the click.
Everything is prefilled; it takes about three minutes and can be skipped.

[Read the Quick Guide](https://www.forge12.com/blog/so-verwendest-du-das-double-opt-in-fuer-contact-form-7/)

#### Free Features

 * **Double Opt-In for Contact Form 7** — per-form activation with full CF7 integration
 * **Centralized Form Settings** — manage all form integrations from a single admin
   panel
 * **Built-In Email Designs** — write the confirmation email per form and pick one
   of three ready-made HTML layouts, or send it plain
 * **Resend Confirmation** — resend the confirmation email to a single recipient
   from the opt-in detail view
 * **Custom Confirmation Pages** — redirect users to a specific page after confirmation
 * **Dynamic Conditions** — enable opt-in based on user input (e.g. only when a 
   checkbox is checked)
 * **Delete Confirmation Modal** — safety dialog before deleting an opt-in record
   to prevent accidental deletion
 * **GDPR Consent Export** — export individual consent records as JSON or CSV directly
   from the opt-in detail view
 * **CAPTCHA Compatibility** — automatically bypasses Forge12 Captcha, Google reCAPTCHA,
   and hCaptcha during opt-in confirmation to ensure mail delivery
 * **Rate Limiting** — configurable IP and email rate limits to prevent abuse
 * **Error Redirect Page** — redirect users to a custom page when an opt-in error
   occurs (rate limit, invalid email)
 * **Token Expiry** — confirmation links expire after a configurable time period
 * **GDPR Data Storage** — tracks Form ID, Email, Registration/Confirmation Date&
   IP, Consent Text
 * **GDPR Anonymization** — anonymize personal data instead of deleting it
 * **WordPress Privacy Tools** — integrates with WordPress personal data export 
   and erasure requests
 * **Automatic Cleanup** — configurable auto-deletion of confirmed and unconfirmed
   entries
 * **Category System** — organize opt-ins into categories for better management
 * **Pagination & Search** — search and filter opt-in records in the admin dashboard
 * **Admin Tooltips** — contextual help tooltips throughout the admin interface
 * **WordPress Multisite** — network-wide activation creates tables on all sites
   automatically
 * **Developer Hooks** — 48 action hooks, 86 filters, and 13 typed events for full
   extensibility

#### Pro Features

Unlock the full potential of Double Opt-In with the [Pro version](https://www.forge12.com/shop/contact-form-7-double-opt-in?from=readme&utm_source=double-opt-in&utm_medium=plugin&utm_campaign=readme):

**Additional Form Integrations:**

 * **Double Opt-In for Elementor Forms** — seamless integration with Elementor’s
   form widget
 * **Double Opt-In for WPForms** — full support for WPForms submissions
 * **Double Opt-In for Gravity Forms** — complete Gravity Forms integration

**Email Validation & Spam Protection:**

 * **Unique Email Validation** — prevent duplicate submissions per email address(
   block, silent, or redirect mode)
 * **MX Validation** — verify that the email domain has a valid mail server before
   sending
 * **Domain Blocklist** — block disposable and temporary email domains

**Email & Communication:**

 * **Double Opt-Out System** — unique opt-out links per submission with confirmation
   emails
 * **Opt-In Reminder System** — automatic reminders for unconfirmed opt-ins via 
   cron
 * **Visual Email Editor** — drag & drop block editor with live preview and mobile
   preview, template presets, unlimited saved templates and test emails
 * **Conditional Email Templates** — dynamic content blocks based on form data
 * **Multi-Column Layouts** — 2-column, 3-column, and sidebar layouts in the email
   editor
 * **Image & Social Blocks** — add images and social media icons to your emails

**Analytics & Export:**

 * **Analytics Dashboard** — charts and statistics for opt-in/opt-out rates
 * **CSV Export** — export all opt-in records for external processing

**User Management:**

 * **Auto User Creation** — automatically create WordPress users after opt-in confirmation
   with configurable role assignment

**Support:**

 * **Premium Support** — priority email support

### Privacy & Telemetry

**As of version 5.1.7 the plugin no longer transmits any telemetry.** The daily

job that used to send a usage snapshot has been removed, and an update also removes
it from the WP-Cron schedule of sites that already had it.

Usage counters (how many opt-ins were confirmed, for example) are still kept,
 but
they never leave the site. They are stored in a single WordPress option and are 
used only in the admin — for instance to decide whether the plugin has been useful
long enough to ask you for a review.

**We never sell or share data.**

#### GDPR / DSGVO Compliance

 * No personal data, no cookies, no user tracking.
 * Nothing is sent to any external server. Counters stay in your database and are
   
   removed when you uninstall the plugin.
 * The telemetry setting under **Double Opt-In > Settings** is retained: should
   
   transmission ever be reintroduced, it will be honoured before anything is sent.

#### Bundled assets

The admin interface uses the Inter typeface. It is **self-hosted** — the font
 file
is embedded in the plugin’s own admin bundle, so opening the plugin’s screens does
not contact Google Fonts or any other third party. Inter is licensed under the SIL
Open Font License 1.1 (see licenses/inter-OFL-1.1.txt).

## 屏幕截图

[⌊Dashboard -- Total, confirmed and pending opt-ins at a glance, with the latest
submissions.⌉⌊Dashboard -- Total, confirmed and pending opt-ins at a glance, with
the latest submissions.⌉[

**Dashboard** — Total, confirmed and pending opt-ins at a glance, with the latest
submissions.

[⌊Opt-In list -- Every record with form, status and date; search and filter by status,
follow-up actions and mail delivery.⌉⌊Opt-In list -- Every record with form, status
and date; search and filter by status, follow-up actions and mail delivery.⌉[

**Opt-In list** — Every record with form, status and date; search and filter by 
status, follow-up actions and mail delivery.

[⌊Opt-in detail -- Timestamps and IP addresses of request and confirmation, the 
consent text, and whether the form mail ran after the click.⌉⌊Opt-in detail -- Timestamps
and IP addresses of request and confirmation, the consent text, and whether the 
form mail ran after the click.⌉[

**Opt-in detail** — Timestamps and IP addresses of request and confirmation, the
consent text, and whether the form mail ran after the click.

[⌊Forms -- All Contact Form 7 forms with Double Opt-In switched on or off per form.⌉⌊
Forms -- All Contact Form 7 forms with Double Opt-In switched on or off per form
.⌉[

**Forms** — All Contact Form 7 forms with Double Opt-In switched on or off per form.

[⌊Form settings -- Consent text, acceptance field, category, sender, subject and
confirmation page for one form.⌉⌊Form settings -- Consent text, acceptance field,
category, sender, subject and confirmation page for one form.⌉[

**Form settings** — Consent text, acceptance field, category, sender, subject and
confirmation page for one form.

[⌊Setup wizard -- Sender, forms, confirmation email and the page after the click,
in four steps.⌉⌊Setup wizard -- Sender, forms, confirmation email and the page after
the click, in four steps.⌉[

**Setup wizard** — Sender, forms, confirmation email and the page after the click,
in four steps.

[⌊Settings -- Data retention, privacy policy page, token expiry and rate limits.⌉⌊
Settings -- Data retention, privacy policy page, token expiry and rate limits.⌉[

**Settings** — Data retention, privacy policy page, token expiry and rate limits.

[⌊What the visitor sees -- After submitting: where the confirmation mail comes from
and what to do if it does not arrive.⌉⌊What the visitor sees -- After submitting:
where the confirmation mail comes from and what to do if it does not arrive.⌉[

**What the visitor sees** — After submitting: where the confirmation mail comes 
from and what to do if it does not arrive.

## 安装

#### Automatic Installation

 1. Go to **Plugins > Add New** in your WordPress admin.
 2. Search for **“Double Opt-In”**.
 3. Click **Install Now** and then **Activate**.

#### Manual Installation

 1. Download the plugin ZIP file.
 2. Upload it to `/wp-content/plugins/double-opt-in/` or use **Plugins > Add New > 
    Upload Plugin**.
 3. Activate via the WordPress **Plugins** menu.

#### First-Time Setup

 1. After activation, go to **Double Opt-In** in the WordPress admin menu.
 2. Navigate to **Forms** to see all detected Contact Form 7 forms.
 3. Click on a form to enable Double Opt-In and configure the confirmation email.
 4. Set the **Recipient Field** to the form field that contains the visitor’s email
    address (e.g. `your-email`).
 5. Customize the **Subject** and **Body** of the confirmation email, or choose a template
    preset.
 6. Save the settings and test the form.

#### Requirements

 * WordPress 6.0 or higher
 * PHP 7.4 or higher
 * Contact Form 7 5.0+ (for the CF7 integration bundled with Core)

## 常见问题

### How does Double Opt-In work?

When a visitor submits your form, the plugin stores the submission and sends a confirmation
email with a unique link. The original form mail is only delivered after the visitor
clicks that link. This verifies that the email address is valid and belongs to the
person who filled out the form.

### Is this plugin GDPR / DSGVO compliant?

Yes. The plugin tracks all data required for GDPR compliance: consent text, registration
and confirmation timestamps, IP addresses, and form data. It integrates with WordPress
Privacy Tools for personal data export and erasure requests. You can configure automatic
data retention and anonymization policies.

### Is double opt-in mandatory?

For newsletters and other advertising emails in Germany, practically yes: the sender
has to prove consent, and without the confirmation click that proof rarely holds
up. No law names the procedure, but courts and data protection authorities expect
it. This is general information, not legal advice. [More on the legal situation](https://www.forge12.com/de/blog/double-opt-in-wordpress-pflicht-rechtslage)

### Do I need double opt-in for a contact form?

A plain contact request does not need a consent checkbox or double opt-in. It becomes
necessary as soon as the form also signs people up for a newsletter or other advertising.
You can switch double opt-in on per form, or only when a checkbox is ticked (see“
Conditions” below).

### What about Switzerland and Austria?

Advertising emails need prior consent there as well, and the sender has to be able
to prove it. Double opt-in is the common way to do that, even where the law does
not name it.

### Which form plugins are supported?

The free Core plugin supports **Contact Form 7** out of the box. Support for **Avada
Forms**, **Elementor Pro Forms**, **WPForms**, and **Gravity Forms** is available
through separate paid addon plugins (install alongside Core).

### I used Avada with this plugin before. What happens now?

If you configured Double Opt-In on an Avada form before Core 5.0, a one-time notice
appears in your WordPress admin with a **“Claim free Avada grandfather license”**
button. One click installs the paid Avada addon with a permanent free license bound
to your site. Your existing setup continues working with zero configuration changes.
The free claim window is open until October 2026.

### Can I customize the confirmation email?

Yes. In the free version you write subject and text of the confirmation email in
each form’s settings and choose one of three built-in designs or plain text. Placeholders
like `[doubleoptinlink]`, `[doubleoptin_form_date]`, and form field values are replaced
automatically. The Pro version adds a visual drag & drop editor with template presets,
reusable templates and test emails.

### What happens if the user does not confirm?

Unconfirmed opt-ins are stored in the database and can be cleaned up automatically.
You can configure the retention period for unconfirmed entries in the settings (
e.g. delete after 30 days). In the Pro version, you can also send automatic reminder
emails.

### Can I redirect the user to a specific page after confirmation?

Yes. In the per-form settings, you can select a **Confirmation Page**. The user 
will be redirected there after clicking the confirmation link.

### How do I show the right message on the confirmation and error pages?

Put these shortcodes on the page:

 * `[doi_confirmation_status]` says whether the link just confirmed the address,
   was already used, has expired or is invalid. Each text can be replaced, for example`[
   doi_confirmation_status confirmed="Welcome aboard!"]`.
 * `[doi_field name="your-name"]` shows a value from the form, only right after 
   the confirmation.
 * `[doi_if status="confirmed"]…[/doi_if]` shows its content only for the listed
   outcomes (`confirmed`, `already_confirmed`, `expired`, `not_found`, or `none`
   for a visit without a link), so one page can carry a different text and different
   buttons for each case.
 * `[doi_error_message]` on the error page explains why a sign-up was refused (too
   many attempts, address already signed up, and so on).

A page without `[doi_confirmation_status]` still shows a short notice when the link
has expired or is invalid.

### Does the plugin work with CAPTCHA plugins?

Yes. The plugin automatically disables CAPTCHA validation (Google reCAPTCHA, hCaptcha,
CF7 Captcha by Forge12) when re-sending the original form mail after confirmation.
This prevents false spam detections during the confirmation step. CAPTCHA is re-
enabled immediately after the mail has been sent.

### Can I enable Double Opt-In only when a checkbox is checked?

Yes. Use the **Conditions** setting in the per-form configuration. Enter the name
of a form field (e.g. a checkbox). Double Opt-In will only be triggered when that
field has a value.

### How do I access form data after confirmation?

**Legacy approach (WordPress hook):**

    ```
    add_action( 'f12_cf7_doubleoptin_after_confirm', function( $hash, $optIn ) {
        $data = maybe_unserialize( $optIn->get_content() );
    }, 10, 2 );
    ```

**Modern approach (typed event, since 4.0):**

Use `OptInConfirmedEvent` via the EventDispatcher. The event provides `getFormData()`,`
getEmail()`, `getFormId()`, and more. See `docs/hooks-and-events.md` for the complete
reference.

### Does it work with WordPress Multisite?

Yes. When activated network-wide, the plugin creates database tables on all existing
sites. New sites added to the network automatically get their own tables via the`
wp_initialize_site` hook.

### Can I use this without Contact Form 7 or Avada?

The free version requires at least one supported form plugin. However, developers
can register custom form integrations using the `f12_cf7_doubleoptin_register_integrations`
action hook. See the developer documentation for details.

### Where can I find the developer documentation?

A hook, filter, and event reference with code examples ships at `docs/hooks-and-
events.md` inside the plugin directory. It documents 29 of the 48 action hooks, 
28 of the 86 filters, and all 13 typed events — the ones extensions actually reach
for. The rest are discoverable in the source; if you need one documented, ask and
we will add it.

### How do I report a bug or request a feature?

Please visit [forge12.com](https://www.forge12.com) or contact us via the WordPress
support forum.

## 评价

![](https://secure.gravatar.com/avatar/55143c0bf4576e597113ff7addd9604535c2b27f48af48a5c64921c3a4b57417?
s=60&d=retro&r=g)

### 󠀁[Очень полезный и функциональный плагин!](https://wordpress.org/support/topic/%d0%be%d1%87%d0%b5%d0%bd%d1%8c-%d0%bf%d0%be%d0%bb%d0%b5%d0%b7%d0%bd%d1%8b%d0%b9-%d0%b8-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%be%d0%bd%d0%b0%d0%bb%d1%8c%d0%bd%d1%8b%d0%b9-%d0%bf%d0%bb%d0%b0%d0%b3/)󠁿

 [viktoranisimov](https://profiles.wordpress.org/viktoranisimov/) 2026 年 5 月 8
日

Очень полезный и функциональный плагин! Одно из немногих бесплатных решений для 
верификации email в формах. Великолепное юзабилити, удобный и понятный интерфейс,
идеальный баланс настроек по соотношению функционал/сложность.

![](https://secure.gravatar.com/avatar/1a2c95c5a1ce2daef98b01ae25e1854b4e625058304d80340c643b28ab31fb5c?
s=60&d=retro&r=g)

### 󠀁[Great plugin.](https://wordpress.org/support/topic/great-plugin-41312/)󠁿

 [evoratec](https://profiles.wordpress.org/evoratec/) 2026 年 2 月 23 日

Perfect plugin to avoid multiples entries on mail db. Great work.

![](https://secure.gravatar.com/avatar/8dab9e9f3f0cd8c072fdfbde8fd43f379827701f2b5a97dc6161e0d5df9c6bb3?
s=60&d=retro&r=g)

### 󠀁[Einfach zu bedienen ohne viel Schnickschnack](https://wordpress.org/support/topic/einfach-zu-bedienen-ohne-viel-schnickschnack/)󠁿

 [satler](https://profiles.wordpress.org/satler/) 2026 年 2 月 3 日

Endlich mal ein Tool, welches von der Funktionalität das macht, was es soll.

![](https://secure.gravatar.com/avatar/53d314e08952375cccb8b7c06896bae253601a7adc7cbdc487824946bff730fe?
s=60&d=retro&r=g)

### 󠀁[Funktioniert](https://wordpress.org/support/topic/funktioniert-30/)󠁿

 [lucafriedrich](https://profiles.wordpress.org/lucafriedrich/) 2025 年 12 月 3 
日

Funktioniert alles und Support ist super kompetent und sympathisch

![](https://secure.gravatar.com/avatar/4b9a0d98c3bec133222b2dd3222d2baabb5fadb03d8146e39ed3ab6d01e7ba5e?
s=60&d=retro&r=g)

### 󠀁[Works as promised, outstanding support](https://wordpress.org/support/topic/works-as-promised-outstanding-support/)󠁿

 [jbraucker](https://profiles.wordpress.org/jbraucker/) 2024 年 11 月 10 日

I tried this plug-in as I needed a simple double opt-in form and was already using
wpcf7 for other forms.Configuration was easy and the plug-in packs everything I 
needed and more. It did not work at first, so I contacted the customer support and
did not expect much.To my surprise, they replied within hours, checked my configuration,
confirmed everything was right, took a backup of my website to investigate the issue
and then sent me a fix (which had to do with a change in wpcf7's checkbox validation
through an update). All of that within a day.This is customer support at its best!
The amount of effort that went into fixing my problem and the fast replies were 
exceptional. Thank you Marc Wagner and Forge12!

![](https://secure.gravatar.com/avatar/53856731249ee2fb088ef56dae66c3a54ec9da7a5ab0a80d4fbc966416336379?
s=60&d=retro&r=g)

### 󠀁[Perfect for a simple email subscription form with double opt-in](https://wordpress.org/support/topic/perfect-for-a-simple-email-subscription-form-with-double-opt-in/)󠁿

 [James C](https://profiles.wordpress.org/jamescaws/) 2024 年 1 月 8 日

After some trial and then error with other more sophisticated plug-ins, I was delighted
to find this simple one does exactly what it says. It's not trying to be fancy and
it integrates perfectly with Contact Form 7. I now have a simple email newsletter
sign-up form with double opt-in. Once the user confirms their email address via 
the opt-in email request, the Contact Form 7 plug-in sends me an email with their
address, and sends the subscriber a thank-you email.

 [ 阅读所有9条评价 ](https://wordpress.org/support/plugin/double-opt-in/reviews/)

## 贡献者及开发者

「Double Opt-In for Contact Form 7 – Secure, GDPR-Compliant Email Verification」
是开源软件。 以下人员对此插件做出了贡献。

贡献者

 *   [ Forge12 Interactive GmbH ](https://profiles.wordpress.org/forge12/)

[帮助将「Double Opt-In for Contact Form 7 – Secure, GDPR-Compliant Email Verification」翻译成简体中文。](https://translate.wordpress.org/projects/wp-plugins/double-opt-in)

### 对开发感兴趣吗?

您可以[浏览代码](https://plugins.trac.wordpress.org/browser/double-opt-in/)，查看
[SVN仓库](https://plugins.svn.wordpress.org/double-opt-in/)，或通过[RSS](https://plugins.trac.wordpress.org/log/double-opt-in/?limit=100&mode=stop_on_copy&format=rss)
订阅[开发日志](https://plugins.trac.wordpress.org/log/double-opt-in/)。

## 更新日志

#### 5.14.0

 * New: forms that a Pro module groups into a subscription can take their sender,
   subject, mail, confirmation and error page and category from that subscription.
   The consent text and consent field always stay with the form, and the settings
   stored on each form are never changed. Nothing changes without that module.
 * New: filter `f12_doi_form_config_inherited` and the admin extension point `forms.
   banner` on the form settings page.
 * Improved: a form whose required fields are supplied by its subscription is no
   longer reported as incomplete.

#### 5.13.1

 * New: the Opt-Out settings page (part of the paid Opt-Out add-on) shows a hint
   on the “Opt-Out Email” card when the saved mail has no opt-out link placeholder,
   for example when an opt-in template with [doubleoptinlink] is chosen. Needs Opt-
   Out add-on 1.8.1.

#### 5.13.0

 * New: the Notifications card on the Opt-Out settings page (part of the paid Opt-
   Out add-on) can also notify you about confirmed opt-ins and reactivations, and
   lets you write the subject, introduction and line of the mail with placeholders
   such as {form_title} and {category}, with a live preview. Needs Opt-Out add-on
   1.8.0.

#### 5.12.0

 * New: every new sign-up stores which form it came from when a page holds several
   forms (Elementor), so such forms can be told apart. Existing sign-ups are not
   changed. For Elementor forms this needs Elementor add-on 1.3.0.
 * New: the Opt-Ins list and the sign-up details can show and filter by subscription
   when a Pro module groups forms into subscriptions. Nothing changes without that
   module.
 * New: filter `f12_doi_subscription_group_resolver` for a module that provides 
   subscription groups, a read-only route `/subscription-groups` and a `group` filter
   on the Opt-Ins list.
 * Improved: the consent export panel has a Subscription filter when subscription
   groups are available.

#### 5.11.0

 * New: a Help page inside the plugin with the setup guide, troubleshooting and 
   shortcode reference, written in screenshots and short steps. Guides of installed
   add-ons appear there automatically (add-ons need their next release to bring 
   their guide).
 * Fix: e-mail addresses, recipients and IP addresses are no longer written to the
   log (rate limit, recipient check, mail event).
 * Fix: the help text of the confirmation page field said a site-wide confirmation
   page would be used; without a page the link opens the site’s start page.
 * New: filter `f12_doi_help_sources` to add help articles from another plugin.

#### 5.10.0

 * New: the Opt-Out settings page (part of the paid Opt-Out add-on) has a “Notify
   me about unsubscribes” card. Needs Opt-Out add-on 1.6.0.
 * Improved: German and French texts for the new card.

#### 5.9.0

**Withdrawals, every form plugin in the setup wizard, a confirmation page per outcome**

 * New: opt-ins withdrawn through the opt-out show as “Revoked” (filter in the list,
   detail page, its own dashboard card) instead of “Pending”; the original confirmation
   stays visible.
 * New: the setup wizard offers the forms of every installed form plugin (WPForms,
   Elementor Pro, Gravity Forms and Avada with their add-ons), not only Contact 
   Form 7, and finds the email field by its label.
 * New: [doi_if status=”confirmed”]…[/doi_if] shows its content only for the given
   outcome of the confirmation link, so one page can greet, explain an expired link
   and offer the form again.
 * New: the form settings warn when the stored consent text differs from the text
   next to the checkbox in the form (Contact Form 7), and take that text over in
   one click. Developers: FieldTextProviderInterface and the filter f12_doi_form_field_texts.
 * Fix: an add-on installed or activated on the Add-ons page works without reloading
   the page.
 * Fix: the audit log showed event types as internal keys and some messages in English;
   its rate-limit filter found nothing.
 * Fix: the WordPress personal data export described the mail status as “sent” instead
   of in words.
 * Fix: the opt-in list showed category numbers instead of names; the forms page
   said “1 forms”.
 * Fix: the credit request, the deactivation survey and the feedback links were 
   not translated; the French translation had no plural rules.

#### 5.8.1

 * Fix: on sites in formal German (Sie), a sentence on the user creation page was
   shown in English, and the role appeared as its internal key (“subscriber”) instead
   of its name.
 * Fix: German admin texts used the English names “Conditional Templates”, “User
   Creation” and “Unique Email”; they now use the German terms throughout.
 * Fix: the breadcrumb on add-on settings pages read “Page”.

#### 5.8.0

**Know whether the confirmation email went out**

 * New: every opt-in records whether its confirmation email was handed to your mail
   server or failed, and why. Shown in the opt-in list (with a filter), on the detail
   page and in Site Health; included in the WordPress privacy export and eraser.
 * New: after a Contact Form 7 submission, visitors read “please confirm your address”
   with the sender and subject to look for, instead of “Thank you for your message”.
   When the email could not be sent, they are told so.
 * New: Site Health checks SPF and DMARC of the sender domain, the two most common
   reasons confirmation emails land in spam.
 * New: a dashboard hint when many recent opt-ins stay unconfirmed.
 * New: shortcodes [doi_confirmation_status], [doi_error_message] and [doi_field]
   for the confirmation and error pages, and a readable message when a link is broken
   or expired.
 * New: a hidden honeypot field and a minimum fill time keep simple bots away from
   Contact Form 7 double opt-in forms.
 * New: the forms page suggests add-ons only for form plugins that are installed
   on the site.
 * New: after ten confirmations, a one-time request for a review, only on the plugin’s
   own pages.
 * Changed: the free plugin no longer contains locked Pro features. Email template
   management and the opt-out page generator now live in their add-ons. If you use
   them, update the email editor add-on to 1.1.0 and the opt-out add-on to 1.5.0;
   Site Health reminds you.
 * Changed: a renewed consent after an opt-out no longer overwrites the original
   confirmation; it gets its own entry in the audit log.
 * Fix: the Activate button on the Add-ons page and links in REST responses were
   broken (“&” in the URL).
 * Fix: Avada forms without a notification were reported as a failed follow-up action.
 * Fix: several admin texts stayed English on translated sites; the breadcrumb read“
   Page” on detail pages; a waiting button now shows a countdown.
 * Developers: Core API 4.6.0 with the filters f12_doi_submit_notice_data and f12_doi_mail_headers,
   the events f12_doi_optin_opted_out and f12_doi_optin_reopted_in, follow-up adapters
   for add-ons and a shared resend service.

#### 5.7.0

**A setup wizard gets new sites to the first working confirmation email**

 * New: after installing the plugin, a short wizard sets up the sender, the Contact
   Form 7 forms that should ask for confirmation, the confirmation email and the
   page visitors see after clicking the link. Everything is prefilled; it takes 
   about three minutes and can be skipped at any time. A test email to yourself 
   shows the result before visitors see it.
 * New: the sender name and address from the wizard are used for every form you 
   switch on later. Confirmation emails without a sender name no longer arrive as“
   WordPress”.
 * New: if you also use Elementor Pro, WPForms, Gravity Forms or Avada Forms, the
   wizard tells you which add-on protects those forms.
 * Improved: forms that already use Double Opt-In are left exactly as they are. 
   Existing sites do not see the wizard unless you start it under Settings.
 * Fix: this description listed the visual email editor, saved templates and test
   emails as free features. They are part of the email editor add-on; the free plugin
   offers three built-in email designs. Resending a confirmation email from the 
   opt-in details is free.

#### 5.6.3

 * Fix: the developer reference this readme points to — `docs/hooks-and-events.md`
   and `docs/addon-api.md` — was never actually included in the plugin. Both files
   now ship.
 * Improved: the notice for major updates on the Plugins screen no longer starts
   with an emoji; it already sits in a warning box.

#### 5.6.2

**A refused consent no longer looks like a successful sign-up**

 * Fix: when a visitor left the consent checkbox unticked, Contact Form 7 still 
   showed “Thank you for your message. It has been sent.” and emptied the form. 
   The actual reason appeared only in a small notice that disappeared after ten 
   seconds — so the visitor believed they were subscribed and waited for a confirmation
   mail that never came. The form now stops with “You must agree to the consent 
   statement to continue.” and keeps everything the visitor typed; they only have
   to tick the box.
 * Fix: the same on Elementor, WPForms and Gravity Forms forms — the consent checkbox
   is now marked the way a missed required field is, and the form stays on the page
   with the visitor’s input. This needs the Elementor add-on 1.2.1, the WPForms 
   add-on 1.1.1 and the Gravity Forms add-on 1.1.1. With older add-ons the success
   message is at least hidden and the notice stays until the visitor closes it.
 * Developer: new `AbstractFormIntegration::refusedConsentBeforeSubmit()` for integrations
   whose submit hook runs after the form plugin has accepted the submission (Core
   API 4.5.0, additive).
 * Note: this applies to the consent checkbox only. Other refusals (rate limits,
   blocked domains, …) keep their current behaviour and can be shown in the form
   with the filter `f12_cf7_doubleoptin_show_validation_error`, which now also receives
   the error and the form ID.

#### 5.6.1

**The admin no longer stays blank next to Avada and similar plugins**

 * Fix: on some sites the Double Opt-In admin stayed blank or loaded only partly
   after 5.6.0, depending on the browser, with “clearTimeout is not a function” 
   in the browser console. The admin script accidentally registered an internal 
   helper under the global name `_`, which WordPress and many themes and plugins(
   Avada among them) use for the Underscore/Lodash library. Whichever loaded last
   won. The admin script now keeps all of its names to itself, and it no longer 
   replaces WordPress’ own `_` either.

#### 5.6.0

**What happens after the confirmation click is now recorded, retried and visible**

 * Security: a crafted request could switch off the double opt-in for a single submission,
   so the form’s follow-up actions ran without a confirmed address. This is closed
   for all form systems. Update recommended.
 * New: every action that runs after a subscriber confirms — the form’s notification
   mail, the stored entry, and for Elementor each “Actions After Submit” step — 
   is now recorded individually with its outcome. The opt-in detail page shows them
   in a new “Follow-up actions” panel.
 * New: an action that fails for a temporary reason (mail server unreachable, timeout)
   is retried automatically after 1, 5 and 30 minutes. Actions that already succeeded
   are never run again, so a retry does not send a second mail or write a second
   entry. An action whose outcome is unclear (the connection broke after the request
   was sent) is not retried automatically; the panel says so and asks before you
   retry it by hand.
 * New: a “Retry failed actions” button on the opt-in detail page, and a “Follow-
   ups need attention” filter in the opt-in list. A manual retry starts a fresh 
   set of automatic attempts.
 * New: a Site Health check when follow-up actions keep failing, and entries in 
   the audit log for every attempt.
 * Fix: on Elementor forms the actions after the confirmation could be cut short
   by a CAPTCHA or honeypot field that was checked a second time, long after the
   visitor had passed it.
 * Fix: a second click on the confirmation link no longer runs the follow-up actions
   again.
 * Fix: with debug logging switched on, the log files could be downloaded from the
   uploads folder. The folder is now protected and the files carry names that cannot
   be guessed; existing log files are renamed on the next request.
 * Developer: new filter `f12_doi_follow_up_backoff` and adapter interface for form
   integrations; Core API 4.4.0 (additive, no breaking change).

#### 5.5.0

**An old Pro plugin no longer takes the site down with it**

 * Fix: with a Double Opt-In Pro older than 4.0 installed next to the current modules,
   WordPress failed with “There has been a critical error on this website” — including
   the admin, so the old plugin could not be deactivated, the licence page could
   not be opened, and even deleting it from the dashboard failed. The two products
   declare some program parts under the same names; the compatibility loader now
   skips the duplicate instead of loading it a second time. The site stays reachable,
   and one of the two copies is simply not run.
 * New: a Site Health check naming the outdated Pro plugin, its folder and its version,
   with a one-click “Deactivate the old plugin now”. It also appears on the dashboard
   and the plugins screen, where the problem is usually noticed.
 * New: a Site Health check for leftover Pro setup markers. Pro records that it 
   has migrated its licence and installed its modules, and those records survive
   uninstalling it — so a fresh installation used to find them and skip both steps:
   no licence, no modules, and the “Install” button on the Add-ons screen failing
   with a routing error. One click clears them; your licence key and all form settings
   are left alone.
 * Note: neither repair deletes anything from your server. Removing the old plugin’s
   folder stays a manual step over FTP or SSH on purpose — that version’s uninstall
   routine drops the opt-out database table, and the WordPress delete button would
   run it.
 * Fix: the “required field” labels in the admin appeared in English on German and
   French sites, along with 17 other untranslated strings.
 * Improved: the hook reference shipped with the plugin now documents the consent-
   gate hooks and matches the hooks that actually exist.

#### 5.4.0

**The consent checkbox is now enforced everywhere**

 * Fix: a consent checkbox configured for an Elementor form was recorded but never
   required. The visitor could submit without ticking it, and the opt-in was stored
   with your consent text as proof of an agreement nobody had given. The same gap
   applied to Contact Form 7 and Avada forms running through the older compatibility
   path. Every form system now enforces the checkbox at submit time, and a submission
   without it is rejected with “You must agree to the consent statement to continue.”
 * Change: if the acceptance field you configured is **not on the form any more**—
   renamed or deleted in your form builder — the submission is no longer rejected.
   It is accepted, and the mismatch is reported under Tools > Site Health instead.
   A settings mistake should not take your registrations offline, which is what 
   used to happen: the form silently stopped accepting anyone and nothing said why.
 * New: a Site Health check listing every form whose acceptance field no longer 
   exists, naming the form and the field. Until now nothing pointed this out unless
   you happened to open that particular form’s settings.
 * New: filter `f12_doi_enforce_consent_gate` to switch the rejection off for a 
   single form, and action `f12_doi_consent_field_unknown` to react to the mismatch
   yourself.
 * Improved: the warning on the form settings tab now says what actually happens—
   submissions go through, but without provable consent — instead of promising a
   rejection. It is also translated again; since 5.3.2 that warning had been showing
   in English on German and French sites.

#### 5.3.2

 * Fix: opt-ins collected through an Elementor form always showed “User acknowledged:
   no” in the consent audit, even when the visitor had ticked the consent checkbox.
   Elementor stores its submitted fields differently from the other integrations
   and the audit view did not know that layout, so it looked in the wrong place.
   It now reads every integration’s layout, and existing records show their acknowledgment
   correctly without anything having to be re-saved.
 * Fix: the acceptance field you picked for a form was silently converted to lower
   case when saved. Any form field whose name contains a capital letter — which 
   Elementor explicitly allows, and which is common on German sites (“Datenschutz”)—
   therefore stopped matching, the form settings kept warning that the selected 
   field does not exist, and picking it again changed nothing. Field names are now
   stored exactly as the form spells them, and a name that was already converted
   is repaired the next time the form settings are opened.
 * Fix: on the integrations that enforce the consent gate, that same conversion 
   meant the configured checkbox was never found at submit time and every registration
   was rejected as “consent not given”. Those forms accept registrations again.
 * Improved: the warning about a missing acceptance field no longer promises that
   submissions would be rejected on integrations where the consent gate does not
   run.

#### 5.3.1

 * Fix: the opt-out page you selected was discarded when settings were read, so 
   the `[doubleoptoutlink]` placeholder in confirmation and reminder mails pointed
   at your front page instead of your consent centre. It now resolves to the page
   you configured.

#### 5.3.0

**Telling you when something is broken:**

 * New: Double Opt-In now reports its own runtime preconditions under Tools  Site
   Health. If one of the plugin’s database tables is missing, you see it there as
   a critical issue with the reason spelled out, instead of a feature silently failing
   for your visitors.
 * New: a “Double Opt-In” section in Site Health  Info listing table status and 
   version numbers. It is exportable — send it along when you contact support and
   we can skip a round of questions.
 * New: an admin notice on the dashboard, the plugins screen and the plugin’s own
   pages for as long as such a problem is unresolved.
 * New: addons contribute their own checks through the `f12_doi_health_checks` filter,
   so this covers future addons without further work.

#### 5.2.0

**Getting hold of us:**

 * New: Support and Feedback links in the plugin sidebar, in the plugin list and
   in the admin menu. Until now the only route out of the plugin was the review 
   page, so a problem could only be reported as a public rating that nobody could
   answer.
 * New: the review notice offers “Something not working? Tell us” alongside the 
   review button.
 * Change: the review notice now waits for 25 confirmed opt-ins instead of 3. Three
   confirmations is too early to ask anyone to vouch for the plugin.
 * New: an optional dialog when deactivating asks what went wrong. It never blocks
   or delays deactivation, sends nothing by itself, and appears once.

**Optional credit link:**

 * New: a “Double Opt-In by Forge12” link can be shown on the page a subscriber 
   lands on after confirming. **Off by default** — it appears only if you switch
   it on under Settings, and it is marked `nofollow`.
 * New: after 50 confirmed opt-ins the plugin asks once whether you would like to
   show it, with a preview of exactly what would appear. Asked once, either answer
   ends it.
 * New: filter `f12_doi_confirmation_output` for anyone who wants to put their own
   markup on the confirmation page — the plugin had no hook there at all.

**Fixes:**

 * Fix: the plugin’s own links pointed into a section of forge12.com that does not
   exist. Every addon’s “Visit plugin site” link, the documentation links, and the
   link in the Avada migration notice returned 404. Corrected everywhere, including
   inside the translations, which carried their own copies.

#### 5.1.7

**Telemetry removed:**

 * Fix: the telemetry setting was never checked. The daily job was scheduled regardless
   of it, and the sending routine did not look at it either — so switching telemetry
   off in the settings did not actually switch anything off.
 * Fix: the daily snapshot has been removed entirely, and updating also removes 
   the job from your site’s scheduled tasks. It had been posting to an endpoint 
   that no longer exists, so it failed every day without saying so.
 * Privacy: usage counters remain on your site and are never transmitted. They are
   deleted when the plugin is uninstalled.
 * Note: nothing had actually been transmitted for some time — the receiving server’s
   TLS certificate was invalid, so WordPress refused the connection. The consent
   bug is fixed regardless.

#### 5.1.6

**PHP 7.4 compatibility:**

 * Fix: the plugin declared `Requires PHP: 7.4` but shipped PHP 8 syntax (a nullsafe
   operator and a union return type), which would have caused a fatal error on a
   PHP 7.4 server. Both are gone — the whole plugin now parses and runs on 7.4.
 * New: minimum-PHP guard. On a server older than PHP 7.4 the plugin stops before
   loading anything and shows an admin notice, instead of taking the site down with
   a white screen.
 * Fix: the plugin header was missing `Requires at least` and `Requires PHP` entirely,
   so WordPress could not block activation on an unsupported server. Both are now
   declared.
 * Maintenance: the build now refuses to package any file that would fail on PHP
   7.4, so this class of problem cannot come back unnoticed.

#### 5.1.5

**Security & hardening:**

 * Fix: the legacy AJAX endpoints (opt-in details, template loader) now require 
   the `manage_options` capability — not just a nonce — and the privileged nonce
   is no longer emitted on every wp-admin page.
 * Fix: the consent CSV export neutralises spreadsheet formula injection (values
   beginning with `=` `+` `-` `@`).
 * Fix: the visitor IP is resolved from `REMOTE_ADDR` and only trusts `X-Forwarded-
   For` from proxies you configure via the new `f12_doi_trusted_proxies` filter —
   this prevents spoofing the opt-in rate limiter and the stored GDPR consent IP.
 * Fix: the form-URL email placeholder is URL-escaped.
 * Maintenance: removed leftover debug logging, added ABSPATH guards to directly-
   reachable files, and corrected a text domain (wordpress.org compliance).

#### 5.1.4

 * Maintenance: internal refactor and packaging cleanup. (Automatic updates for 
   the paid Pro bundle and addon plugins are handled by the Pro bundle plugin, not
   the free Core plugin.)

#### 5.1.2

**Email Template Editor fixes:**

 * Fix: Centered (and right-aligned) text now keeps its alignment in the actual 
   and test emails. The generator wraps text and footer content in a `<div>` instead
   of a `<p>`, so alignment survives multi-line rich-text content (a block-level
   tag inside a `<p>` is invalid HTML and email clients dropped the alignment).
 * Fix: The builder no longer shows two “Save” buttons — removed a deprecated legacy
   editor-bundle enqueue that could mount the editor twice, and hardened the mount
   path against double-mounting.
 * New: The Social Icons block now has an editable settings panel (network + URL
   per icon, add/remove, plus icon size, spacing, alignment, and padding).

#### 5.1.1

 * Improved: Admin menu label renamed from “DOI Admin” to “Double Opt-In”.
 * Improved: Bundle-only licensing polish on the Addons page — a single “Upgrade
   to Pro” bundle CTA replaces per-addon purchase links, and gated pages no longer
   show per-module “license required” states (one key unlocks every included module).
 * Maintenance: Excluded a stray TypeScript build-cache file from the distributed
   plugin.
 * Maintenance: WordPress compatibility updated to 7.0 (“Tested up to”).

#### 5.1.0

**Form Completeness Gate:**

 * New: Per-form completeness check — a form must have all its required fields (
   recipient field, subject, body, sender address) before Double Opt-In can be enabled.
   Half-configured forms are now caught at save time and at the toggle endpoint 
   instead of silently dropping opt-ins at runtime.
 * New: `getMissingRequiredFields()` on the form-settings model returns the list
   of unconfigured fields and powers the page-level banner + master-toggle lock 
   in the admin UI.
 * New: Forms-list “Incomplete” badge + disabled toggle for incomplete forms, with
   parity between the React UI and the REST gate.
 * New: Live auto-disable on required-field clear — clearing the recipient field(
   or any other required input) instantly disables the form in the UI and removes
   the runtime hook, without waiting for a page reload.
 * New: One-shot upgrade migration that audits every stored form on `admin_init`
   and disables any that fail the completeness check. Idempotent, runs once per 
   site.
 * New: REST `save` and `toggle` endpoints reject any payload that would leave a
   form incomplete-but-enabled, with a structured error code the React UI surfaces
   inline.

**File Lifecycle (GDPR data minimization):**

 * New: `f12_doi_optin_pre_delete` cascade hook fires before an opt-in is removed,
   allowing addons to delete their own per-submission artefacts (uploaded files,
   third-party form-plugin entries).
 * New: `FileStorage` service + template-method base for file hand-off — CF7, Avada,
   Elementor, Gravity Forms, and WPForms now all delete uploaded files when the 
   parent opt-in is deleted or expires.
 * New: CF7 post-mail file-cleanup hook removes attachments from the temporary store
   as soon as the confirmation mail leaves the system.
 * New: Reset-feature integration with the file-lifecycle so a manual reset cleans
   up attached files alongside the opt-in row.
 * Improved: WP_DEBUG-gated reset-confirmation endpoint + admin button for developer-
   only re-testing of the confirmation pipeline.

**Form Settings UX:**

 * New: Page-level completeness banner with a sticky warning marker until all required
   fields are filled.
 * Improved: General tab — relabelled fields, clearer helper text, required-field
   markers, page-section descriptions.
 * Improved: Email tab — relabelled fields, clearer helper text, required markers,
   recipient-field stale-flag (recipient was set but the field no longer exists 
   on the form).
 * Improved: Mapping tab — expanded description with auto-detect hint, surfacing
   the symmetric `f12_doi_settings_dto_from_array` / `f12_doi_settings_dto_sanitize`
   filter pair so addons can round-trip arbitrary keys cleanly.
 * Improved: Forms-tabs polish + addon-settings routing — `/addon-settings/<id>`
   is now the canonical mount point for Pro and free addons.
 * Fix: Removed the fake header Save button that lied to users — only the per-tab
   Save action persists settings.
 * Fix: AdminLayout no longer reverts `enabled=true` when a save is rejected by 
   the completeness gate; the gate marker stays sticky until the user fixes the 
   underlying problem.

**Addon Platform:**

 * New: Marketplace AddonsPage with state-aware CTAs (install / activate / a single“
   Upgrade to Pro” bundle CTA), plus a registry-driven Features Overview card on
   the dashboard.
 * New: Per-addon feature toggle pages, decoupled from plugin activation — a feature
   can be installed but disabled without uninstalling.
 * New: Addons self-contribute sidebar entries via a manifest, replacing the old
   hard-coded core sidebar.
 * New: Per-addon mount points on Form Settings  Pro Features (e.g. unique-email,
   conditional, user-registration self-render their per-form panel).
 * Improved: Bundle-only licensing — every paid module is unlocked by the one Pro
   bundle license, so ProGate/AddonGate show either install guidance or a single
   bundle-activation CTA, with no per-addon purchase links or per-module license
   states.

**REST API:**

 * New: `POST /f12-doi/v1/optout/page/generate` — idempotently creates the Opt-Out
   landing page with both shortcodes, returns 409 with an edit link on title collision.
 * New: `GET /f12-doi/v1/consent-export/history?limit=N` — recent audit-runs for
   the consent-export “Recent exports” card.
 * New: `GET /f12-doi/v1/consent-export/stream-info` — live hint-counts: how many
   records this stream has exported already and when the last run was.
 * New: `DELETE /f12-doi/v1/consent-export/history` and `DELETE /f12-doi/v1/consent-
   export/history/<id>` — bulk and per-run audit deletion.

**Bug Fixes:**

 * Fix: `consent_text` snapshot was lost when the runtime migrated from the legacy`
   OptInFrontend` to `AbstractFormIntegration`. Opt-in records since then displayed“
   Not recorded” instead of the actual configured consent text. The new `buildOptInProperties()`
   shared base now captures it (and the new `consent_field`) on every opt-in.
 * Fix: Legacy frontend `FormData` proxy now resolves `getFormType` correctly so
   consent-field plumbing works on CF7.
 * Fix: Elementor `form_fields` are unwrapped in placeholder substitution — `[doi_email]`
   and friends now resolve in confirmation mails on Elementor forms regardless of
   nesting.
 * Fix: Confirmation and error redirect pages now resolve at runtime via the page-
   resolver, not at save time, so renames stay in sync.
 * Fix: `href="#"` in legacy templates no longer breaks the confirmation link in
   inline-styled mails.
 * Fix: Table doesn’t exist error for `f12_cf7_doubleoptin_categories` on manual
   file upload — both custom tables now verify on every update cycle.

**Architecture:**

 * New: Migration registry — addons register schema migrations; Core applies pending
   ones on `admin_init`.
 * New: Symmetric `f12_doi_settings_dto_from_array` / `f12_doi_settings_dto_sanitize`
   filter pair — addons can round-trip arbitrary keys through the form settings 
   DTO without monkey-patching the model.
 * Improved: Plugin is now part of a monorepo; build pipeline produces one ZIP per
   package; PHPUnit gate aborts the build on red tests.
 * Improved: Test count Core: 655  1712 unit tests across the monorepo, all green.

#### 5.0.0

**Breaking change: plugin family restructured into Core + paid addons.**

 * Breaking: Avada Forms integration removed from Core. Available as a separate 
   paid addon (`double-opt-in-avada`). Existing free-plugin users with DOI configured
   on Avada forms get a free permanent grandfather license via a one-click claim
   button in admin.
 * Breaking: PHP minimum lowered from 8.0 to 7.4 to align with WordPress’s supported
   PHP versions.
 * New: Addon API stabilised and covered by semver (`F12_DOI_CORE_API_VERSION` =
   4.3.0). See `docs/addon-api.md`.
 * New: Addon license registry (`AddonLicenseRegistryInterface`) — license providers(
   Pro bundle, standalone keys) grant entitlements; addons check `isLicensed()`.
 * New: Migration registry (`MigrationRegistry`) — addons register schema migrations;
   Core applies pending ones on admin_init.
 * New: GDPR Art. 7 consent-acceptance evidence chain. Form Settings  General now
   exposes a “Consent acceptance field” dropdown; on every opt-in Core captures 
   the consent text, the acceptance field name, and the user-acknowledged value.
   The opt-in detail view shows a proper Consent Evidence card.
 * New: Form Settings  Pro Features tab is now contributed by addons (unique-email,
   conditional, user-registration, …) via the `forms.pro-features` mount point. 
   With no Pro addon active, the tab disappears entirely instead of rendering an
   empty panel.
 * New: Dashboard widgets are now contributed via the `dashboard.widget` mount point.
   With the Analytics addon active, Top Forms / Activity / Conversion Rate cards
   appear; without it, the base dashboard shows totals + recent opt-ins only.
 * Fix: `fieldMapping` save bug — placeholder mappings configured under Form Settings
   Mapping were captured by the React form but silently dropped before persistence.
   Now correctly round-trips through the new symmetric `f12_doi_settings_dto_from_array`/…

## 额外信息

 *  版本 **5.14.0**
 *  最后更新：**2 天前**
 *  活跃安装数量 **1,000+**
 *  WordPress 版本 ** 6.0 或更高版本 **
 *  已测试的最高版本为 **7.1.3**
 *  PHP 版本 ** 7.4 或更高版本 **
 *  语言
 * [English (US)](https://wordpress.org/plugins/double-opt-in/)
 * 标签
 * [contact form 7](https://cn.wordpress.org/plugins/tags/contact-form-7/)[double opt in](https://cn.wordpress.org/plugins/tags/double-opt-in/)
   [email verification](https://cn.wordpress.org/plugins/tags/email-verification/)
   [GDPR](https://cn.wordpress.org/plugins/tags/gdpr/)[newsletter](https://cn.wordpress.org/plugins/tags/newsletter/)
 *  [高级视图](https://cn.wordpress.org/plugins/double-opt-in/advanced/)

## 评级

 5 星（最高 5 星）。

 *  [  9 条 5 星评价     ](https://wordpress.org/support/plugin/double-opt-in/reviews/?filter=5)
 *  [  0 条 4 星评价     ](https://wordpress.org/support/plugin/double-opt-in/reviews/?filter=4)
 *  [  0 条 3 星评价     ](https://wordpress.org/support/plugin/double-opt-in/reviews/?filter=3)
 *  [  0 条 2 星评价     ](https://wordpress.org/support/plugin/double-opt-in/reviews/?filter=2)
 *  [  0 条 1 星评价     ](https://wordpress.org/support/plugin/double-opt-in/reviews/?filter=1)

[您的评价](https://wordpress.org/support/plugin/double-opt-in/reviews/#new-post)

[查看全部评论](https://wordpress.org/support/plugin/double-opt-in/reviews/)

## 贡献者

 *   [ Forge12 Interactive GmbH ](https://profiles.wordpress.org/forge12/)

## 支持

最近两个月解决的问题：

     总计 1，已解决 1

 [查看支持论坛](https://wordpress.org/support/plugin/double-opt-in/)

## 捐助

您愿意支持这个插件的发展吗?

 [ 捐助此插件 ](https://www.paypal.com/donate?hosted_button_id=MGZTVZH3L5L2G)