> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tinytrack.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Cloudflare

> A transparent proxy that counts pageviews server-side, auto-injects the TinyTrack script, and serves the tracker and beacons first-party.

## How It Works

The Worker runs on a Cloudflare route that covers your site. For each request it:

* Counts one `page_view` per HTML document request, server-side at the edge.
* Injects the TinyTrack script into the HTML response, so your source stays untouched.
* Serves the tracker from `/_tinytrack/tracker.js` and takes client events at `/_tinytrack/track`, first-party on your own domain.

Everything else passes straight through to your origin.

## Install

Cloudflare clones the repo and sets up the worker.

[![Deploy to Cloudflare](https://deploy.workers.cloudflare.com/button)](https://deploy.workers.cloudflare.com/?url=https://github.com/tinytrack-io/cloudflare-worker)

<Steps>
  <Step title="Set your website id">
    1. Go to: **Workers & Pages**
    2. Open: **tinytrack-cloudflare-worker → Settings → Variables**: set `TINYTRACK_WEBSITE_ID` (TinyTrack **Settings → Tracking**)
  </Step>

  <Step title="Route it over your site">
    **Domains → Add Route**, e.g. `example.com/*`.
  </Step>
</Steps>

<Warning>
  Use Worker **Routes**, not Custom Domains: a Custom Domain replaces your origin and breaks the proxy.
</Warning>

You can reduce the number of requests to your worker by excluding assets, see [Reducing Worker invocations](#reducing-worker-invocations).

## Install (manual)

Prerequisites:

* Requires a Cloudflare account with your site's DNS proxied
* Node.js 18+
* TinyTrack website ID

<Steps>
  <Step title="Setup">
    ```sh theme={null}
    git clone https://github.com/tinytrack-io/cloudflare-worker
    cd tinytrack-cloudflare-worker
    npm install
    npx wrangler login
    ```
  </Step>

  <Step title="Add tinytrack websiteId secret">
    ```sh theme={null}
    npx wrangler secret put TINYTRACK_WEBSITE_ID
    ```
  </Step>

  <Step title="Deploy">
    ```sh theme={null}
    npm run deploy
    ```
  </Step>

  <Step title="Cloudflare configuration">
    **Workers & Pages → tinytrack-cloudflare-worker → Domains → Add Route**, e.g. `example.com/*`, covering the whole site.
  </Step>
</Steps>

## Reducing Worker Invocations

A `example.com/*` route sends every request through the worker, including assets it just passes through. The worker only needs to see **HTML document requests** and **`/_tinytrack/*`**. To stop paying invocations for the rest, add routes with the Worker set to **None** for your high-volume static prefixes.

To add exclusions:

1. Go to **Cloudflare → Domains**
2. Go to your domain **example.com**
3. Go to **Workers routes**
4. Add routes you want to exclude with **Add Route**
5. Worker should be **None**

Route patterns match path prefixes only (no file extensions) and a route without a Worker negates broader patterns, see the [Workers routes docs](https://developers.cloudflare.com/workers/configuration/routing/routes/).

Example exclusions:

* `example.com/_app/immutable/*` (SvelteKit)
* `example.com/_next/static/*` (Next.js)
* `example.com/assets/*`
* `example.com/static/*`
* `example.com/images/*`
* `example.com/api/*`

## Configuration

| Var                     | Default                       | Notes                                                                            |
| ----------------------- | ----------------------------- | -------------------------------------------------------------------------------- |
| `TINYTRACK_WEBSITE_ID`  | (none)                        | **Required.** Public by design.                                                  |
| `TINYTRACK_DOMAIN`      | request hostname minus `www.` | **Set explicitly when your route spans multiple subdomains**, or sessions split. |
| `INJECT_SCRIPT`         | `"true"`                      | `"false"` = server-side pageviews only.                                          |
| `TINYTRACK_PATH_PREFIX` | `/_tinytrack`                 | First-party paths the worker serves itself.                                      |
| `TINYTRACK_DEBUG`       | `"false"`                     | `"true"` = step-by-step debug logs for HTML document requests.                   |

Only `TINYTRACK_WEBSITE_ID` is declared in `wrangler.jsonc`, so it is the only field shown on the one-click deploy setup page. The optional vars fall back to the defaults above; to override one, add it in **Workers & Pages → Settings → Variables** (kept across deploys, the config sets `keep_vars`) or to the `vars` block in `wrangler.jsonc`.

<Note>
  Already have the TinyTrack script in your HTML? Remove it, or set `INJECT_SCRIPT` to `"false"`. Running both causes duplicate client-side events.
</Note>

## What Gets Tracked

* **Server-side:** one `page_view` per HTML request (any status). Static assets, `/api/`-style paths, prefetches, and non-GET requests are skipped.
* **Client-side:** SPA navigations, outbound clicks, goals, scroll depth, session pings, custom events. The injected script skips the initial pageview, so there is no double counting.
* Bots are recorded for crawler and [AI traffic](/tracking/ai-traffic) analytics.

## Troubleshooting

* `npx wrangler tail` shows live logs; pageview failures log as `[TinyTrack] pageview tracking failed`.
* No data? Check the route covers the page and `TINYTRACK_WEBSITE_ID` is set.
* Client events missing? Check the browser console for `/_tinytrack/tracker.js` (usually CSP or a leftover manual snippet).

## Uninstall

Remove the Worker Route and your site instantly serves direct from origin. Then `npx wrangler delete` when done. Roll back a bad deploy from **Workers & Pages → Deployments → Rollback**.
