# KD Submissions

**Contributors:** keydigital1  
**Tags:** elementor, form submissions, leads, crm, analytics  
**Requires at least:** 6.2  
**Tested up to:** 7.1  
**Requires PHP:** 8.0  
**Stable tag:** 2.3.0  
**License:** GPLv2 or later  
**License URI:** [https://www.gnu.org/licenses/gpl-2.0.html](https://www.gnu.org/licenses/gpl-2.0.html)

Lead management for Elementor form submissions: statuses, comments, lead sources, contact-click tracking and an analytics dashboard.

## Description

KD Submissions turns Elementor Pro form submissions into a simple lead inbox and dashboard on the front end (`/pieteikumi`), so site owners can work with their leads without going into wp-admin.

**Lead management**

- Combined list of all new (unread) submissions across forms.
- Multiple statuses per submission, custom statuses, and comments shown as pills.
- Filter by form, status and date; hide or show columns; rename forms and fields.
- Add submissions manually (e.g. leads from a phone call).
- Access for Administrators, Editors and Shop Managers.

**Analytics**

- Dashboard with submissions, email and phone link clicks, visitors and sessions (visitors and sessions come from Independent Analytics, if installed).
- Charts for submission trends, statuses, forms and lead sources.
- Lead source for every submission: UTM source, external referrer (e.g. google.com, facebook.com), direct visit, or "no data" when the source is unknown.

**Spam detection (on your site only)**

- Every new submission gets a spam score from simple signals: an invisible honeypot field, form filled in too fast, links (also in the name field), typical SEO/marketing pitches, disposable email domains and the same text sent repeatedly.
- Nothing is blocked or deleted. Likely spam gets the status "Iespējams spams" with the reasons next to it, and is left out of the dashboard counts. Remove the status and the submission counts again.
- Works alongside CleanTalk, which blocks most spam before it is saved.

**Privacy-friendly lead source tracking**

- The source is remembered across pages in a first-party cookie (`ref_source`, 30 days) **only after the visitor gives analytics consent**. Supported: WP Consent API, Cookiez banner, or a custom `window.kdSubmissionsHasConsent()` function.
- Without consent nothing is stored on the visitor's device; only the source of the current page view is sent with the form.
- The cookie is deleted when consent is withdrawn.

**Optional: KEY DIGITAL client portal**

Sites maintained by KEY DIGITAL can share aggregated statistics (numbers only, no personal data) with the KEY DIGITAL client portal. This is **off by default** and described in detail under *External services* below.

## External services

This plugin can connect to the **KEY DIGITAL client portal** (go.key-digital.lv, operated by KEY DIGITAL SIA, Latvia) so the site owner and their maintainer can see site results in one place.

**The connection is off by default.** It is switched on in *Pieteikumi → Iestatījumi → KEY DIGITAL statistika* (or with `define( 'KEYD_WHMCS_SYNC', true );` in `wp-config.php`). Sites that were already sending statistics with version 2.2.0 or older keep it on after updating and see a one-time admin notice with a link to switch it off.

**What is sent (aggregated numbers and names only, no personal data):**
- site address and name;
- number of submissions, unread submissions, and distribution by status;
- number of submissions per form (top 5) and per traffic source, e.g. Google, Facebook, direct (top 5);
- number of clicks on email and phone links;
- number of visitors and sessions (from Independent Analytics, if installed) and conversion rate.

**Not sent:** submission content, names, email addresses, phone numbers, IP addresses, uploaded files or any other personal data.

**When:** after a new submission or contact click (at most once per minute), once a day as a summary, and when the portal requests the current unread count (`POST /wp-json/keyd/v1/unread-count`, signed requests only). When sharing is switched off or the plugin is deactivated, a single signed notice with only that state (no statistics) is sent, so the portal can show why data stopped.

**Security:** each site generates its own key. The key is sent once over HTTPS during registration and confirmed by the portal through `POST /wp-json/keyd/v1/handshake`. All later requests in both directions are signed with HMAC-SHA256 (timestamp + nonce); the key is not sent again.

- Privacy policy: https://key-digital.lv/privatuma-politika/
- Terms of use: https://key-digital.lv/lietosanas-noteikumi/

## Frequently Asked Questions

### Does the plugin require Elementor Pro?
Yes. Submissions are read from Elementor Pro's form submissions tables.

### How do I add a new status?
Use the **Status Manager** button. The new status is available immediately.

### Can I filter submissions by multiple criteria?
Yes, by form, status and creation date at the same time.

### Is the `ref_source` cookie set without consent?
No. Without analytics consent the lead source is only taken from the page the visitor is on when submitting the form, and nothing is stored in the browser. You can change the consent category or cookie lifetime with the `keyd/referral/config` filter.

### My leads now show "Tiešais apmeklējums" (direct visit) more often. Why?
Since 2.2.1 the source is remembered across pages only with analytics consent. Visitors who decline cookies and browse a few pages before submitting are recorded as a direct visit. This is expected and required by EU cookie rules.

### What does the plugin send to KEY DIGITAL?
Only when you switch it on: aggregated numbers (submissions, clicks, visitors, top forms and lead sources by count). Never names, emails, phone numbers, IP addresses, messages or files. See *External services*.

### How do I switch statistics sharing on or off?
*Pieteikumi → Iestatījumi → KEY DIGITAL statistika*. Agencies can force the setting with `define( 'KEYD_WHMCS_SYNC', true );` (or `false`) in `wp-config.php`.

### The settings show "Nav savienots" (not connected). What now?
The KEY DIGITAL portal confirms the connection by calling `/wp-json/keyd/v1/handshake` on your site. Security plugins, firewalls or a password on the site can block it. Allow that route, then click **Izveidot savienojumu no jauna**. Automatic retries slow down after failures (15 min, 1 h, 3 h, 6 h, 12 h, then daily).

## Changelog

### 2.3.0
Spam detection:
- New local spam check for Elementor submissions (honeypot, fill-in time, links, marketing phrases, disposable emails, repeated text). Likely spam is marked "Iespējams spams" with its reasons, never deleted, and excluded from totals, unread count, trends, statuses, forms, lead sources and conversion.
- Filters: `keyd/spam/enabled`, `keyd/spam/threshold` (default 5), `keyd/spam/phrases`, `keyd/spam/disposable_domains`.
- KEY DIGITAL portal receives only the number of likely spam submissions, reason codes and whether CleanTalk is active — never the content.

Lead source:
- "Tiešais apmeklējums" is now used only for real direct visits. When the source is unknown (e.g. the visitor came from another page of the site and no consent was given), "Nav datu" is saved instead.
- Fixed: consent given on an inner page stored "direct visit" for the whole session.
- Returns from payment, bank and sign-in pages (Stripe, PayPal, Montonio, Paysera, banks, Google/Apple/Microsoft login) no longer count as the source; `www.` is treated as the same site.

KEY DIGITAL portal connection:
- The connection check also works when the REST API is closed by a firewall (via `?rest_route=` and `admin-ajax.php`).
- Fixed: 2.2.1 switched statistics sharing off on some sites that were sending statistics. They are switched back on once, with a notice; sites where the admin chose the setting are never changed.
- New, lighter notice that can be dismissed for good.

Other:
- Requires PHP 8.0 and WordPress 6.2.
- Plugin Check clean: all database queries use placeholders (`%i` for table names), SVG icons are escaped with `wp_kses()`.

### 2.2.1
**Security and privacy release. Recommended for all users.**

KEY DIGITAL portal connection:
- Removed the shared secret that was built into the plugin. Each site now creates its own key, registers it once with the portal (confirmed by a callback to the site) and signs every request with HMAC-SHA256 including timestamp and nonce (replay protection). Requests from the portal to the site are signed the same way.
- Statistics sharing is now opt-in, with a new settings tab "KEY DIGITAL statistika" that lists exactly what is sent and what is not. Sites that were already sending statistics keep sharing on after the update and see a one-time notice with a link to switch it off.
- When sharing is switched off or the plugin is deactivated, the portal receives a single notice with only that state, so it can show "sharing off" instead of "no data".
- Nothing is counted or sent while sharing is off.
- Failed connection attempts back off (15 min, 1 h, 3 h, 6 h, 12 h, then daily); the next attempt time is shown in settings.
- New optional `KEYD_WHMCS_SYNC` constant to force and lock the setting from `wp-config.php`.
- Multilingual sites (Polylang, WPML, TranslatePress) always report their main address, so one site no longer appears as several (e.g. `/en`, `/de`) in the portal.
- Local and development installs (`.local`, `.test`, `localhost`, IP addresses, or `WP_ENVIRONMENT_TYPE` = `local`) never connect or send statistics.

Lead source tracking:
- The `ref_source` cookie is stored only after analytics consent (WP Consent API, Cookiez banner or `window.kdSubmissionsHasConsent()`), and deleted when consent is withdrawn.
- Fixed: the stored source was overwritten on every page view (expiry was checked as 5 ms instead of 30 days), so internal navigation turned leads into "direct visit". A new UTM or external referrer now replaces the stored source; internal and direct visits keep it.
- Fixed: the tracking script was loaded twice.
- Cookie now uses `SameSite=Lax` and `Secure` on HTTPS.
- New filter `keyd/referral/config` (cookie name and lifetime, consent categories, direct-visit label).

Code quality:
- Request input sanitized and unslashed, database queries prepared, debug logging only when `WP_DEBUG_LOG` is on, aligned with WordPress coding standards.

### 2.1.0
- Added upgrade bootstrap rule so updates from 2.0.3 or 2.0.4 trigger an immediate one-time WHMCS daily sync.

### 2.0.4
- Added realtime WHMCS sync hooks for new submissions and contact clicks
- Added 60-second realtime throttle with aggregation so no event counts are lost
- Added daily reconciliation sync window to keep WHMCS totals aligned with WordPress

### 2.0.3
- Added dynamic mailto/tel click tracking via REST endpoint
- Added email/phone click metrics to dashboard stats and WHMCS sync payloads
- Replaced conversion-rate card with total contact-clicks card and added contact-clicks pie chart

### 2.0.2
- Added chunked backfill with persistent cursor
- Added sync watermark
- Added retry queue
- Added shared batched series payload builder for date ranges

### 2.0.1
- Split and update codebase to increase code quality
- Add integration with ERP system

### 1.2.1
- Completely remove licensing
- Change which is the default page, related links and buttons. Add redirects to previous links
- Add new submissions page. Display a combined list of all unviewed submissions

### 1.1.1
- Add a licensing system to analytics page

### 1.1.0
- Referral system, which shows the referral source in analytics and submission data
- Ability to add custom form names in settings
- Header and footer components with proper script loading, titles and favicon

### 1.0.7
- Add admin bar and admin menu items directing to plugin

### 1.0.6
- Resolve mismatched storage engines
- Resolve mismatched table collation
- Resolve mismatched column types

### 1.0.5
- Changed scripts and styles loading for theme compatabilty

### 1.0.4
- Added the ability to hide and show specific columns
- Improved UX and UI for editing names of columns

### 1.0.3
- Wordpress good practices implmenetation

### 1.0.2
- Added ability for Editor and Shop Manager roles to access `/pieteikumi` and `/pieteikumi/add` pages.
- Enhanced role-based permissions for improved workflow control.

### 1.0.1
- Added primary template loading for `/pieteikumi` and `/pieteikumi/add` pages, overriding any theme templates.
- Clear LiteSpeed cache for `/pieteikumi` and `/pieteikumi/add` pages on plugin activation and deactivation.
- Styling changes for improved usability.

### 1.0
- Initial release with full-featured submission management.
- Dynamic status and comment management.
- Real-time UI updates using AJAX.
- Advanced filtering by form type, statuses, and creation dates.

## Upgrade Notice

### 2.2.1
Security and privacy update: per-site keys replace the shared secret, statistics sharing becomes opt-in, and the lead source cookie is only set after analytics consent. Recommended for all users.

### 2.1.0
When updating from 2.0.3 or 2.0.4, the plugin now runs one immediate one-time WHMCS daily sync automatically.

### 2.0.4
Add realtime WHMCS sync with throttled aggregation and daily reconciliation

### 2.0.3
Add contact click tracking and dashboard visualizations

### 2.0.2
Improve WHMCS submissions sync

### 2.0.1
Split and update codebase to increase code quality, add integration with ERP system

### 1.2.1
Remove licensing, change which is the default page and add new submissions page. Display a combined list of all unviewed submissions

### 1.1.1
Add a licensing system to analytics page

### 1.1.0
Added referral system, ability to add custom form names

### 1.0.8
Added analytics dashboard with charts and statistics, submission date column, and Independent Analytics integration

### 1.0.7
Add admin bar and admin menu items directing to plugin

### 1.0.6
Resolve several mismatches regarding data

### 1.0.5
Fixed theme compatability issues

### 1.0.4
Added the posibilty to hide columns for easier viewing

### 1.0.3
Wordpress good practices implmenetation

### 1.0.2
Enables Editor and Shop Manager roles to access key pages. Role-based permissions have been expanded for better compatibility.

### 1.0.1
Introduces enhanced page template management and automatic LiteSpeed cache clearing for critical pages. Includes minor styling improvements.

### 1.0
This is the first release of the KD Submissions plugin.
