Add optional Microsoft Clarity heatmaps with privacy controls - #202
Merged
Conversation
jimdc
force-pushed
the
integrate-microsoft-clarity-free-click-heatmap-a
branch
from
July 30, 2026 23:36
f0c96be to
9c82366
Compare
github-merge-queue
Bot
removed this pull request from the merge queue due to failed status checks
Jul 31, 2026
github-merge-queue
Bot
removed this pull request from the merge queue due to failed status checks
Jul 31, 2026
Load Clarity only when a project id is configured. Skip on Do Not Track and Global Privacy Control, mask form fields (including email), and document the About privacy posture in all shipping languages. The integration stays dormant until an operator adds a real project id.
The About privacy intro no longer claims a blanket "no cookies" once optional heatmaps may load. Point the readiness gate at the non-exhaustive accounts/ad-tech wording and the plain-language Clarity disclosure.
github-merge-queue
Bot
removed this pull request from the merge queue due to failed status checks
Jul 31, 2026
Handlers re-fetch live data when generated_at is older than MAX_AGE_MS. Fixed fixture timestamps (2026-07-29) aged out of that window and made meeting-outcomes and property route tests hit real upstream data. Seed fresh wall-clock timestamps so the routes serve the fixture writes.
jimdc
force-pushed
the
integrate-microsoft-clarity-free-click-heatmap-a
branch
from
July 31, 2026 01:01
9c82366 to
f027a07
Compare
6 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds an optional Microsoft Clarity integration for click and scroll heatmaps so the site owner can see which parts of the public UI are hard to use. The loader is dormant until a project id is configured — no live id is committed. When configured, Clarity loads asynchronously, fails soft if blocked, respects Do Not Track / Global Privacy Control, and masks form fields (including email) before any script runs.
Privacy posture (plain English)
CityScroll can load Microsoft Clarity to collect anonymous heatmaps of where people click and scroll, so hard-to-use parts of the site can be fixed. Form fields and typed text — including email — are masked and are not sent as plain text. Clarity does not load when a browser signals Do Not Track or Global Privacy Control, and the site works fully if Clarity is blocked or offline. Clarity is not used for advertising or personal profiles. First-party aggregate analytics and Cloudflare’s cookieless page-view totals remain separate.
Operator steps (project id)
Clarity requires a project under a Microsoft account. Until the id is set, the integration stays off.
cityscroll.org(and any live aliases you want measured).https://clarity.microsoft.com/projects/view/<PROJECT_ID>/).CONFIGURED_PROJECT_IDinsite/clarity.jsto the real id and redeploy, orwindow.CROL_CLARITY_PROJECT_ID = "<id>"in a small script beforeclarity.js, or<meta name="crol-clarity-project-id" content="<id>">on public pages.https://www.clarity.ms/tag/<id>loads when DNT/GPC are off, and does not load when Do Not Track or Global Privacy Control is on.data-clarity-mask="true".What changed
site/clarity.js— config path, DNT/GPC skip, input masking, non-blocking tag injectclarity.jsafter first-partyanalytics.jsSECURITY.mdandAGENTS.mdnote the optional third-party scriptnode --test test/clarity.test.mjsValidation
node --test test/clarity.test.mjs— passpython3 test/standards/i18n_keys.py— passpython3 test/standards/i18n_fallback_sync.py— passStatus
dormant-until-configured — merge ships the wiring; live heatmaps begin only after the operator pastes a real project id and sets Strict masking.