=== Form Flight Recorder ===
Contributors: lukeaxiomflow
Tags: contact form, form notifications, submission log, monitoring, alerts
Requires at least: 6.2
Tested up to: 7.1
Stable tag: 1.0.1
Requires PHP: 7.4
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Catches the form notification that was never generated and the form that quietly stopped submitting — the two failures a mail log cannot show.

== Description ==

Your form said "Thanks!" — did the lead actually reach you?

Two failures no mail logger can show you, because in both cases **there is nothing to log**:

1. **The submission that produced no notification.** The form completed, the visitor saw the thank-you message, and no email was ever generated — a misconfigured notification, a conflict, a broken hook. Nobody was told about the lead.
2. **The form that silently stopped working.** An update broke the page, a JS error killed the submit button, a spam filter started eating everything. Zero submissions looks exactly like a quiet day — unless something knows the form's normal rhythm.

Form Flight Recorder watches both, across **Contact Form 7, WPForms, Gravity Forms, Ninja Forms and Fluent Forms**:

**Reconciliation ledger**

* Every completed submission is recorded (counts and timestamps — never the content) together with the notification evidence from the same request: emails generated, hand-off to the mail system, transport failures, and the form plugin's own sent/failed status where it offers one (Contact Form 7 does).
* A submission that expected a notification and produced **none** becomes a "NO notification" alarm.
* A notification the mail transport rejected becomes a "send failed" alarm with the transport's own error text.
* Expectations come from the form plugin's settings at submission time (CF7 skip_mail/demo mode, WPForms notification settings, Gravity Forms active notifications), with a per-form auto/on/off override.

**Heartbeat**

* Every form gets an automatic baseline (its usual submissions/week). A form that normally receives submissions and has gone quiet beyond its threshold — both your configured hours and 3× its typical gap — raises a "form gone silent" alarm. Forms without a meaningful baseline are never flagged (no false alarms on genuinely quiet forms).

**Alerts & visibility**

* Instant email the first time a form misses a notification, fails a send, or goes silent (max one per form per day).
* Daily or weekly digest — sent only when there's something to say.
* Cockpit page: reconciled ledger, silent forms, per-form baselines.
* Site Health checks and WP-CLI (`wp ffrd status --format=json`).

**Form Flight Recorder Pro** (in-dashboard upgrade, 14-day trial, no card):

* **Page-presence check** — daily proof each form still renders on its page (catches "the update removed my form").
* Slack / webhook alert channels.
* Weekend-aware baselines (no Monday-morning false alarms).
* REST status endpoint + CSV export for agencies, 90-day history.

**Pure observation.** The wp_mail observation is a passthrough — nothing is blocked, delayed or altered, and no form plugin data is ever written. Form Flight Recorder verifies that your site *generated and handed off* each notification; what happens after hand-off belongs to your mail transport (that's what SMTP plugins and mail logs are for — we tell you when there was nothing to log).

== External services ==

**The plugin's own features contact nothing external.** Reconciliation reads your own database, and alert and digest emails go through your site's normal mail system. No submission content ever leaves your site.

**Freemius (freemius.com), who sell and license the Pro version**

Freemius is contacted in four situations. Every one of them is something you click. It is never contacted in the background.

1. **If you opt in on the activation screen** (or start a trial / activate a licence). Sent to api.freemius.com: your site URL, your WordPress and PHP versions, and the email address of the account you activate with. Skipping the opt-in is a first-class choice and the plugin is fully functional without it.
2. **If you open the "Upgrade" page** under the plugin's menu. Your own server (not your browser) asks api.freemius.com for current plan prices, sending your site URL. This happens whoever you are, including if you skipped the opt-in — but only when you open that page. The page itself loads no third-party scripts; everything it renders is served from this plugin's own folder. The payment SDK's bundled pricing script used to inject Google Analytics and a remote checkout script into wp-admin on that page; this build removes both, along with the SDK's remaining remote references (all modifications are listed under "Source code" below).
3. **If you open the "Contact Us" page**, which is Freemius's hosted support form (wp.freemius.com). The link carries your site URL and your WordPress login URL so the form knows which site you are writing about.
4. **If you click a plan to buy**, you go to Freemius's hosted checkout (checkout.freemius.com). It receives your site URL, site name, WordPress and PHP versions, and your WordPress administrator email address (pre-filled, sent whether or not you complete the purchase). Freemius is the merchant of record. Their checkout page loads its own third-party scripts (at the time of writing: Stripe, PayPal, Google Tag Manager, and Freemius's own assets); we do not control that list. If you never click a plan, none of it loads.

Terms: https://freemius.com/terms/ — Privacy: https://freemius.com/privacy/

Installing, activating, skipping the opt-in, every scheduled check, using every screen, deactivating (the SDK's deactivation-feedback dialog is switched off in this build, so deactivation is one click and sends nothing), and WordPress's update cycle all complete without contacting Freemius at all. Free updates come from WordPress.org like any other plugin.

**Your own site and alert endpoints (Pro, optional)**
The Pro page-presence check fetches **your own site's public pages** from your own server (loopback requests); nothing goes to a third party. If you enter a Slack or webhook URL, alerts are POSTed to that URL you chose, only when an alert fires. Nothing is sent anywhere you did not enter yourself.

== Source code ==

This plugin's own PHP and JavaScript are unminified and readable in the plugin folder. The one exception is the third-party payment SDK in `vendor/freemius/`, which ships pre-minified; its source and build tooling are public:

* Freemius WordPress SDK: https://github.com/Freemius/wordpress-sdk
* The pricing screen at `vendor/freemius/assets/js/pricing/freemius-pricing.js`: https://github.com/Freemius/pricing-page

This plugin ships four deliberate modifications to that SDK (all in `assets/js/pricing/freemius-pricing.js`, all removing remote references from wp-admin): the `appendScripts()` method is emptied (it injected Google Analytics + checkout.js), the GA pageview tracker is stubbed out, the remote loader GIF is replaced with an inline data-URI, and testimonial photos are forced to the bundled placeholder. Three carry a "Form Flight Recorder:" comment at the patch site.

== Installation ==

1. Install and activate. You'll find **Form Flight Recorder** in the admin menu.
2. It starts recording with the next submission on any detected form plugin (Contact Form 7, WPForms, Gravity Forms, Ninja Forms, Fluent Forms).
3. Set your digest and silence thresholds under **Settings**; tune individual forms under **Forms**.

== Frequently Asked Questions ==

= Does it store what visitors typed into my forms? =

No. Counts, timestamps, form ids/titles, a masked recipient (j***@example.com) and the first 40 characters of the subject line — never field content.

= Does it prove the email reached the inbox? =

No plugin can. Form Flight Recorder proves your site **generated** the notification and handed it to the mail system (and records the transport's error when hand-off fails). Deliverability beyond that point is your SMTP provider's territory — the point of this plugin is the failure class where there's nothing for a mail log to show: the email that was never generated at all.

= Which form plugins are supported? =

Contact Form 7, WPForms (Lite and Pro), Gravity Forms, Ninja Forms and Fluent Forms. Forms from other plugins are not recorded.

= My form intentionally sends no email. Will it nag me? =

Mark that form "off" on the Forms tab and its missing-notification alerts stop. The heartbeat still watches its submission rhythm.

= How does the silence detection avoid false alarms? =

A form is only flagged when it averages 3+ submissions/week AND has been quiet longer than both your threshold and 3× its typical gap. Pro adds weekend-aware baselines.

= Why did a spam submission not appear in the ledger? =

Submissions rejected by validation or flagged as spam never complete, so they are not real submissions — the recorder only counts what the form plugin accepted.

== Screenshots ==

1. The cockpit: reconciled ledger, silent forms, problem counters.
2. Per-form settings: expectations, baselines and silence thresholds.
3. Site Health checks.

== Changelog ==

= 1.0.1 =
* Initial public release: submission-to-notification reconciliation across Contact Form 7, WPForms, Gravity Forms, Ninja Forms and Fluent Forms; zero-submission heartbeat with per-form baselines; instant alerts and daily digest; Site Health tests; WP-CLI with JSON.

== Upgrade Notice ==

= 1.0.1 =
Initial public release.
