Changelog ======== = 1.3.7 = * **Sessions (dedicated SessionManager)**: Decoupled session tracking from attribution signal detection. Sessions are now managed by a standalone `SessionManager` module with a 30-minute inactivity timeout (Stape/GA4 model), independent of UTM or click-ID changes. `session_count` inside `runAttribution()` is no longer incremented on attribution signals — session lifecycle is driven purely by user activity. * **Sessions (separate storage)**: Session state (`session_id`, `session_number`, `session_started_at`, `last_activity_at`) is persisted in its own `ct_session` cookie and localStorage key, keeping attribution and session concerns fully separated. * **Sessions (backward compatibility)**: On first run the SessionManager seeds `session_number` from the existing `session_count` in the attribution payload, then stops writing to attribution storage. `session_count` remains available as an alias of `session_number` in all outward-facing payloads (dataLayer, API, REST, form/purchase dispatch). * **Sessions (API surface)**: Added `window.ClickTrail.getSession()` and `window.ClickTrailSession` for client-side access. `Identity.get()` now returns `session_number` alongside `session_id`. The dataLayer `ct_page_view` push includes `session_number`. * **Sessions (server-side)**: Added `Attribution_Provider::get_session()` to read the `ct_session` cookie server-side. Form submission and purchase dispatch contexts now include `session_id` in event metadata when available. * **Sessions (consent)**: Session state is cleared alongside attribution data when consent is denied or revoked, and the `clearData()` API method clears both stores. = 1.3.6 = * **Forms (Ninja Forms)**: Replaced the speculative Ninja Forms storage path with an explicit submission-extra contract on `extra.clicktrail_attribution`, added normalized payload handling with safe fallback to the current request attribution payload, and surfaced stored attribution in the Ninja Forms submission detail UI through `nf_react_table_extra_value_keys`. * **Forms (Elementor Forms)**: Added a native Elementor Pro forms adapter using the official `elementor_pro/forms/new_record` submission hook. ClickTrail now logs Elementor form submissions on the same adapter contract as the other supported form plugins, reads submitted `ct_*` attribution fields when present, and falls back to the current consent-aware attribution payload when explicit hidden fields are not part of the form. * **Attribution coverage (modern campaign + browser IDs)**: Expanded the capture schema beyond classic UTMs so ClickTrail now preserves `utm_id`, `utm_source_platform`, `utm_creative_format`, and `utm_marketing_tactic`, plus top-level browser/platform identifiers such as `fbc`, `fbp`, `ttp`, `li_gc`, `ga_client_id`, and `ga_session_id`. The same broader field set now flows through the runtime, browser events, WooCommerce checkout persistence, canonical URL cleanup, and cross-domain attribution token allowlists where appropriate. * **Browser events (capability gating)**: Split browser event collection from browser delivery transport. `event_v2` now acts as the single capability gate for loading and booting `clicutcl-events.js`, while REST delivery remains a separate transport concern. Disabling browser event collection now stops browser event listeners and `dataLayer` pushes from the events runtime without affecting attribution capture. * **Consent (frontend attribution parity)**: Switched the attribution runtime to the shared consent bridge contract instead of hardcoding the legacy `ct_consent` cookie and banner-only events. Cookiebot, OneTrust, Complianz, GTM, and custom bridge integrations now unblock attribution correctly when consent is granted. * **Privacy / retention (client storage)**: Replaced indefinite localStorage attribution persistence with a TTL-bound mirror that honors `cookie_days`, drops legacy no-expiry payloads, and clears client-side attribution state when consent is denied or revoked. * **Attribution schema (metadata consistency)**: Standardized attribution metadata on the same `ft_` / `lt_` prefix contract used by the rest of the payload. The runtime and PHP provider now normalize legacy `first_*` / `last_*` metadata aliases back to canonical keys such as `ft_touch_timestamp` and `ft_landing_page`, and the form injector now targets the canonical metadata fields consistently. * **Identity enrichment (forms and purchases)**: Added consent-aware identity resolution to form submission and WooCommerce purchase dispatch paths. Server-side form and purchase events now carry the same top-level `identity` payload used by REST intake, with a temporary `meta.identity` mirror kept for backward compatibility with older collectors. * **Forms (Fluent Forms — hooks)**: Registered both slash-style (`fluentform/form_element_start`, `fluentform/submission_inserted`) and underscore-style legacy hooks so the adapter fires on Fluent Forms v5+ and on installations still running v4 or below. A static dedup guard in `on_submission` ensures the entry is logged exactly once even if both aliases fire. * **Forms (Fluent Forms — meta persistence)**: Implemented the previously commented-out Fluent Forms entry meta write. Attribution values are now inserted into `fluentform_submission_meta` via `wpFluent()` on each submission, making them accessible from the Fluent Forms entry detail view and its API. The insert is wrapped in a try/catch so a table-level error does not block ClickTrail's own event log. * **Forms (Gravity Forms — entry meta registration)**: Added `gform_entry_meta` filter registration in the Gravity Forms adapter. Each attribution key (prefixed `ct_`) is now declared as a named meta entry, making attribution values visible in the Gravity Forms entry detail screen, exportable via the CSV/XLSX export tool, and searchable in the entries list — matching the behaviour of first-class Gravity Forms fields. * **Admin (Diagnostics — copy)**: Renamed "Recent v2 Intake Events" card to "Recent Event Intake" and updated its description and empty-state text to remove internal "v2" terminology from user-facing diagnostic output. * **Admin CSS (settings app utilities)**: Added `.clicktrail-setting-block` (with `.is-disabled` opacity state), `.clicktrail-setting-label` (inline-flex label layout), `.clicktrail-provider-block` (provider row separator), `.clicktrail-ops-links` (action link row), and `.clicktrail-diagnostics-grid--compact` (inset grid variant) to support the unified settings app layout. = 1.3.5 = * **Admin UX (final unified settings app)**: Replaced the split Settings API + separate advanced tracking UI with one modern WordPress-native settings shell for the main ClickTrail settings screen. * **Admin IA (capability tabs)**: Reorganized settings into four capability-based tabs -- `Capture`, `Forms`, `Events`, and `Delivery` -- so users can configure ClickTrail by use case instead of internal implementation layers. * **Admin copy (humanized language)**: Removed user-facing `Tracking v2` terminology from the main settings flow and translated developer-first labels into product-facing language. * **Admin compatibility (legacy URLs)**: Added alias routing for old admin tabs so `general`, `whatsapp`, `trackingv2`, `advanced`, `server`, and `destinations` continue to land in the correct new capability tab. * **Admin persistence (grouped save layer)**: Added unified admin AJAX load/save endpoints that group settings by capability in the UI while still writing back to the existing option stores. * **Admin UX (delivery summary)**: Added a lightweight Delivery health summary inside Settings with queue backlog, last dispatch, last error, debug state, and direct links to Logs and Diagnostics. * **Admin UX (unified identity)**: Replaced `wp.components` Card/CardBody/CardHeader in the Advanced tab React UI with the same `.clicktrail-card` shell used by all PHP-rendered settings tabs — eliminating the two-identity split. * **Admin UX (tab consolidation)**: Reduced settings tabs from six to four — Attribution (core capture + JS fallback + cross-domain + WhatsApp), Consent, Destinations, and Advanced — each organized around a clear user intent rather than internal system names. * **Admin UX (WhatsApp)**: Moved WhatsApp settings from a standalone tab into a collapsible card on the Attribution tab, where it belongs alongside the other capture settings it shares an option group with. * **Admin UX (Destinations tab)**: Destinations tab now presents GTM, server-side delivery, and advertising platform toggles (Meta, Google, LinkedIn, Reddit, Pinterest) as a single unified configuration surface — two PHP forms followed by the React v2 destinations card. * **Admin UX (humanized v2 notice)**: Replaced the generic "advanced tracking" notice with a plain-language explanation of why the Advanced tab exists and when it is needed, removing the term "v2" from user-facing copy. * **Admin UX (tab icons)**: Updated tab icons to reflect each tab's purpose — chart-area for Attribution, privacy shield for Consent, share for Destinations, admin-tools for Advanced. * **Admin JS (React card shell)**: Rewrote `admin-tracking-v2.js` to render cards using our `.clicktrail-card` / `.clicktrail-card__body--react` CSS classes, with icon + title + description in the header matching PHP-rendered cards exactly. * **Admin JS (React controls)**: Gave each card a contextual icon, humanized title, and plain-English description. Feature flags card explains each flag inline via `help` text. * **Admin CSS**: Added `.clicktrail-card__body--react` padding, row separators, and overrides for `wp.components` ToggleControl, TextControl, and TextareaControl to match our design tokens (border radius, border colour, blue focus ring, toggle pill sizing). = 1.3.4 = * **Admin UX (tab navigation)**: Renamed all settings tabs to plain-English labels — Attribution, Consent, Channels, Destinations, Advanced, Diagnostics — replacing internal developer slugs. * **Admin UX (tab consolidation)**: Merged GTM and Server-side tabs into a single Destinations tab, reducing tab count and grouping related delivery settings together. * **Admin UX (card layout)**: Replaced flat settings sections with a card-based layout — each card carries an icon, title, and description, with a hairline border and white background matching WP admin conventions. * **Admin UX (status bar)**: Added a summary status bar on the Attribution tab showing live pills for Attribution, Consent Mode, JS Capture, Cross-domain, and Server-side states. * **Admin UX (sticky save)**: Added a sticky save bar that remains visible at the bottom of the viewport while scrolling through long settings pages. * **Admin UX (collapsible cards)**: Advanced sections (Cross-domain, Channels) can be collapsed to reduce visual noise; collapsed state driven by `aria-expanded` and a CSS `is-collapsed` toggle. * **Admin UX (conditional dimming)**: Dependent fields dim and disable when their parent toggle is off — JS injection controls mutation observer and field overwrite rows; link decoration controls allowed domains, skip-signed, and cross-domain token; WhatsApp controls the append-attribution row; consent toggle controls all consent sub-fields. * **Admin UX (diagnostics)**: Redesigned Diagnostics page with a stats-first grid (Queue Backlog, Last Dispatch, Last Error, Debug Logging) followed by action cards for testing, logging, data management, and telemetry. * **Admin UX (field labels)**: Rewrote all settings field labels in plain English throughout Attribution and Consent tabs. * **Admin UX (destinations card)**: Tracking v2 Destinations card (Meta, Google, LinkedIn, Reddit, Pinterest) now renders on the Destinations tab in addition to the Advanced tab. * **Admin JS**: Added `admin-settings.js` to handle collapsible card toggle behaviour and all conditional field dependency bindings on settings screens. * **Admin CSS**: Comprehensive stylesheet additions covering cards, status pills, save bar, diagnostic stat tiles, dimmed rows, field inputs, and responsive breakpoints. = 1.3.3 = * **Admin reliability**: Fixed `clicutcl_attribution_settings` persistence so checkbox/toggle values on the settings page now save correctly alongside scalar fields like `enable_attribution` and `cookie_days`. * **Forms integration**: Fixed Fluent Forms hook registration for `fluentform_form_element_start` to accept the documented single argument, preventing fatal errors on form render. * **Security (API hardening)**: Added request body-size guards (128KB) on public webhook and lifecycle endpoints to prevent oversized payload abuse (HTTP 413 on overflow). * **Security (authz)**: Closed batch endpoint nonce bypass by requiring `manage_options` capability on the wp_rest nonce path. * **Security (XSS)**: Replaced consent-banner `innerHTML` rendering with safe DOM API construction to eliminate DOM XSS sinks in active consent UI. * **Security (legacy exposure)**: Removed deprecated `assets/js/ct-consent.js` from runtime and added ignore rules to prevent accidental reintroduction. * **Security (secrets hygiene)**: Implemented masked admin reads and write-only secret updates for tracking v2 settings (`secret`/`token` fields are no longer exposed back to admin clients). * **Security (optional at-rest protection)**: Added optional secret encryption-at-rest for tracking settings (`security.encrypt_secrets_at_rest`) with transparent decrypt-on-read. * **Privacy (data minimization)**: Replaced raw WordPress user IDs in dataLayer payloads with salted one-way SHA-256 hashes. * **Privacy (WP compliance)**: Added personal data exporter/eraser integration for ClickTrail tracking data via WordPress privacy APIs. * **Consent (runtime architecture)**: Added consent bridge layer (`clicutcl-consent-bridge.js`) to normalize consent resolution across built-in banner, CMPs, GTM Consent Mode, and custom implementations. * **Consent (event gating)**: Updated event initialization to wait for resolved consent and added dispatch-time guard to block event pushes when consent is denied/unresolved. * **Consent (admin controls)**: Added consent source and CMP timeout settings, with sanitization and localized runtime bridge configuration. * **GTM behavior**: Preserved unconditional GTM snippet loading while aligning ClickTrail event initialization with resolved consent signals. * **Attribution integrity**: Hardened attribution token flows and canonical click-ID normalization (including Snapchat aliases to canonical `sccid` handling). * **Attribution coverage**: Aligned click-ID handling across parsing/mapping paths for Google, Meta, TikTok, Microsoft, Twitter/X, LinkedIn, Snapchat aliases, and Pinterest identifiers. * **WooCommerce logic**: Fixed fallback attribution path so flat-cookie attribution is normalized into first/last touch before purchase payload flattening. * **Forms integration**: Corrected Ninja Forms attribution global usage to `window.ClickTrail` API. * **Admin UX**: Replaced dead PII warning CTA with actionable links to diagnostics/settings. * **Internationalization**: Replaced hardcoded admin error strings with translatable strings for consistency with WP i18n conventions. * **Technical debt (modularization)**: Reduced blast radius by splitting oversized classes into bounded-context traits (admin pages/diagnostics, tracking controller security/debug/token internals, log controller WA/runtime internals). * **Technical debt (legacy cleanup)**: Removed deprecated runtime integration class (`includes/integrations/class-form-integrations.php`) and updated ignore policy for archived artifacts. * **Standards (boolean coercion fix)**: Fixed toggle sanitization so string values like `"false"` no longer coerce to enabled. * **Standards (style consistency)**: Refactored `class-site-health.php` to consistent WordPress/PSR-friendly formatting and safer input handling patterns. * **Standards (enforcement)**: Added `phpcs.xml.dist`, typing policy documentation, and QA script to enforce consistent repository typing policy. * **Docs hygiene**: Removed duplicated Portuguese section in `README.md` to prevent documentation drift. * **Docs truth-alignment**: Updated `readme.txt` claims to match shipped click-ID and consent-mode behavior exactly. = 1.3.2 = * **Security**: Enforced signed-token authorization for WA click ingestion, removed Origin/Referer as a security control, and added trusted-proxy-aware client IP handling. * **Security**: Closed WA ingestion bypass paths and aligned authorization checks across endpoints. * **Performance**: Removed hot-path option churn for WA diagnostics and moved attempt/dispatch traces to debug-only transient ring buffers. * **Performance**: Eliminated per-request schema checks on the WA hot path with DB readiness flags and fail-fast handling when DB is not ready. * **Reliability**: Added canonical click-ID normalization boundary (`lt_/ft_` to canonical IDs) before allowlist/signing flow. * **Reliability**: Hardened settings sanitization with schema+merge behavior to prevent silent setting loss on partial saves. * **Admin UX/Perf**: Scoped admin script loading to relevant screens instead of global wp-admin enqueue. * **Polish**: Escaped DB-derived admin table output (`created_at`) and standardized safe output rendering. * **Developer Experience**: Added debug-gated JS logging to avoid production console noise by default. * **API**: WA endpoint contract now requires a signed `token` for accepted writes. * **Internal**: Diagnostics storage now uses transient ring buffers instead of hot-path option-array rewrites. * **Internal**: Added hardening config surfaces for token TTL, nonce replay limits, trusted proxies, and diagnostics buffering/throttling. = 1.3.1 = * **Performance**: Implemented conditional loading for `clicutcl-events.js` tracking script—now only loads on the front-end (excluding feeds, robots, and admin) to minimize overhead. * **Security (Safety Check)**: Added existence check for `WooCommerce` class before instantiating the integration, preventing potential hooks from loading unnecessarily. * **Improvement (Extensibility)**: Introduced `clicutcl_should_load_events_js` filter to allow granular control over when tracking scripts are enqueued. = 1.3.0 = * **Feature (Cache Resurrection)**: Implemented Client-Side Field Injection (`enable_js_injection`) to automatically populate hidden form fields via JavaScript, ensuring accurate attribution even on fully cached pages (WP Rocket, Cloudflare, local caching). * **Feature (Cross-Domain)**: Introduced Link Decoration (`enable_link_decoration`) to safely pass attribution parameters to allowed domains, with automatic support for all subdomains of the current site. * **Feature (Bot Protection)**: Added advanced bot detection to prevent attribution pollution from crawlers, webdrivers, and headless browsers. * **Feature (DX/Insight)**: Integrated with WordPress Site Health to provide proactive diagnostics on caching conflicts and cookie blocking. * **Feature (Dashboard)**: Added "ClickTrail Status" dashboard widget for real-time tracking health visibility. * **Improvement**: Added JS Fallback for WooCommerce Checkout, ensuring order attribution is captured even when server-side cookies are stripped. * **Improvement**: Renamed the primary settings submenu from "ClickTrail" to "Settings" to eliminate duplicate labels and improve UX. * **Improvement**: Added official Portuguese (Brazil) translation (`pt_BR`) covering Admin, Consent Banner, and Site Health. * **Improvement**: Fully refactored attribution frontend to remove jQuery dependency and expose a modern JS API (`window.ClickTrail`). = 1.2.3 = * **Fix**: Fixed Short Description formatting in readme.txt to comply with WordPress.org plugin guidelines. * **Improvement**: Removed deprecated `load_plugin_textdomain()` call—WordPress 4.6+ handles translations automatically for plugins hosted on WordPress.org. * **Improvement**: Added PHPCS ignore comment for intentional direct database query on custom plugin table. = 1.2.2 = * **Fix**: Resolved critical autoloading issues on Linux/Unix environments (case-sensitive paths) to prevent Fatal Errors during activation. * **Fix**: Implemented strict PHP interface compatibility for all Form Adapters (CF7, WPForms, Gravity Forms, Ninja Forms, Fluent Forms) to resolve fatal errors on PHP 8+. * **Fix**: Added robust "preflight" checks in the boot sequence to safely deactivate the plugin if files are corrupted or missing, instead of crashing the site. * **Improvement**: Enhanced autoloader performance and added fallback for mixed naming conventions. * **Improvement**: Updated plugin metadata and readme for better WordPress.org validation compliance. = 1.2.1 = * **Fix**: Fixed scroll tracking to use GTM's built-in variable names (`gtm.scrollThreshold`, `gtm.scrollUnits`, `gtm.scrollDirection`) instead of custom Data Layer Variables, making GTM setup simpler and more reliable. * **Fix**: Fixed scroll percentage calculation bug that prevented scroll events from firing. Changed from string-based property access to direct property access with cross-browser fallbacks for better reliability. * **Improvement**: Renamed `time_on_page` event to `user_engagement` with descriptive engagement levels (quick_view, browsing, engaged, interested, highly_engaged) and added detailed parameters (`engagement_time_msec`, `time_label`, `time_threshold`) for better analytics insights. * **Fix**: Corrected typo in settings class name (`Attribution_Settings`) for consistency. * **Docs**: Updated readme.txt and README.md with benefit-focused messaging emphasizing ROI and business value over technical features. = 1.2.0 = * **Security**: Hardened AJAX handlers with strict WhatsApp URL validation and optimized PII risk logging using nonce verification and state checks. * **Feature**: Introduced Custom Database Table (`wp_clicutcl_events`) for scalable event logging, removing reliance on Custom Post Types. * **Feature**: Implemented REST API Log Endpoint (`/wp-json/clicutcl/v1/log`) for faster and lighter tracking requests. * **Feature**: Added Admin Log Viewer (`ClickTrail > Logs`) to view events from the custom database table. * **Feature**: Implemented Automated Database Cleanup (Cron) to keep the events table healthy. * **Refactor**: Major architectural improvements including Namespaced Admin class, decoupled AJAX Log Handler, and extracted CPT registration. * **Refactor**: Standardized Integrations (WooCommerce & Forms) into namespaced classes (`CLICUTCL\Integrations`), cleaning up the global namespace and dependencies. * **Refactor**: Centralized settings logic (`Attribution_Settings`) and Attribution Utilities (`Utils\Attribution`) for better maintainability. * **Fix**: Fixed GTM Data Layer variables for Scroll Tracking—now uses GTM's built-in variable names (`gtm.scrollThreshold`, `gtm.scrollUnits`, `gtm.scrollDirection`) plus `percent_scrolled` for GA4 compatibility. No custom Data Layer Variables needed in GTM! * **Fix**: Fixed scroll percentage calculation bug that prevented events from firing. Changed from string-based property access to direct property access with cross-browser fallbacks. * **Fix**: Improved engagement tracking by renaming `time_on_page` event to `user_engagement` with descriptive engagement levels (quick_view, browsing, engaged, interested, highly_engaged) and added `engagement_time_msec`, `time_label`, and `time_threshold` parameters. * **Cleanup**: Removed legacy `clicutcl_wa_click` Custom Post Type and associated AJAX handlers. * **Cleanup**: Removed `CLICUTCL\Ajax\Log_Handler` and `CLICUTCL\Post_Types\WhatsApp_Click` classes. = 1.1.1 = * Refreshed readme copy and release guidance to align WordPress.org listing with latest documentation. * Prepared for updated screenshots/assets to keep plugin visuals accurate. = 1.1.0 = * Added comprehensive Event Tracking (Searches, Downloads, Scroll Depth, Time on Page). * Added Server-side Event Tracking for User Login, Signups, and Comments. * Implemented Google Consent Mode v2 support with region-specific defaults. * Added manual Google Tag Manager (GTM) Container ID injection. * Refactored codebase for better modularity and performance. * Enhanced WooCommerce integration with "Source" column and detailed meta box. = 1.0.0 = * Initial release with attribution capture, consent banner, and integrations for WooCommerce, Contact Form 7, Fluent Forms, and WhatsApp.