Skip to content

Global GDPR opt-in by default with consent refactor and HubSpot/PostHog hardening#4611

Merged
knolleary merged 5 commits intomainfrom
yndira/remove-region-consent
Feb 27, 2026
Merged

Global GDPR opt-in by default with consent refactor and HubSpot/PostHog hardening#4611
knolleary merged 5 commits intomainfrom
yndira/remove-region-consent

Conversation

@Yndira-E
Copy link
Contributor

@Yndira-E Yndira-E commented Feb 27, 2026

Description

This PR makes GDPR-style consent the default for all users globally (no region-based branching), aligns tool behavior with consent categories, and simplifies consent handling to reduce duplication and improve reliability.

What Changed

1) Global GDPR default consent

  • Set default consent to denied for non-essential storage categories across all regions.
  • Keep security_storage granted.
  • Preserve stored user preferences via cc_cookie on returning visits.

2) Consent flow refactor (CookieConsent)

  • Refactored consent logic into reusable helpers:
    • applyAnalyticsConsent(...)
    • applyAdsConsent(...)
    • applyFunctionalConsent(...)
    • pushGtmJsEvent()
  • Updated callback responsibilities:
    • onConsent: idempotent sync on page load (no consent event emission, no GTM repush).
    • onFirstConsent: first explicit user decision handling (state transitions + events).
    • onChange: subsequent preference changes only.

3) HubSpot alignment with consent categories

  • HubSpot runtime (hs-script-loader) is now gated under analytics.
  • Meetings embed and chat widget activation are handled under analytics consent.
  • Added robust HubSpot revocation on analytics withdrawal:
    • _hsq.push(['doNotTrack'])
    • _hsp.push(['revokeCookieConsent'])
    • fallback manual cookie cleanup for HubSpot cookies across host/root domains.
  • Fixed HubSpot privacy listener mapping:
    • consent.categories.functionality now reflects actual CookieConsent state (no forced true).

4) PostHog withdrawal hardening

  • On analytics withdrawal, keep:
    • posthog.opt_out_capturing()
    • posthog.reset()
    • posthog.set_config({ persistence: 'memory' })
  • Added explicit cleanup for PostHog cookies and storage keys to ensure withdrawal is enforced.

5) Cookie cleanup safety net

  • Added autoClear rules in CookieConsent for analytics category, covering:
    • Google Analytics cookies
    • HubSpot cookies
    • PostHog cookies
    • Warmly cookies

6) Consent copy updates

  • Updated consent modal text to match real behavior:
    • HubSpot meetings and chat are described under analytics.
  • Updated meetings fallback placeholder copy to request Analytics cookies.

Why

  • Enforce GDPR-compliant opt-in defaults globally.
  • Ensure behavior matches declared consent categories.
  • Improve withdrawal reliability (especially for third-party tools with sticky cookies).
  • Reduce duplicated logic and make consent handling easier to maintain.

Next steps (follow-up PR)

To make consent updates fire tags immediately without page reload for the LinkedIn tag( and avoid per-vendor code changes), we should standardize GTM triggering with a generic consent event model:

  1. Push generic events from the site when consent is granted/changed, e.g.:

    • ff_consent_update (always on change, with payload)
    • optional category-specific aliases (ff_ads_consent_granted, etc.) only if needed.
  2. In GTM, create reusable Custom Event triggers (once), then reuse them across tags:

    • Trigger: Custom Event = ff_consent_update
    • Optional conditions by consent category/values (from dataLayer payload).
  3. Keep each tag’s Additional Consent Checks (analytics_storage, ad_storage, etc.) as the hard gate.

This removes the need to create one-off triggers per tool and keeps tag onboarding scalable for non-engineering teams.

Related Issue(s)

Checklist

  • I have read the contribution guidelines
  • I have considered the performance impact of these changes
  • Suitable unit/system level tests have been added and they pass
  • Documentation has been updated
  • For blog PRs, an Art Request has been created (instructions)

@netlify
Copy link

netlify bot commented Feb 27, 2026

Deploy Preview for flowforge-website ready!

Name Link
🔨 Latest commit c935605
🔍 Latest deploy log https://app.netlify.com/projects/flowforge-website/deploys/69a1bab5e9b8e70008bcaa12
😎 Deploy Preview https://deploy-preview-4611--flowforge-website.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
Lighthouse
Lighthouse
1 paths audited
Performance: 89 (🟢 up 26 from production)
Accessibility: 81 (no change from production)
Best Practices: 100 (🟢 up 8 from production)
SEO: 91 (no change from production)
PWA: -
View the detailed breakdown and full score reports

To edit notification comments on pull requests, go to your Netlify project configuration.

@netlify
Copy link

netlify bot commented Feb 27, 2026

Deploy Preview for flowforge-website ready!

Name Link
🔨 Latest commit 0f61d8a
🔍 Latest deploy log https://app.netlify.com/projects/flowforge-website/deploys/69a1ce54429f2f00087915a3
😎 Deploy Preview https://deploy-preview-4611--flowforge-website.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
Lighthouse
Lighthouse
1 paths audited
Performance: 90 (🟢 up 27 from production)
Accessibility: 81 (no change from production)
Best Practices: 100 (🟢 up 8 from production)
SEO: 91 (no change from production)
PWA: -
View the detailed breakdown and full score reports

To edit notification comments on pull requests, go to your Netlify project configuration.

@Yndira-E
Copy link
Contributor Author

cc @UnicornGunnerz for visibility

@knolleary knolleary merged commit 2db603e into main Feb 27, 2026
7 checks passed
@knolleary knolleary deleted the yndira/remove-region-consent branch February 27, 2026 17:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants