@convex-internal/web-analytics
v2.0.1
Published
Shared consent state, consent banner, and analytics setup for Convex websites.
Downloads
1,165
Readme
@convex-internal/web-analytics
Shared consent state, consent banner, and analytics setup for Convex websites.
Core
Mount a framework entry at the root (React or Svelte). Analytics start in production, except on localhost. Consent is synced to PostHog. The banner shows when the visitor has not chosen yet.
PostHog already copies standard campaign params (UTMs, gclid, rdt_cid,
fbclid, and other common click IDs) from the landing URL onto events. This
package also captures dub_id. After consent, PostHog creates an anonymous
person profile. Campaign params still available at that point can be stored as
$initial_*, supporting person-level attribution before login.
capture
Record an event from client code through the framework-neutral root entry. The optional third argument is PostHog's capture options.
import { capture } from "@convex-internal/web-analytics";
capture("www-login", undefined, {
transport: "sendBeacon",
send_instantly: true,
});Consent banner
The banner shows when consent is "undecided". It records
cookie_consent_shown when it appears and cookie_consent_decided with
{ decision: "accepted" | "declined" } just before the choice is saved.
The banner stays hidden while Global Privacy Control is on, because that
resolves consent to "declined" rather than "undecided". GPC does not
write the cookie; see Cookie behavior.
Theme with --wa-banner-* variables on .wa-banner:
.wa-banner {
--wa-banner-background-color: var(--color-seashell);
--wa-banner-font-family: var(--font-primary);
--wa-banner-accept-background-color: var(--color-plum-p4);
}- Background, text, and border:
--wa-banner-background-color,--wa-banner-text-color,--wa-banner-border-color,--wa-banner-border-radius,--wa-banner-box-shadow,--wa-banner-backdrop-filter - Type and layout:
--wa-banner-font-family,--wa-banner-font-size,--wa-banner-padding,--wa-banner-max-width,--wa-banner-action-gap,--wa-banner-z-index - Link and focus:
--wa-banner-link-color,--wa-banner-focus-color - Buttons:
--wa-banner-button-border-radius,--wa-banner-button-padding,--wa-banner-button-min-height,--wa-banner-button-font-size,--wa-banner-button-font-weight - Accept button:
--wa-banner-accept-background-color,--wa-banner-accept-text-color - Decline button:
--wa-banner-decline-background-color,--wa-banner-decline-text-color
Buttons default to 80% opacity and go to 100% on hover or keyboard focus.
Cookie behavior
Once the cookie has been read, consent is resolved in this order:
- Global Privacy Control. If
navigator.globalPrivacyControl === true,consentis"declined". GPC is not stored: the cookie is not written or changed. Turn GPC off and the stored cookie (if set) applies again. - Cookie.
trueis"consented",falseis"declined", and a missing or unrecognized value is"undecided".
The cookie is stored with path=/ and a max-age of one year. On convex.dev
and *.convex.dev it is also set with domain=.convex.dev so the website,
Docs, Stack, and other subdomains share one choice. The cookie is marked
Secure everywhere except localhost.
Changes made through setConsent update immediately. Changes made
elsewhere, such as in another tab or DevTools, are synchronized through cookie
change events when available, and when the window regains focus or its
visibility changes as a fallback.
React
Import from @convex-internal/web-analytics/react.
WebAnalyticsProvider is a client component. useConsent throws if called
outside that provider.
import { WebAnalyticsProvider } from "@convex-internal/web-analytics/react";
<WebAnalyticsProvider>{children}</WebAnalyticsProvider>;Consented
Renders children only when consent is "consented". It renders nothing during
SSR, while consent is still "unknown" or "undecided", if the visitor
declined, or while Global Privacy Control is on.
import { Consented } from "@convex-internal/web-analytics/react";
<Consented>
<YourAnalyticsScripts />
</Consented>;useConsent
consent(ConsentStatus)"unknown"until cookie has been read (SSR and first client render)"undecided"after that if there is no recognized choice yet"consented"if the cookie istrueand GPC is not set"declined"if the cookie isfalseor GPC is set
setConsent("consented" | "declined")- Saves the choice to the
allowsCookiescookie and updates context - Do not write the cookie yourself
- Saves the choice to the
Use the hook when you need consent or setConsent directly. Enable tracking
only when consent === "consented".
Svelte
The Svelte entry exports only WebAnalytics. Render it once in the root
layout. It has no props and no snippet: it starts PostHog and shows the banner.
There is no Consented wrapper or consent store. Those can be added later;
nothing using the Svelte entry has needed them yet.
<script>
import { WebAnalytics } from "@convex-internal/web-analytics/svelte";
</script>
<WebAnalytics />Test in-development changes
- In the
web-analyticsrepo, build and pack the package:
cd /path/to/web-analytics
npm run build
npm packThis creates a tarball such as convex-internal-web-analytics-1.0.0.tgz.
- Install that tarball in the consuming app:
cd /path/to/consuming-app
npm install /path/to/web-analytics/convex-internal-web-analytics-1.0.0.tgz --force--force ensures npm refreshes the package when the filename and version have
not changed.
Publish a version to npm
- Confirm that you are signed in to the npm account with access to the
@convex-internalorganization:
npm whoamiRun npm login first if needed.
- Commit any README or code changes, then bump the version.
npm versionrequires a clean Git worktree and creates a version commit and tag.
npm version major # breaking, or 0.x → 1.0.0
npm version minor # new backwards-compatible functionality
npm version patch # bug fixes- Run tests, inspect the package contents, then publish.
.npmrcsetsignore-scripts=true, soprepackwill not run — build first:
npm test
npm run build
npm pack --dry-run
npm publishConsume a published version
Convex repos typically set min-release-age=7 in .npmrc, so a version
published in the last 7 days will fail to install. Override the window for that
one install:
npm install @convex-internal/web-analytics@<version> --min-release-age=0Use the local tarball workflow whenever you need to test changes that have not been published yet.
