9d9

Analytics

First-party pageview and event analytics. No Google. No cookies-by-default.

Every 9d9 site can ship a 1.5 KB beacon that records pageviews and custom events to a first-party endpoint on your own subdomain. Dashboard charts read from the same daily rollup. No third-party scripts, no cookies unless your visitor's browser allows localStorage, no ad targeting.

Install

Drop one line into the <head> of your site, with your org id as data-org. The org id is visible at the top of your dashboard's Settings page.

<script src="https://api.9d9.dev/beacon" data-org="org_xxx" async></script>

That's it. Pageviews appear in the dashboard within a minute. No build step, no redeploy when org ids change (just edit the markup).

What gets recorded

FieldSourceNotes
pathlocation.pathname + searchTruncated at 500 chars.
referrerdocument.referrerEmpty for direct hits.
visitor_idrandom, in localStorageStable across sessions on the same browser. Cleared by site-data wipes.
session_idrandom, in sessionStorageNew per tab/window session.
deviceUA regexmobile or desktop.
countryCloudflare cf-ipcountryTwo-letter ISO code, set by edge — never sent by the beacon.
utm_source / medium / campaignURL queryFor attribution.

What is not recorded: IP address, exact user agent string, screen size, mouse movement, scroll depth, or anything else not in the table above.

Custom events

Call navigator.sendBeacon directly to record arbitrary events — pricing-card click, "Book now" pressed, video play, etc.

fetch("https://api.9d9.dev/beacon", {
  method: "POST",
  headers: { "content-type": "application/json" },
  body: JSON.stringify({
    org_id: "org_xxx",
    type: "event",
    path: "/checkout",
  }),
});

Read API

The dashboard reads from GET /v1/sites/{org_id}/analytics?days=N. Returns a daily-rollup array — pageviews, visitors, top path per day. Daily rollups run at 02:00 UTC.

Rate limits + abuse

The beacon endpoint accepts up to 600 events per IP per minute. Beyond that the endpoint returns 429 and the event is dropped. Beacons themselves are best-effort — page-unload events can be lost. Treat these numbers as directionally correct, not financial-accounting precise.

Privacy

No third-party cookies. No ad-network identifiers. visitor_id is a random string in localStorage with no PII baked in. IP addresses are not stored — only the two-letter country derived at the edge.

Most regions don't require a cookie banner for this kind of first-party measurement, but check your local rules. The localStorage key 9d9 uses is technically client-side storage; some jurisdictions treat that the same as cookies.