=== TrackFormPro – Lead Form Tracking for Meta Conversions API & Pixel ===
Contributors: trackformpro, freemius
Tags: meta conversion api, facebook pixel, facebook conversion api, lead generation, server side tracking
Requires at least: 6.0
Tested up to: 7.1
Requires PHP: 7.4
Stable tag: 1.4.9
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

For lead generation: Gravity Forms, WPForms, Contact Form 7, Fluent Forms, Formidable and Elementor leads to Meta's Conversions API and Pixel.

== Description ==

**Track Form Pro** sends every form submission (Gravity Forms, WPForms, Contact Form 7, Fluent Forms, Formidable Forms and Elementor Forms) to Meta as a Conversions API (CAPI) server event, and can also fire the matching Meta Pixel event in the browser using the same event ID so Meta counts the conversion once.
**Built for lead generation businesses:** sites whose sales start with a form, such as quote and estimate requests, bookings and consultations, callbacks, contact forms, free inspections and demos. Typical users are local services, agencies, clinics, B2B, real estate and education.

Track Form Pro is an independent plugin. It is not affiliated with, endorsed by or sponsored by Meta Platforms, Inc. "Meta", "Facebook" and "Meta Pixel" are trademarks of their owner and are used only to describe what the plugin connects to.

**Not for online stores:** it doesn't track WooCommerce orders, checkouts or product events. For a shop, use a WooCommerce tracking plugin.

**Key Features:**
- **Works with Gravity Forms, WPForms (Lite and Pro), Contact Form 7, Fluent Forms, Formidable Forms and Elementor Forms (beta).**
- **Every form found and filled in for you**: forms from all six form plugins are listed on their own, and the email, phone, name and address fields are filled in from each form's field types. Change any of them from dropdowns: email, phone, first/last name, city, state, ZIP, country, gender, date of birth, external ID.
- **Normalization and SHA-256 hashing** of customer data on your server, following Meta's formatting rules (e.g. phone numbers with country code, 2-letter state and country codes).
- **Browser + server deduplication** with a shared `event_id`.
- **Meta click and browser IDs** (`_fbc`, `_fbp`, and `fbclid` from the landing page URL) forwarded with server events.
- **Event per form** (Lead, Contact, Schedule, Purchase…) and a **Track** switch for forms you don't advertise for.
- **Value and currency** from form fields, with a per-form default value.
- **Ad click and UTM tracking:** the fbclid and UTMs from the landing page are kept and sent with the lead.
- **Privacy:** a consent option that works with the WP Consent API (Complianz, CookieYes, Cookiebot and other banners) or a consent cookie, and starts tracking as soon as the visitor accepts; Limited Data Use for US state privacy laws, following Global Privacy Control and Do Not Track.
- **Bot filtering:** search engines, crawlers, uptime monitors and automated browsers don't load the Pixel and their form submissions aren't sent, keeping fake leads out of your ad results.
- **Setup checklist, health check with plain-language fixes, help tips and a guide.**
- **Activity log, automatic retries and a test-event button** in the admin.

**Track Form Pro Premium** (paid plans with a 14-day free trial, available from the plugin's Upgrade menu or trackformpro.com) adds an attribution report (leads, conversion rate and lead value per campaign, ad set and ad), form abandonment (which forms visitors start but don't finish, and the field where they leave), a weekly email report, URL triggers, duplicate-lead blocking, direct CookieYes / Complianz / Cookiebot consent, waiting for values from lead routers, CRMs or Zapier, average lead values, trigger rules and custom events, several pixels, funnel events, Event Match Quality from Meta, email alerts and double-counting detection. The free plugin is complete without it.

== Installation ==

1. Upload the plugin files to `/wp-content/plugins/track-form-pro` or install via the Plugins screen, then activate it.
2. In Meta Events Manager, generate a Conversions API access token for your dataset (pixel).
3. Go to **Track Form Pro → Settings → General** and add the pixel ID and access token. Recommended settings (browser events, deduplication, advanced matching) are already on; the **Get started** checklist guides you through the rest.
4. In **Status & Test**, send a test event with a Test Event Code from Events Manager to confirm the connection.
5. In **Forms**, choose the event for each form and map at least the email and phone fields. Switch off **Track** on forms you don't advertise for.
6. Check **Status & Test → Health check** for anything that still needs attention.

== Privacy ==

**What is sent:** when a tracked form is submitted, your site sends an event directly to the Meta Conversions API (graph.facebook.com). No other service is involved. The event includes:
- Mapped customer fields (email, phone, names, city, state, ZIP, country, gender, date of birth, external ID), normalized and **SHA-256 hashed on your server** before sending.
- Unhashed technical data Meta requires: visitor IP address, browser user agent, the `_fbp`/`_fbc` Meta cookie values, the page URL and referrer, UTM parameters, the form entry ID, and any mapped value/currency.

The browser Pixel (loaded from connect.facebook.net) also sends page views and form conversion events directly from the visitor's browser to Meta. With "Advanced matching" on (default), the browser conversion event also carries the same SHA-256-hashed customer fields as the server event.

**Cookie:** when a visitor arrives from an ad or a campaign link, the plugin stores the Meta click ID (fbclid) and UTM parameters in a first-party cookie, `track_form_pro_attr`, for up to 90 days, so a later form submission can be attributed to that click. With the consent option on, the cookie is only set after consent. These values are also saved on the form entry.

**US privacy laws:** the "US state privacy laws" setting can send Meta's Limited Data Use flag either only for visitors who opted out (the browser's Global Privacy Control or Do Not Track signal, or a `track_form_pro_do_not_sell=1` cookie set by your consent tool) or for all visitors; Meta then applies it to visitors from US states with privacy laws.

**What is stored on your site:** your pixel IDs and access tokens (in the WordPress options table; tokens are never printed back into admin pages). When logging is enabled, event payloads (hashed customer data, IP address, user agent, page URLs) and Meta's responses are stored in a database table on your site; access tokens are never logged. Logs older than 30 days are deleted automatically, and you can clear them at any time. Events that fail to send are kept in a retry table for up to 6 days.

**Your responsibility:** as the site owner, you must disclose this data sharing in your privacy policy and obtain consent where the law requires it (e.g. GDPR, CCPA). Enable the plugin's GDPR option if tracking must wait for consent.

== External Services ==

This plugin connects to the following external services:

**Meta Conversions API (graph.facebook.com)**
- **What it is:** Meta's server-side API for advertising measurement.
- **Data sent:** the event data listed in the Privacy section, sent with your pixel ID and access token.
- **When:** every time a tracked form is submitted, and when you click "Send test event" in the Status & Test tab.
- **Terms of Service:** https://www.facebook.com/legal/terms/businesstools
- **Privacy Policy:** https://www.facebook.com/privacy/policy/

**Meta Pixel (connect.facebook.net)**
- **What it is:** Meta's browser tracking script.
- **Data sent:** page views and form conversion events from the visitor's browser, including Meta cookies.
- **When:** on every page view (unless the GDPR option is on and consent is missing) and after a tracked form is submitted.
- **Terms of Service:** https://www.facebook.com/legal/terms/businesstools
- **Privacy Policy:** https://www.facebook.com/privacy/policy/

**Bundled font**
- The admin pages use the Archivo font, included in the plugin (`assets/fonts`, SIL Open Font License 1.1). It is loaded from your own site; no font service is contacted.

**Freemius**
- **What it is:** plugin SDK for opt-in usage statistics, support, and the optional Premium upgrade (pricing page, free trial, checkout and licence activation).
- **Data sent:** only if you opt in: site URL, WordPress/PHP versions, plugin version and admin email. No form or visitor data.
- **When:** on activation (opt-in screen), periodically after opting in, and when you open the Upgrade page, start a trial or activate a licence.
- **Terms of Service:** https://freemius.com/terms/
- **Privacy Policy:** https://freemius.com/privacy/

== Frequently Asked Questions ==

= Does this plugin add the Meta Pixel code? =
Yes. It adds the Meta Pixel base code and a PageView in the page `<head>` for the pixels you configure. Remove any other copy of the same pixel (theme, tag manager or another plugin) to avoid double counting.

= Which form plugins are supported? =
Gravity Forms, WPForms (Lite and Pro), Contact Form 7, Fluent Forms, Formidable Forms and Elementor Forms (Elementor Pro; in beta). Server events work with AJAX and non-AJAX forms, and browser events use the same event ID. Contact Form 7, WPForms Lite and Elementor don't store entries, so their leads are always sent right away (Premium's "wait for the value" needs stored entries).

= Does it work with caching plugins? =
Yes. Leads are sent from your server when the form is submitted, so page caching (WP Rocket, LiteSpeed Cache, W3 Total Cache, Cloudflare and others) doesn't stop them. The browser event uses a token created in each visitor's browser, so cached pages don't mix visitors up. Don't combine or delay the Track Form Pro script if your optimization plugin lets you exclude scripts, so the browser event fires right away.

= Does data go through a third-party server? =
No. Events go straight from your site to Meta's Conversions API. Your access token and customer data are not sent anywhere else.

= Is customer data hashed? =
Mapped customer fields are normalized and SHA-256 hashed on your server before they leave it. IP address, user agent and Meta cookie values are sent unhashed because Meta requires them that way.

= What happens if Meta is unreachable? =
The event is retried automatically after 1, 5 and 15 minutes, 1 hour and 6 hours, with the same event ID, so it is never counted twice. Network errors, timeouts and "Meta is busy" answers are retried; an invalid token or event is reported instead, because it would fail the same way again. Track Form Pro → Activity Logs shows what is waiting, with a Retry now button, and whether each failed event was delivered later. Events older than 6 days are dropped because Meta rejects them.

= How do I test the connection? =
Open Track Form Pro → Settings → Status & Test, enter the Test Event Code from Meta Events Manager → Test events, and click "Send test event". Meta's response is shown immediately.

= Can I use more than one pixel? =
The free plugin sends to one pixel. Track Form Pro Premium adds more pixels and a pixel per form.

= What does Premium add? =
Waiting for values filled in by lead routers, CRMs or Zapier; average lead values; trigger rules and custom events; a pixel per form; funnel events; Event Match Quality from Meta; email alerts; and double-counting detection. You can start a 14-day free trial from Track Form Pro → Upgrade; the free plugin works fully on its own.

== Screenshots ==

1. General settings: one Meta pixel with its Conversions API token, browser events and deduplication.
2. Forms from Gravity Forms, WPForms, Contact Form 7, Fluent Forms and Formidable Forms in one list, each with its Meta event.
3. Per-form mapping: customer data, value field and a default value.
4. Status & Test: health check, connection status and a test event.
5. Activity Logs: every event sent to Meta and Meta's answer.
6. How to Configure: a plain-language setup guide in the plugin.

== Changelog ==

= 1.4.9 =
* The plugin is now listed as "TrackFormPro – Lead Form Tracking for Meta Conversions API & Pixel" (WordPress.org naming rules). Nothing changes in how it works.

= 1.4.8 =
* Several Meta pixels in the free version: add as many pixels as you need, and every lead is sent to each of them. Premium adds choosing a pixel per form.
* Premium, sites that already have several pixels: your existing forms keep sending to the first pixel, as before. New forms send to all pixels until you choose one.
* The plugin is now called "Track Form Pro – Lead Form Tracking for Meta Conversions API & Pixel". Track Form Pro is not affiliated with Meta.

= 1.4.7 =
* Plugin header: the author address is no longer a copy of the plugin address (a WordPress.org requirement). No change in how the plugin works.

= 1.4.6 =
* Security hardening: request data is read together with its nonce check, a signed-in user's browser-events request needs a valid nonce, and the hidden form fields are escaped where they are printed.
* Internal names (transients, query arguments) all use the track_form_pro_ prefix.

= 1.4.5 =
* Free version: fewer upgrade prompts on the General tab. Premium features are listed once, in the summary at the bottom of the page.

= 1.4.4 =
* Multisite: every site of a network gets the recommended settings and its own tables, also sites added later; deleting the plugin cleans up every site.
* Deactivating the plugin removes its scheduled jobs (they are scheduled again when it is activated).

= 1.4.3 =
* Premium: Meta's Event Match Quality is shown in the header of the settings page (for example "Match quality 9.3/10") and kept up to date in the background.

= 1.4.2 =
* Report (Premium): new Placement and Platform breakdowns. Add placement={{placement}} and site_source_name={{site_source_name}} to your ad URL parameters to see leads per Feed, Reels, Stories, and per Facebook or Instagram.
* Report: campaign_id, adset_id and ad_id are read too, and are shown when no name is passed. All campaign parameters are now remembered when the visitor moves to another page before submitting.
* Report: "ig", "an", "msg" and "th" as utm_source are counted as Meta traffic.
* Form abandonment is easier to read on phones.
* Fixed: Contact Form 7 forms were shown as "#cf7_10" instead of "#10" in the activity log; the Status tab shows the form's name for the last event.

= 1.4.1 =
* Activity Logs: events from older versions that failed and were then delivered are now shown as retried (not failed), with the right attempt numbers.
* Premium report: sources written as facebook_ad, fb, meta_ads and similar are reported as "facebook", and placeholders Meta didn't fill in (such as {{ad.id}}) as "(none)". Earlier report data is renamed on update.
* Premium report: lead values show their currency, and the conversion rate says "new" when there is no earlier period to compare with.
* Premium form abandonment: multi-step forms (e.g. Gravity Forms pages) and forms with validation errors now report the field where visitors left on later steps too.

= 1.4.0 =
* Customer data is filled in for you: the email, phone, name and address fields of each form are found from the form plugin's field types (and their labels), and used until you change them. A field with the whole name is sent as first and last name. Forms whose fields were saved as "Not mapped" earlier show "Email/phone fields found" and a "Use the fields found" button.
* Premium: Form abandonment in the report: which forms visitors start but don't submit, how many, and the field they were in when they left. Only the field is recorded, never what visitors type; consent and bot filtering apply as for the rest of the report.
* Premium: Weekly email report: leads and lead value, what reached Meta, top forms and campaigns, forms visitors give up on and anything in your setup that needs a look, on the day you choose. "Send one now" shows you the email.
* Premium: the Double-counting check is now shown under General → Lead quality & reports, with what it found.
* New look for the admin pages, matching trackformpro.com: a navy header, clearer type (Archivo, bundled), a white canvas, and the forms as one list.
* Report counters only accept forms that exist on the site.

= 1.3.1 =
* Activity Logs redesigned: results by day, filters (sent, retried, failed), customer data at a glance, a 7-day chart, and details with what was sent, Meta's answer and every delivery attempt. Works on phones.
* Failed events that are being retried now show as "Retrying" instead of "Failed", and a failed event shows "Delivered later" once a retry gets through.
* New "Waiting to retry" panel with a Retry now button.
* Failure alert emails redesigned: they explain what is wrong and how to fix it, name the form, and come from "Track Form Pro".
* Tested with Elementor 4.3.2 (Elementor Forms are still labelled beta), and with Autoptimize, LiteSpeed Cache (combine, defer and delay JavaScript), Complianz, CookieYes and WP Consent API.
* Fix: with "Require consent" on, a visitor who accepts the consent banner and then submits a form on the same page now also gets the browser event. Before, browser tracking only started on the next page.
* Fix: WP Consent API with consent banners that only tell the browser their consent model (e.g. CookieYes): server events now wait for the visitor's explicit consent, like browser events.
* Retries keep the time of the first failure, so an event is never sent after Meta's 7-day limit.
* Report: same header as the other pages, fits on phones, and conversion rates are hidden when fewer form views than leads were recorded (instead of showing more than 100%). In the free version, the Report page now previews the real report with example numbers.
* Clearer Premium badge (gold, with a crown) on locked features in the free version.
* Removed "Send only when paid" for Gravity Forms payment forms, so every form plugin works the same way: the event is sent when the form is submitted. Events still waiting for a payment when you update are sent right away.

= 1.3.0 =
* Under the hood: the code is reorganised for easier maintenance (every function now uses the plugin's own prefix, and lead sending and the settings and log pages are classes). Nothing changes in how the plugin works or what it sends.
* Fix: a PHP 8.4 notice in the Premium report's CSV export.

= 1.2.3 =
* First release on WordPress.org.
* Form plugins: Gravity Forms, WPForms (Lite and Pro), Contact Form 7, Fluent Forms, Formidable Forms and Elementor Forms (beta), all on one shared engine.
* Meta Conversions API server events (Graph API v25.0) sent directly from your site, with the matching browser Pixel event and a shared event ID for deduplication.
* Customer data normalized to Meta's format and SHA-256 hashed on your server; fbclid, _fbc, _fbp and UTMs kept from the landing page.
* Event, value, currency and default value per form, and a Track switch for forms you don't advertise for.
* Privacy: WP Consent API or consent cookie, Limited Data Use following Global Privacy Control and Do Not Track, and bot filtering.
* Get started checklist, health check with plain-language fixes, test-event button, activity log and automatic retries.
* Works with page caching (WP Rocket, LiteSpeed Cache, W3 Total Cache, Cloudflare and others): every visitor gets their own submission token, and leads from cached pages are still counted once.
* Forms that redirect to a thank-you page also fire the browser event, on the thank-you page, with the server's event ID.
* Optional Track Form Pro Premium with a 14-day free trial from the Upgrade menu.

== Upgrade Notice ==

= 1.4.9 =
New plugin name for WordPress.org; nothing changes on your site.

= 1.4.8 =
Several pixels in the free version. Premium sites with several pixels: check Forms → Pixel for new forms.

= 1.4.7 =
Plugin header only; nothing changes on your site.

= 1.4.6 =
Security hardening and consistent internal names.

= 1.4.5 =
Fewer upgrade prompts in the free version.

= 1.4.4 =
Multisite set-up and clean-up, and scheduled jobs removed on deactivation.

= 1.4.3 =
Match quality in the settings page header.

= 1.4.2 =
Placement and Platform breakdowns in the report, more ad URL parameters, small fixes.

= 1.4.1 =
Fixes for Activity Logs, the report's source names and form abandonment on multi-step forms.

= 1.4.0 =
Email, phone and name fields are filled in for you; Premium adds form abandonment and a weekly email report; new look for the admin pages.

= 1.3.1 =
Clearer Activity Logs with retry status and a Retry now button.

= 1.3.0 =
Code reorganised for easier maintenance; no change in behaviour.

= 1.2.3 =
First release on WordPress.org.
