Skip to content

feat(consent): gate host-side visitor recognition on cookieTracking consent - #75

Closed
0xgautam wants to merge 2 commits into
mainfrom
agent/cookie-consent-runtime
Closed

feat(consent): gate host-side visitor recognition on cookieTracking consent#75
0xgautam wants to merge 2 commits into
mainfrom
agent/cookie-consent-runtime

Conversation

@0xgautam

@0xgautam 0xgautam commented Sep 4, 2026

Copy link
Copy Markdown
Collaborator

What does this PR do?

Adds cookieTracking as a third category of SurfaceSetConsent, matching the new Cookie Tracking privacy control in trysurface/surface_forms#5811, and lets a page opt the tag into waiting for it.

Pages that run a consent banner load the tag with data-consent-mode:

<script src=".../surface_tag.min.js" site-id="..." data-consent-mode></script>
<script>
  window.SurfaceSetConsent({ adTracking: true, surfaceAnalytics: true, cookieTracking: true });
</script>

With the attribute, until cookieTracking is granted the tag:

  • runs no identify or browser fingerprint and never reads or writes the surfaceLeadData cache
  • starts no user journey, sets no surface_journey_id / surface_recent_visit cookies and sends no page-view beacons
  • forwards an empty cookie snapshot, surfaceLeadData: null and userJourneyId: null in STORE_UPDATE
  • still answers the iframe's SEND_DATA handshake with STORE_UPDATE and LEAD_DATA_UPDATE, so the form renders, identifies without recognition and submits as before

A grant starts journey tracking, identifies and pushes lead data to the frames. Withdrawal clears the journey cookies and the lead cache. Every SurfaceSetConsent call is a complete snapshot, so an older two-field call denies cookies.

Every answer is also written to window.__SURFACE_CONSENT__ and dispatched as a surface:consent DOM event, and the tag reads a snapshot an SDK that loaded first left there. That is how a customer-hosted Forms SDK form and the tag agree on one banner answer without wrapping each other's API.

Without the attribute nothing changes. Journey tracking on pages without forms, the public SurfaceIdentifyLead API, cookie forwarding, conversions, HTML forms and open triggers all behave exactly as on main.

Rollout

Deploy order does not matter. An old Forms build ignores the extra boolean; a new Forms build with the old tag gates itself inside the iframe. Rollback is a plain revert of this bundle.

Testing

  • pnpm typecheck
  • pnpm test: 25 tests pass, including new SurfaceStore cases for consent mode (no journey, identify or cache read before a grant; grant starts them and forwards cookies; withdrawal clears them; no attribute means no change) and a listener case for the denied handshake.
  • pnpm build, cmp surface_tag.js surface_embed_v1.js
  • git diff --check
  • Manual browser QA with test/consent.html against a Forms staging deploy: pending.

Testing Instructions

test/consent.html now loads the tag with data-consent-mode and has a Cookies checkbox. Serve the repo root, open it in tag mode against a form whose Cookie Tracking is On consent, and check in devtools: before answering there are no surface_journey_id, surface_recent_visit or surfaceLeadData entries and no lead/identify or lead/track requests; after accepting they appear; after withdrawing the cookies and cache are removed. Load any other test page without the attribute to confirm the old behavior.

…onsent

Adds `cookieTracking` as a third category of `SurfaceSetConsent`, mirroring
the new Cookie Tracking privacy control in Forms (trysurface/surface_forms#5811).
Every call is a complete snapshot, so an older two-field call denies cookies.

Pages that load the tag with `data-consent-mode` get a tag that does no
visitor recognition until that category is granted: no identify or
fingerprint, no `surfaceLeadData` cache read/write, no journey cookies or
page-view beacons, and an empty cookie snapshot in STORE_UPDATE. A grant
starts all of it; withdrawal clears the journey cookies and lead cache.
Frames still receive their handshake so forms render and submit as before.

Without the attribute nothing changes for existing installs.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@0xgautam
0xgautam force-pushed the agent/cookie-consent-runtime branch from aac8f18 to 0dea851 Compare September 6, 2026 20:28
@0xgautam 0xgautam changed the title Gate Surface tag tracking on form-scoped cookie consent feat(consent): gate host-side visitor recognition on cookieTracking consent Sep 6, 2026
… document

`SurfaceSetConsent` now also writes the normalized snapshot to
`window.__SURFACE_CONSENT__` and dispatches a `surface:consent` DOM event, and
the tag reads a snapshot an SDK that loaded first left there. This is how a
customer-hosted SDK form and the tag agree on one banner answer without either
wrapping the other's API.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@0xgautam

0xgautam commented Sep 8, 2026

Copy link
Copy Markdown
Collaborator Author

Superseded: the Surface Tag source now lives in the monorepo at packages/surface-scripts, so this change moved to a PR stacked on trysurface/surface_forms#5811 (branch agent/privacy-cookie-consent-tag). Nothing further will land here.

@0xgautam 0xgautam closed this Sep 8, 2026
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.

1 participant