For developers

Analytics you can read in one tag

One script tag, goals without setup, and a server you can read and run yourself.

your-site/index.html
<script
  defer
  data-site="tkb_a1b2c3d4"
  data-domain="example.com"
  src="https://stats.example.com/js/tkb_a1b2c3d4.js">
</script>
Liveexample.comdemo
Visitors129
Online4
  • signup1

One tag, every framework

<script
  defer
  data-site="tkb_a1b2c3d4"
  data-domain="example.com"
  src="https://stats.example.com/js/tkb_a1b2c3d4.js">
</script>

Paste it in your <head>. Route changes in single-page apps are counted for you.

// app/layout.tsx
import { Analytics } from 'trckable/next'

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        {children}
        <Analytics site="tkb_a1b2c3d4" />
      </body>
    </html>
  )
}

// app/api/e/route.ts
export { POST } from 'trckable/next'

npm i trckable, then one component and one route. The page for it: Analytics for Next.js.

import { Analytics } from 'trckable/react'

export default function App() {
  return (
    <>
      <Analytics site="tkb_a1b2c3d4" host="https://stats.example.com" />
      {/* your app */}
    </>
  )
}

Works in Vite, React Router, Remix or anything else that renders React.

import { init } from 'trckable'
init({ site: 'tkb_a1b2c3d4', host: 'https://stats.example.com' })

Call it once, as early as you can. Solid, Qwik and plain JavaScript all work the same way.

<?php // functions.php of your child theme
add_action('wp_head', function () { ?>
  <script
    defer
    data-site="tkb_a1b2c3d4"
    data-domain="example.com"
    src="https://stats.example.com/js/tkb_a1b2c3d4.js">
  </script>
<?php });

A child theme survives theme updates. More builders: other platforms.

The same tag, the same numbers. All the install options, same-origin proxy included.

Goals with no setup

demoYour site

Ship it today

Click the button. In a real site this tag does the counting.

<button data-trckable-goal="signup" data-trckable-goal-plan="pro">
  Start free trial
</button>
trckable('goal', 'signup', { plan: 'pro' })
Goalsdemo

No goal counted yet. Click Start free.

Nothing here is sent anywhere: this is a picture of the flow. Goals are on for a new site. Once one is counted, it shows in your Goals card. How goals work.

Read it from anywhere

terminal
curl -H 'Authorization: Bearer tkb_live_…' \
  'https://stats.example.com/api/v1/sites/tkb_a1b2c3d4/now'
{
  "online": 3,
  "visitors": 41,
  "previous": 36,
  "sources": [{ "channel": "Search", "visitors": 18 }],
  …
}

Read-only keys, one spec, nothing held back. The HTTP API. Example numbers.

MCPexample

How many signups this week?

trckable_goals

42 people reached the signup goal in the last 7 days.

terminal
npx trckable mcp

Your assistant, your key, read-only tools. The MCP server.

Open source, one command

terminal
docker run -d --name trckable -p 8080:8080 -v trckable-data:/data ghcr.io/trckable/trckable
# a one-time setup link: open it, create your account, add your site
docker logs trckable

Free, with every feature. The server is AGPL-3.0, the tracker is MIT. Read the code on GitHub · Self-host guide.

Private, small and fast

  • 2 KBbrowser script
  • 1container, no external database
  • 57 MBmemory when idle
  • 0IP addresses stored
  • No cookie banner needed

    In cookieless mode nothing is stored on your visitor's device.

  • No IP address stored

    Not in a log, not in the database, not on disk.

  • Nothing from another company

    No fonts, no CDN, no pixels. The browser talks to your server only.

Measured the same way as the tools we compare with: By the numbers.

Coming next

  • NextKeys to send goals from your server
  • NextRevenue on goals
  • NextSDKs for Node, Python and Go
  • NextAn assistant inside trckable
Start free