Back to Blog

Recorde Setup Guide: Privacy-First Analytics in Two Minutes

Ronan··7 min read
SetupGetting StartedPrivacyCustom EventsDocumentation

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:

AttributePurpose
deferLoads the script without blocking your page render.
data-domainThe domain you're tracking — must match the site you added in Recorde.
srcThe versioned script URL on your ingestion host. The version number (0.2.0) pins it to a specific, immutable release.
integrityA 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.php just 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

  1. Add the snippet and publish (or preview) your site.
  2. Visit any page on your site to generate a pageview.
  3. 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" });
ArgumentRequiredLimits
Event nameYesA string, 1–255 characters.
MetadataNoA 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 sessionStorage and 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-domain value exactly matches the domain you registered in Recorde (no https://, no trailing slash, no www. 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 POST to /api/e. A 403 usually 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.
Read the deployment guide