Recorde Setup Guide: Privacy-First Analytics in Two Minutes
Get privacy-first analytics running on your site in a couple of minutes. Recorde is a single lightweight script — no cookies, no consent banner required, and nothing that slows your pages down.
This guide assumes you already have a Recorde instance running. If not, start with the deployment guide and come back here once the dashboard is up.
Where to find your exact snippet: every code example below uses placeholder values. The exact snippet for your site — with your domain, your instance's script URL, and the current version pinned — is on the site's Setup page in your dashboard. Copy it from there; this guide explains what each part does.
1. Add the tracking snippet
Paste this snippet into the <head> of your website, on every page you want to
track:
<script
defer
data-domain="example.com"
src="https://collect.example.com/js/recorde-0.2.0.min.js"
integrity="sha384-..."
crossorigin="anonymous"
></script>
What each part does:
| Attribute | Purpose |
|---|---|
defer | Loads the script without blocking your page render. |
data-domain | The domain you're tracking — must match the site you added in Recorde. |
src | The versioned script URL on your ingestion host. The version number (0.2.0) pins it to a specific, immutable release. |
integrity | A Subresource Integrity hash. Your visitors' browsers verify the script against this hash and refuse to run it if it has been tampered with. |
crossorigin="anonymous" | Required for the integrity check to work. The script is loaded without sending any credentials. |
The script is about 1 KB gzipped and loads asynchronously, so it has no measurable impact on your page speed or Core Web Vitals.
Prefer automatic updates?
The pinned snippet above never changes until you copy a new one. If you'd rather
always receive the latest version automatically — without re-copying the snippet
on each release — use the rolling URL instead (note it has no integrity or
crossorigin attribute):
<script defer data-domain="example.com" src="https://collect.example.com/js/recorde.min.js"></script>
This trades cryptographic pinning for hands-off updates. For most sites the pinned snippet is recommended.
2. Where to place it
Add the snippet inside the <head> tag. Here's where that is on common
platforms:
- Plain HTML: in the
<head>of every page, or in a shared header/template file (e.g.header.html). - Next.js (App Router): in your root
app/layout.tsx, inside the<head>. - Next.js (Pages Router): in
pages/_document.tsx, inside the<Head>component. - WordPress: use a plugin such as Insert Headers and Footers, or add it to
your theme's
header.phpjust before</head>. - Shopify: Online Store → Themes → Edit code →
theme.liquid, inside the<head>. - Webflow / Squarespace / Wix: paste it into the site-wide "head code" / "custom code" setting in your site settings.
- Framer: Site Settings → General → Custom Code → "Start of
<head>tag".
Once it's in a shared layout or template, it applies to every page automatically — you don't need to add it per page.
3. Verify it's working
- Add the snippet and publish (or preview) your site.
- Visit any page on your site to generate a pageview.
- Open your site's Setup page in the Recorde dashboard and click Verify installation — it confirms the first pageview within a minute.
You can also check it yourself: open your browser's developer tools, go to the
Network tab, reload the page, and look for a request to recorde-*.min.js
(loads with status 200) followed by a POST to /api/e (status 202).
4. Track custom events (optional)
Pageviews are tracked automatically. To record other actions — signups,
purchases, downloads, button clicks — and attach your own metadata, call
recorde.track() from your site's JavaScript:
// Event name only
recorde.track("signup");
// Event name with metadata
recorde.track("signup", { plan: "pro", source: "pricing-page" });
| Argument | Required | Limits |
|---|---|---|
| Event name | Yes | A string, 1–255 characters. |
| Metadata | No | A plain object — up to 50 keys, 8 KB total, nested at most 3 levels deep. Values can be strings, numbers, or booleans. |
A few examples:
// E-commerce purchase
recorde.track("purchase", { value: 49.99, currency: "GBP", items: 3 });
// Outbound link clicks
document.querySelectorAll('a[href^="http"]').forEach((link) => {
link.addEventListener("click", () => {
recorde.track("outbound_click", { url: link.href });
});
});
// Newsletter signup
form.addEventListener("submit", () => {
recorde.track("newsletter_signup", { source: "footer" });
});
Custom events are fire-and-forget — they never throw errors into your page and survive page navigations. See the custom events guide for the full reference.
5. Single-page apps (SPAs)
If your site uses client-side routing (React, Vue, Angular, SvelteKit, Next.js,
etc.), Recorde tracks route changes automatically. It listens for History API
navigations (pushState, replaceState, popstate) and hash changes, and
sends a new pageview whenever the path changes. No extra configuration is
needed.
6. Privacy & opt-out
Recorde is built to be privacy-first:
- No cookies. A rolling session ID is stored in
sessionStorageand expires after 30 minutes of inactivity. - No personal data. No IP addresses are stored (country is derived in memory and the IP is discarded), no fingerprinting, no cross-site tracking.
- Query strings are stripped from URLs and referrers, and a built-in list of sensitive parameters (tokens, emails, etc.) is removed before anything is sent.
- Global Privacy Control (GPC) is honoured automatically — visitors with GPC enabled are never tracked.
Giving visitors an opt-out
You can offer visitors a one-click opt-out in three ways:
1. A privacy-policy link. Link to #recorde-optout anywhere on your site:
This site uses Recorde for anonymous analytics.
<a href="#recorde-optout">Opt out of analytics</a>.
Visiting any page with #recorde-optout in the URL disables tracking for that
visitor; #recorde-optin re-enables it.
2. The JavaScript API:
recorde.optOut(); // disable tracking for this visitor
recorde.optIn(); // re-enable it
recorde.isOptedOut(); // → true / false
3. The built-in privacy badge. Add the data-privacy attribute to your
snippet to show a small, unobtrusive shield in the bottom-right corner that lets
visitors toggle tracking themselves:
<script
defer
data-domain="example.com"
data-privacy
src="https://collect.example.com/js/recorde-0.2.0.min.js"
integrity="sha384-..."
crossorigin="anonymous"
></script>
7. Troubleshooting
No data showing up?
- Confirm the
data-domainvalue exactly matches the domain you registered in Recorde (nohttps://, no trailing slash, nowww.unless that's how you registered it). - Make sure the snippet is in the
<head>and the page has actually loaded in a browser. Bots and crawlers are filtered out and won't appear in your stats. - Check the Network tab for the
POSTto/api/e. A403usually means the domain isn't registered in the dashboard.
CORS errors on localhost?
This is expected during local development — by default Recorde only accepts
events from your registered domain. Your site is unaffected: the script fails
safely and simply records nothing. Set RECORDE_CORS_ALLOW_LOCALHOST=true on
the ingestion service to record events from localhost while developing.
The script didn't load (blocked by integrity)? If you pinned an old version that's no longer published, the browser blocks the script and no analytics are recorded — but your page is completely unaffected. Copy the current snippet from your dashboard Setup page to fix it.
Need help?
If you're stuck, open an issue on GitHub or email team@recorde.io — we're happy to help you get set up.
Run Recorde on your own server.
Clone the repository, bring up the stack, paste the snippet. Keep it if it fits.
- One Docker Compose stack: dashboard, ingestion service, database.
- Minutes to first pageview. One script tag on your site.
- Run alongside your existing analytics. No disruption.
- Apache 2.0. No plans, no seats, no usage caps.