Skip to content

Cookie Consent: classic-theme fallback for required Privacy/CCPA/Manage-Preferences links#49854

Open
chihsuan wants to merge 5 commits into
trunkfrom
wooa7s-1564-cookie-consent-classic-theme-fallback-for-required
Open

Cookie Consent: classic-theme fallback for required Privacy/CCPA/Manage-Preferences links#49854
chihsuan wants to merge 5 commits into
trunkfrom
wooa7s-1564-cookie-consent-classic-theme-fallback-for-required

Conversation

@chihsuan

@chihsuan chihsuan commented Jun 23, 2026

Copy link
Copy Markdown
Member

Fixes # WOOA7S-1564

Proposed changes

Why: Privacy Policy / CCPA "Do Not Sell" / GDPR "Manage Privacy Preferences" links are injected only via Block Hooks into a core/navigation block in a footer template part. Classic themes and block themes with no footer nav get nothing, and the CCPA link is legally required to be conspicuous, so this is a legal gap.

How: A wp_footer fallback renders the floating control, but only when Block Hooks injection didn't run for this response. Dedup uses a server-side "did-inject" flag set by a render_block_core/navigation-link callback. The footer template part renders before wp_footer, so the flag is authoritative.

Why a floating control (not inline injection): Classic themes have no standardized footer region/hook to target the way Block Hooks gives us on block themes, so generic inline injection isn't feasible. A fixed-corner floating control is theme-independent, guarantees the links are present, and is the same pattern popular consent plugins already use.

Region gating (cache-safe): Mirrors the nav-link gating and goes one step further to gate the whole control:

What:

  • maybe_render_footer_links_fallback() (wp_footer, registered in init()) — gated by the inject flag + a visibility check (skips admin / 404 / previews).
  • mark_footer_links_injected() render filter — flips the inject flag for all three links.
  • footer-links-fallback.php — accessible <button> toggle (aria-haspopup/aria-expanded/aria-controls) + the three links; the container and region-specific links render hidden.
  • Interactivity: state.showFallbackControl, context-local fallbackExpanded toggle, Escape-to-close with focus return; reuses the jetpack/cookie-consent store, no new global state.
  • Styles for the fixed control (focus-visible, reduced-motion, print-hidden).

Related product discussion/links

Does this pull request change what data or activity we track or use?

No new data is tracked. The "Manage Privacy Preferences" control reuses the existing consent events already fired by the nav-link version.

Testing instructions

Setup:

  • Use a site with the premium-analytics plugin active (it calls Cookie_Consent::init()), plus the WP Consent API plugin (wp-consent-api) active — the latter is required for the consent banner/modal to function (window.wp_set_consent); without it the "Manage Privacy Preferences" control cannot open the modal.
  • Set a published Privacy Policy page (Settings → Privacy). The CCPA "Your Privacy Choices" page is auto-created on init.
  • To simulate a region, set the geolocation cookies (when both are present the client skips the geo API and uses them; 6-hour TTL). In DevTools → Application → Cookies (or the console), set country_code and region: CCPA → country_code=US, region=CA; GDPR → country_code=FR, region= (any value). Reload after changing.

Classic theme (e.g. Twenty Twenty-One):

  • CCPA region: a fixed "Privacy" control appears at the bottom-left. Expand it → Privacy Policy, Your Privacy Choices, and (after consent is set) Manage Privacy Preferences.
  • GDPR region: once consent is saved (banner dismissed), the control appears with Privacy Policy and Manage Privacy Preferences.
  • Neither region: the floating control does not appear (its only link would be Privacy Policy, already reachable in the footer).
  • Click Manage Privacy Preferences → the consent preferences modal opens.
  • Keyboard: Tab to the toggle, Enter/Space opens the panel, Escape closes it and returns focus to the toggle.

Block theme with a footer navigation (e.g. Twenty Twenty-Four):

  • The links are injected into the footer navigation and the floating control does not appear (no duplication).

Important

Note: this PR adds the classic-theme fallback rendering. Broader cross-theme polish (contrast across theme palettes, CSS isolation, aligning the z-index with the monorepo's 50000+ convention) is tracked in WOOA7S-1545; the styling here is intentionally minimal.

CCPA:

Screenshot 2026-06-23 at 5 01 57 PM

GDPR:

Screenshot 2026-06-23 at 5 03 24 PM

@chihsuan chihsuan added the [Status] Needs Review This PR is ready for review. label Jun 23, 2026
@chihsuan chihsuan self-assigned this Jun 23, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Thank you for your PR!

When contributing to Jetpack, we have a few suggestions that can help us test and review your patch:

  • ✅ Include a description of your PR changes.
  • ✅ Add a "[Status]" label (In Progress, Needs Review, ...).
  • ✅ Add testing instructions.
  • ✅ Specify whether this PR includes any changes to data or privacy.
  • ✅ Add changelog entries to affected projects

This comment will be updated as you work on your PR and make changes. If you think that some of those checks are not needed for your PR, please explain why you think so. Thanks for cooperation 🤖


Follow this PR Review Process:

  1. Ensure all required checks appearing at the bottom of this PR are passing.
  2. Make sure to test your changes on all platforms that it applies to. You're responsible for the quality of the code you ship.
  3. You can use GitHub's Reviewers functionality to request a review.
  4. When it's reviewed and merged, you will be pinged in Slack to deploy the changes to WordPress.com simple once the build is done.

If you have questions about anything, reach out in #jetpack-developers for guidance!

@jp-launch-control

Copy link
Copy Markdown

Code Coverage Summary

This PR did not change code coverage!

That could be good or bad, depending on the situation. Everything covered before, and still is? Great! Nothing was covered before? Not so great. 🤷

Full summary · PHP report

chihsuan added 2 commits June 23, 2026 15:52
…gion

Mirror the Block Hooks nav-link gating so the classic-theme fallback only
shows Manage Privacy Preferences in GDPR regions after consent is set,
instead of unconditionally to all visitors worldwide.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a classic-theme (and “no footer nav” block-theme) fallback so the required Privacy Policy / CCPA opt-out / “Manage Privacy Preferences” links are still rendered when Block Hooks injection into a footer core/navigation doesn’t occur, avoiding silent omission of legally required links.

Changes:

  • Add a wp_footer fallback renderer gated by a server-side “did inject” flag set during render_block_core/navigation-link.
  • Add a new footer-links fallback template with Interactivity API bindings (toggle, Escape-to-close w/ focus return, CCPA/GDPR visibility directives).
  • Add styles for the fixed bottom-corner fallback control and update print styling to hide it.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated no comments.

Show a summary per file
File Description
projects/packages/cookie-consent/src/modules/cookie-consent/view.ts Adds Interactivity actions/context needed for the fallback control (toggle + Escape handling) and safely initializes contexts that share isCcpaRegion.
projects/packages/cookie-consent/src/modules/cookie-consent/styles.scss Adds styling for the fixed-position fallback control and ensures it’s hidden in print.
projects/packages/cookie-consent/src/footer-links-fallback.php New template that renders the accessible toggle + panel and wires up Interactivity directives for CCPA/GDPR visibility and “Manage Preferences”.
projects/packages/cookie-consent/src/class-cookie-consent.php Adds the wp_footer fallback rendering, the “injected” dedupe flag via render_block_core/navigation-link, and helper methods to resolve link URLs/labels.
projects/packages/cookie-consent/changelog/add-classic-theme-footer-links-fallback Changelog entry documenting the new fallback behavior.

Gate the whole floating control on isCcpaRegion || isGdprManageLink via a
state.showFallbackControl getter, instead of rendering a persistent global
control whose only universal link is the Privacy Policy. Rendered hidden and
revealed client-side, keeping the server HTML geo-independent (cache-safe).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants