Skip to content

v1.5.0 — Security hardening, first/last-touch attribution, lead delivery reliability

Choose a tag to compare

@CCDevelopment CCDevelopment released this 13 Sep 17:28
· 1 commit to master since this release

Security

  • Attribution cookies are no longer trusted. Values are type-checked, length-capped and sanitized before use; the marketing channel is recomputed server-side. Garbage or oversized cookies are ignored.
  • Leads endpoint locked down. Must be HTTPS on an approved host (dashboard.progressiodev.com; extend with the ppt_allowed_lead_hosts filter or the PPT_LEADS_ENDPOINT constant). Requests go through wp_safe_remote_post(), closing the SSRF / exfiltration path.
  • Lead contact fields validated (is_email, phone digit check, length caps). API key never rendered into the settings page and is also sent as Authorization: Bearer.
  • Stored page URLs keep only the path and marketing parameters — never full query strings. Cookies carry Secure on HTTPS. Measurement ID validated against G-XXXXXXXXXX.
  • Added uninstall.php (removes options, queue, cron) and directory index.php guards. Settings sanitizer no longer fatals on non-array input and works from WP-CLI/REST.

Added

  • First-touch attribution in a first-party cookie (configurable window, default 90 days) alongside per-session last touch, with a stable visitor ID. Both are sent on every GA4 event (first_* / traffic_*) and every lead.
  • Channel classification (traffic_channel, first_channel) mirroring GA4's default channel grouping. Added msclkid, ttclid, li_fat_id, dclid.
  • Lead field mapping (Settings → Lead Field Mapping) to pin name/email/phone/message fields per form; improved label heuristics as the fallback. message is now captured.
  • Confirmed lead delivery with a WP-Cron retry queue (5 attempts, backoff). Status panel shows last sent / last error / queue size with "Send test lead" and "Retry queued leads" buttons.
  • GA4 generate_lead fires once the Leads API accepts a lead, carrying the dashboard's lead_id.
  • data-ppt-cta / data-ppt-label attributes as an alternative to CSS classes; file_download and video_start / video_progress / video_complete events (YouTube, Vimeo, HTML5).
  • Status panel: Measurement ID check, duplicate-gtag detection (Site Kit, MonsterInsights, ExactMetrics, GTM4WP), detected form plugins.
  • WP-CLI: wp ppt status | test-lead | queue | get | set.
  • PPT_LEADS_API_KEY, PPT_LEADS_ENDPOINT, PPT_MEASUREMENT_ID constants; ppt_settings, ppt_lead_payload, ppt_tracker_config, ppt_download_extensions filters.
  • Lead payload adds channel, firstTouch, lastTouch, visitorId, submissionId, contactHash, ipHash, userAgent, formPlugin, isSpam/spamScore, pluginVersion.

Fixed

  • Google Ads auto-tagged landings (gclid with no UTMs) were never attributed.
  • Sites on www. reported their own internal navigation as a referral source.
  • form_submit double-counted in Auto mode (generic fallback fired alongside the plugin-specific success event) and counted search/login/comment forms.
  • landingPage in lead payloads was the submitting page, not the landing page; pageUrl now carries the submitting page.
  • Contact Form 7 checkbox fields produced "Array". Fluent Forms current fluentform/submission_inserted hook supported.
  • Events fired before gtag.js finished loading were dropped; they now queue in dataLayer.

Upgrade notes

  • Requires WordPress 5.9 / PHP 8.0 (the code already depended on str_contains).
  • form_submit volume on Auto-mode sites will drop to roughly half on upgrade — that was the double count. Annotate your GA4 property on the deploy date.
  • traffic_source / traffic_medium now describe the last non-direct touch (falling back to first touch), matching GA4's own convention. New first_* and traffic_channel / first_channel parameters need registering as custom dimensions — run scripts/ga4-setup/create-custom-dimensions.js.
  • The dashboard must accept the new payload keys (deployed 13 Sep 2026). Until it returns an id, generate_lead fires without lead_id.