← back to tempo
privacy policy
last updated: July 5, 2026
at a glance Anonymous typing stays on your device. Google sign-in creates an online account on our server (name, picture, Google ID, email) so progress follows you across devices and the leaderboard stays fair. Paid plans go through Stripe Checkout — we never see card data. Chat and DMs are reviewed by automated moderation including a third-party AI classifier. Live races stream typing progress to the other players in the room. Cookies are grouped into functional (required), analytics, and marketing — you pick which are on from our first-visit modal, and can reopen it any time from the emblem in the bottom-left. We log IPs only for security and don't sell, profile, or cross-site-track. Export or delete your account from Account → Sync. Full cookie details in the cookie policy.

who runs tempo

tempo is operated by PrecisionWorkz, the data controller for everything described here. Contact us via the about page for any privacy question or request.


what we collect

  • On your device (localStorage): settings, typing history and stats, a local user identifier, and — once you sign in — a saved reference to your online user ID. Local-mode data never leaves your device.
  • Account & sign-in (Google only): display name, profile-picture URL, Google account identifier ("sub"), and email. Used to link the account across devices, keep the leaderboard fair, and enforce bans. We also store registration time, custom username, last-seen IP, and any perma-link state you initiate.
  • Gameplay & social: leaderboard scores (name, WPM, accuracy, badges, timestamp), achievements, friends list and requests, public chat content (most recent ~100 messages or 2 hours), and DMs.
  • Race-room data: while a race is in progress, your display name, current position in the text, and live WPM are shared with the other players in the room. The room and its per-player state expire automatically a few minutes after the race ends.
  • Moderation & anti-cheat: automated moderation outcomes (category, action, brief excerpt), strike counts, ban records, user reports, anti-cheat flag records with categories and timestamps. Anti-cheat flags exclude a session from the leaderboard but don't stop typing.
  • Security data: IP addresses and minimal metadata logged only on specific events — see "security & IP logging".
  • Payments: Stripe Checkout processes all paid-plan purchases and one-time donations. We never receive or store your card details — Stripe handles the payment surface end-to-end. We retain the plan, tier, grant timestamp, and Stripe session/event IDs needed to confirm activation, support refunds, and detect duplicate webhook deliveries. The 3-day Premium trial is a direct grant — no payment data is collected.

We use your browser's localStorage and a small session token to authorize writes to your own account. Google Sign-In sets its own cookies under Google's control. Visitors on the Free plan may have additional first-party cookies set by Google Analytics 4 (visitor and session measurement, see "analytics" below) and by Google AdSense (ad relevance and frequency capping, see "advertising" below). Both are scoped to this site. Starter and Premium subscribers bypass both — neither GA nor AdSense scripts load in their browsers, and no cookies are set by either service for paid users.


cookie policy

Tempo uses three categories of client-side storage. On your first visit our consent modal asks you to choose which are on; you can reopen it any time from the small t. emblem in the bottom-left corner of the app.

  • Functional (required): browser localStorage keys that hold your settings, theme, typing history, cached user id, and — when signed in — the session token that authorizes writes to your account. Also includes a random client-generated consent session id (_consentSid) so we can aggregate anonymous decision counts on the staff dashboard without ever linking to your Tempo account. These are strictly necessary for the app to work; there is no toggle to turn them off.
  • Analytics (optional, off by default): Google Analytics 4 (property G-CW311XFKRC). If you turn this on we un-block the GA4 tag on the same page load; GA4 then sets first-party cookies (_ga, _ga_*) for anonymous session and visitor measurement. If you leave it off, the GA4 script stays inert (type="text/plain") and no GA cookies are set at all.
  • Marketing (optional, off by default, free plan only): Google AdSense for ad selection and frequency capping. Same gating as analytics — the tag stays inert until you grant consent. Starter and Premium subscribers never see this category regardless of choice, because ads don't load for paid users at all.

How the gate works. The GA4 and AdSense tags are shipped as type="text/plain" so browsers don't execute them. Our own inline resolver runs synchronously in the page head, reads your stored consent state, and only swaps a tag to type="text/javascript" if the matching category is granted. There is no third-party CMP script involved — the whole gate is a small chunk of code in our own repo.

Session id, not a fingerprint. The _consentSid value is a random UUID generated in your browser the first time the modal opens. It is stored in localStorage, sent only to /api/consent with your decision, and is never combined with any account, IP address, or fingerprint. If you clear browser storage you get a new random id on the next visit.

Changing your mind. Click the t. emblem in the bottom-left to reopen the modal. New decisions overwrite the previous choice and are re-broadcast to the staff aggregate counters idempotently — old counters get decremented, new counters get incremented, so the totals always reflect exactly one row per unique session.


why we use it & legal basis

For EU/UK/Swiss users (and similar regimes): performance of our agreement with you (running the test, scores, sign-in, processing your purchase); our legitimate interest in keeping the service secure and fair (bot defence, anti-cheat, rate-limiting, ban enforcement); your consent where required (Google sign-in identifiers); and legal compliance where required. You can withdraw consent at any time by signing out and deleting your account.


analytics & what we don't do

We run two analytics tools, and which one fires depends on your plan.

Vercel Analytics runs on every visit regardless of plan. It provides aggregate, cookieless traffic measurement — page views, referrer, rough country. The script is served from our own origin, sets no cookies, doesn't assign a persistent identifier, and doesn't follow you across other sites.

Google Analytics 4 (gtag.js, property G-CW311XFKRC) runs on the Free plan only. The init script is wrapped in a synchronous check against a local _paid flag — for Starter and Premium subscribers, the GA script never loads and no GA cookies are set in their browsers. For free users, GA4 sets first-party cookies (_ga, _ga_*) used for session and visitor measurement, and may pass aggregated data to Google per Google's own policies. You can opt out site-wide by signing in and upgrading to any paid plan, or by installing the Google Analytics opt-out browser add-on.

We do not use Mixpanel, Segment, advertising trackers other than Google AdSense (see below), or any other behavioural analytics service. We do not sell or rent your data, do not build our own advertising profiles, and do not track you across other sites.

advertising (free plan only)

Free-plan visitors see ads served by Google AdSense. Google may set cookies and process data for ad selection, frequency capping, and measurement, per Google's advertising policies. You can manage personalized ad settings at adssettings.google.com. Starter and Premium subscribers see no ads — the AdSense script is removed from the DOM after plan confirmation and is never loaded on subsequent visits for paid users (managed via the same client-side plan check that gates GA).


ai-assisted moderation

Public chat and direct messages are reviewed before delivery via three layers: local keyword filters on our server, a third-party classifier from OpenAI that scores hate / harassment / sexual / violent / etc. categories, and a focused LLM review (also OpenAI) used when a moderator re-checks a user-reported message with surrounding context. The provider receives only message text and short context, no tempo account identifier, and doesn't train its public models on this content. Violation events are recorded with verdict, category, action, and an excerpt in the moderation log (most recent ~200) and the per-account history. Strikes escalate to warnings, time-outs, and permanent chat bans — see the terms for appeals.


payments & donations

All paid-plan and donation transactions are processed by Stripe, an independent data controller for the payment surface itself. You enter card details on Stripe-hosted Checkout pages; the data goes directly to Stripe under their privacy policy — we never see it, store it, or pass it through our server. After a successful payment Stripe sends us a signed webhook (verified by HMAC-SHA256 with our webhook secret) telling us which plan and tier to activate against which tempo user ID; we then write that grant to your account record. We deduplicate the webhook by event ID for 24 hours to prevent double-grants on retries. For donations, we additionally record the display name you chose for the public donor wall (the wall lists names only — no user IDs).

The 3-day Premium trial is a direct internal grant — no Stripe call, no payment data. The trialused flag is kept against your uid for 10 years to enforce the once-per-uid rule. The trial expires automatically and reverts you to free; nothing recurs.


google sign-in & dual identity

Sign-in goes through Google's OAuth flow. We receive your display name, profile picture, Google sub, and email; we store the sub and email to link progress across devices, prevent duplicate accounts, and enforce bans. You can revoke tempo's access from your Google account settings at any time — that doesn't by itself delete data already stored; use Account → Sync → Danger Zone for that.

tempo keeps the anonymous local identity and the Google-linked online identity strictly separate on the same device. Signing out swaps back to local and clears any paid-plan state and the online session token from the device. Signing back in restores the online identity from our server via the index that maps Google sub → canonical user ID. Local stats never reach our server unless you choose to merge them in. A "perma-link" you request becomes a permanent uid ↔ Google binding that only the owner can reverse.


security & ip logging

To defend tempo against bots, abuse, and unauthorized access, we log IPs and minimal metadata only when one of these happens: bot-detection check during a session, new account registration, account termination, attempted access to a restricted area, chat ban / moderation action / perma-link operation, or repeated wrong-password attempts on an auth endpoint. IP bans are narrow — only for brute-force attempts on authentication endpoints or manual operator review. Heavy rate-limited traffic is logged but never auto-bans. Anti-cheat flags don't cause IP bans either.

Legal basis: our legitimate interest in fraud, abuse, and unauthorized-access prevention, balanced against your rights. Logs are never used for advertising, profiling, or anything unrelated.

Retention: security audit log capped at ~500 most recent entries (older discarded). Last-seen IP up to 90 days. IP/account ban records up to 12 months and only while a ban is active; you can request earlier deletion of an expired record. Routine encrypted backups may persist up to 35 days before rolling off; we don't restore from them to bring back deleted data. To delete security-log data, contact us with subject Data Deletion; we comply unless a record is needed to enforce an active ban, detect ongoing abuse, or meet a legal obligation.


how long we keep data

  • On-device data: until you clear browser storage
  • Account link (Google ID, email, rank, regtime): while account exists; deleted on request
  • Session tokens: up to ~2 years, or until deletion
  • Stats & badges (server-side): ~1 year after last activity, or until deletion
  • Public chat: most recent ~100 messages or 2 hours
  • DMs: until you or the recipient delete the thread or account
  • Moderation log (global): capped at most recent ~200; per-account history retained while the account exists
  • Race rooms & per-player state: ~10 minutes, then auto-expired
  • Stripe payment metadata (plan, tier, session IDs): while the grant is active + audit retention
  • Trial-used flag: 10 years to enforce once-per-uid
  • Pending sync / perma-link requests: up to 30 days, then auto-expire
  • Security logs, last-seen IP, ban records: as described above
  • Encrypted backups: up to 35 days, no restore-to-recover

your rights

You have rights to access, correct, delete, export, restrict, and object to our use of your personal data, depending on where you live.

  • Export: Account → Sync → "export data"
  • Delete: Account → Sync → Danger Zone → "delete account"
  • Access / correction / objection: contact us via the about page

We aim to respond within 30 days. EEA/UK users may lodge a complaint with their local data protection authority. California residents have CCPA/CPRA rights — including access, deletion, correction, opt-out of "sale" or "sharing" (we do neither), and non-discrimination for exercising them.


service providers & international transfers

We use a small set of third-party processors — including hosting, edge networking, database, sign-in, and payment (Stripe) services — that handle data on our behalf under our instructions, or as independent controllers for clearly demarcated surfaces (Stripe processes payment data directly with you). Data may be processed on servers outside your home country, including in the United States. Where required, we rely on appropriate safeguards such as Standard Contractual Clauses for those transfers.


children

tempo isn't directed at children under 13 (US, COPPA) or 16 (EU/UK / equivalent). We don't knowingly collect data from children below that age. A parent or guardian who believes a child has created an account can contact us via the about page for immediate removal.


changes & contact

Material updates to this policy will appear in the "last updated" date and, where appropriate, an in-app notice. Continued use after an update is your acceptance. Privacy questions or requests: contact page.