# ATT Consent - Developer Context ## What This Is A WordPress plugin implementing Google Consent Mode v2 with session attribution preservation. It replaces paid CMv2 plugins (e.g., CookieYes) with a self-contained, distributable alternative. ## Architecture ### Core Flow 1. **Inline `` script (priority 1)** - Sets consent defaults and captures attribution to sessionStorage. Must run before any Google tags. 2. **Tracking script (priority 2)** - Loads gtag.js or GTM. In Advanced mode, loads immediately. In Basic mode, deferred until consent. 3. **Footer** - Banner HTML + enqueued `banner.js` and `banner.css`. ### Key Files - `includes/class-frontend.php` - Orchestrates the output order. The `output_consent_defaults()` method generates the critical inline script. - `public/js/consent-manager.js` - Core logic: `AttConsent.update()` replays attribution, sends consent signals, injects scripts, sets cookie. This is the public API. - `public/js/banner.js` - UI only. Calls `AttConsent.update()` on button clicks. - `includes/class-admin.php` - Admin settings with 5 tabs. Handles save via `admin_post`, scripts CRUD via AJAX. - `includes/class-scripts-manager.php` - CRUD for custom JS snippets stored in `{prefix}att_cc_scripts` table. ### Settings Single serialized option: `att_consent_settings`. Access via `ATT_Consent::get_settings()` which merges with defaults. ### Custom Scripts Table ```sql {prefix}att_cc_scripts (id, name, snippet, category, placement, status, priority, created_at, updated_at) ``` Scripts are passed to frontend JS via the inline config object, NOT rendered in PHP (they'd execute before consent). Injected into DOM by `consent-manager.js` after consent. ### Consent Cookie Name: `att_cc_consent`. Value: JSON `{"functional":bool,"analytics":bool,"marketing":bool}`. First-party, SameSite=Lax. ### Attribution Storage sessionStorage key `att_cc_attr` stores referrer, UTMs, GCLID/DCLID on first page of session. Key `att_cc_consent_given` tracks whether attribution has been replayed. Attribution is replayed via `gtag('set')` BEFORE `gtag('consent','update')` so GA4 session_start gets correct source. ## Category-to-Signal Mapping | Category | Google Signals | |----------|---------------| | Necessary | `security_storage` (always granted) | | Functional | `functionality_storage`, `personalization_storage` | | Analytics | `analytics_storage` | | Marketing | `ad_storage`, `ad_user_data`, `ad_personalization` | ## WordPress Hooks **Filters:** `att_consent_settings_save`, `att_consent_banner_html` **Actions:** `att_consent_before_banner`, `att_consent_after_banner` **JS Event:** `att_consent_update` (CustomEvent with `detail: {functional, analytics, marketing}`) ## Coding Standards - WordPress PHPCS (WordPress-Extra) - All admin inputs sanitized: `sanitize_text_field`, `sanitize_hex_color`, `absint`, `wp_kses_post` - Nonce verification on all forms and AJAX - Capability check: `manage_options` for all admin operations - Script snippets stored raw (admin-only input, intentionally executable) - Frontend JS is vanilla - no jQuery dependency - Text domain: `att-consent` ## Testing Activate plugin, enter a GA4 Measurement ID in General settings, visit frontend. Verify: - `window.dataLayer` contains consent default with `wait_for_update` - Clicking Accept All fires `gtag('consent','update')` with all granted - Cookie `att_cc_consent` is set - Return visit: no banner shown, consent applied from cookie - Attribution test: visit with `?utm_source=test`, navigate without consenting, consent on page 2, check GA4 DebugView for correct source ## Environment - WordPress 6.8.3, Astra child theme - Local Sites development environment - WooCommerce + LearnPress site - Previously used CookieYes (`cookie-law-info` plugin)