Files
att-consent/CLAUDE.md
Steve Hanlon 6bf9f553de Initial commit: ATT Consent plugin v1.0.0
Google Consent Mode v2 cookie consent plugin with session attribution
preservation, custom script management, and gtag.js/GTM support.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 05:45:42 +00:00

3.7 KiB

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 <head> 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

{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.

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)