Repository navigation
Add c15t to tanstack.com - #1364
Draft
KayleeWilliams wants to merge 5 commits into
Draft
KayleeWilliams wants to merge 5 commits into
KayleeWilliams wants to merge 5 commits into
Conversation
|
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: true
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. |
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
Loaders and server functions set Cache-Control on the whole response. getOSSStats sets "public, max-age=300, stale-while-revalidate=3600", so any page that loads stats, including the homepage, told browsers and proxies they could reuse its HTML for 5 minutes and serve it stale for up to an hour. That was harmless while every visitor got the same HTML. With the consent banner, the server renders the visitor's own consent state from their c15t cookie: whether to show the banner, their recorded choices and their subject ID. A visitor who accepted and opened the homepage in a new tab got the cached pre-choice HTML from the browser's disk cache, so the banner came back until c15t re-read the cookie on the next focus. A shared cache could hand one visitor's consent state to another. The hosting layer now sets "Cache-Control: private, no-cache" on every HTML response and drops Cloudflare-CDN-Cache-Control. Browsers still keep the page, but revalidate it on each visit. JSON, images and other non-HTML responses keep the headers their routes set.
Add a c15t consent banner and hold Google Analytics, NameThatHost, Scarf and video embeds until the visitor chooses. Sentry strips user data until Analytics is allowed. Self-host fonts so Google Fonts no longer sees each visitor's IP before a choice.
main (TanStack#1399) added traffic-quality tagging to the inline GA bootstrap, which this branch replaces with c15t's gtag helper. Install the same wrapper in the helper's onBeforeLoad, after gtag and config are queued and before held page views flush, so every event still carries traffic_quality.
KayleeWilliams
force-pushed
the
kaylee/add-c15t-consent-integration
branch
from
November 13, 2026 17:00
d8e90e1 to
a3102ce
Compare
main added two trackers after this branch began. Live presence (TanStack#1442) sets the tanstack_live cookie and sends heartbeats, and server-side Scarf (TanStack#1398) forwards the visitor's IP and user agent on every HTML request. Both checked only DNT and GPC. Live presence now starts when the visitor allows Analytics and stops when they withdraw it. The Worker reads the stored c15t choice and skips server Scarf for browser requests without Analytics consent. Only browsers send Sec-Fetch-* headers, so crawler and agent requests, which carry no consent cookie, stay in the server request dataset.
c15t 3.2.2 is the stable release after the 3.0 alphas this branch pinned. - Google Analytics used the gtag helper's default loadMode, 'always', which loads gtag.js for every visitor and sends cookieless Consent Mode pings before they choose. It now uses 'after-consent', so no request reaches Google until Analytics is allowed, as the banner promises. - c15t 3.2 starts helper scripts for visitors who already consented from the server HTML, before hydration. It does this only when the entry keeps the helper's own onBeforeLoad, so the override that installed traffic quality and flushed held events is gone. The first page view now does both, and onLoad flushes for a visitor who sends none. - transport_url is a fixed https://tanstack.com/_a. The server renders the config, and window.location does not exist there. - vendorDetails: undefined is gone. Since 3.1 the dialog shows vendor switches only when the site declares vendors.
This branch has not been deployed
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.
Visitors now choose what tanstack.com measures. Google Analytics, NameThatHost, Scarf and YouTube or Vimeo embeds wait for that choice. The banner comes in the server HTML, so it shows in the first frame and does not move the page.
c15t runs the banner and the consent records. The policy and the stored choices live in Inth, at
tanstack-tanstack.inth.app.Videos
Homepage bar on a large window. The bar covers the stats strip under the hero. When you scroll, it stops under the navbar until you choose.
sticky-bar-dark.mp4
sticky-bar-light.mp4
All window sizes. The homepage at 16 sizes from 390 × 844 to 3840 × 2160, then the floating banner on
/blogat 5 sizes.Too large will update later
What changes
Consent
ConsentRootinsrc/routes/__root.tsxholds the visitor's consent state. The root loader gets that state on the server.consentManifest()invite.config.tsputs the Inth policy into the server build. The server does not ask Inth for the policy on each page. After a policy change in Inth, rebuild the site.variant="bar"). All other pages show c15t's floating card.Scripts that wait for consent
gtaghelper withloadMode: 'after-consent', through the/_aproxy. Google gets no request, not even a cookieless Consent Mode ping, until the visitor allows Analytics. Page views from before the choice stay in a queue and go out only if the visitor accepts.gtagbefore the first event, so every GA event still carriestraffic_quality.tanstack_livecookie and sends no heartbeats.Sec-Fetch-*headers, so they are still counted.src/router.tsxfor all visitors, so it still catches hydration errors. Until a visitor allows Analytics, c15t removes user data, IP addresses and session IDs from the reports.Fonts
public/fonts. Before, Google Fonts got each visitor's IP address before any choice.public/_headerscaches/fonts/*for one year. If a font file changes, give it a new name.Other
@sentry/*goes from 10.47 to ^10.76.1. The c15t integration for Sentry needs 10.67 or later.src/utils/analytics/events.tsis nowregistry.ts. Lists in tracker blockers match the dev module URL/analytics/events.ts. With a blocker on, the page did not hydrate in dev.@c15t/tanstack-start/serverentry. Thebrowserexport condition gives the Worker a stub that throws.Performance
Lab test, median of 7 runs,
mainatfe0b1ba5against this branch. Both are production builds served locally behind a gzip proxy, as Cloudflare compresses responses. Requests carrycf-ipcountry: DE, so the visitor gets an opt-in policy and the banner. Mobile is 412 × 823 with the CPU slowed 4× on a 1.6 Mbps link with 150 ms latency. Desktop is 1350 × 940 with no throttle. Analytics beacons are blocked in both builds.main/, LCP/, Total Blocking Time/, first paint / banner paint/, Reject All response (INP)/blog, LCP/, LCP/, Reject All response (INP)/blog, LCP/,gtag.jsrequest after first paint, visitor who accepted//blog/bloghas the same 0.079 CLS onmain, so the floating banner adds none.main.Checks
pnpm test/blogat 5, in light and dark mode