# Site Tracking shows no events

> A checklist for when Site Tracking receives nothing: the test request, the site key, the environment, the middleware, skipped requests and caching.

Source: https://ranqo.ai/docs/guides/troubleshooting/site-tracking-no-events

Site Tracking is built to fail quietly. The snippet never waits for Ranqo, and the intake endpoint answers every report it accepts or refuses with HTTP 200, so a broken install never slows or breaks your site. It also means nothing tells you it is broken. Work through the checks below from the outside in.

## 1. Send a test event

Run this from a terminal, with your own key in place of the placeholder:

```bash
curl -sG "https://app.ranqo.ai/api/v1/intake/pageview" \
  --data-urlencode "url=https://example.com/test" \
  --data-urlencode "userAgent=Mozilla/5.0 (compatible; GPTBot/1.0)" \
  --data-urlencode "ref=" \
  --data-urlencode "ip=1.2.3.4" \
  --data-urlencode "websiteKey=rk_live_YOUR_SITE_KEY"

# Expected: {"ok":true}
```

- **`{"ok":true}`**: Ranqo accepted the key. The **Install Site Tracking** page, reached from **Traffic**, reads **Working — first event received** once the event lands, naming GPTBot and the path `/test`. The test stays in your data as a GPTBot visit; see [Verify your install](https://ranqo.ai/docs/integrations/site-tracking/verify). If the test works but real visits never arrive, the problem is on your site: go to [step 3](#3-check-the-environment-variable).
- **`{"ok":false}`**: Ranqo refused the request. Go to step 2.
- **An error status, with no `ok` answer**: a failure on Ranqo's side. Run the test again.

## 2. When the answer is `{"ok":false}`

The endpoint gives the same answer for every refusal, so it cannot be used to probe keys. The causes are:

- **A malformed key.** A key is `rk_live_` followed by 40 lowercase hexadecimal characters, exactly as the install page shows it. Quotes, a trailing space or newline, or a key cut short while copying all make it malformed.
- **An unknown or revoked key.** Check it against the key on the **Install Site Tracking** page. If that page offers **Generate site key**, the brand has no active key. See [Site keys](https://ranqo.ai/docs/integrations/site-tracking/keys).
- **A missing or malformed request.** The `url` or `websiteKey` parameter is missing, or a value is far longer than a real URL or User-Agent.
- **Too many events at once.** Each key accepts up to 100 events per second. Events above that in the same second are dropped; the next second starts again.

## 3. Check the environment variable

Every snippet reads the key from `RANQO_SITE_KEY`.

- **Set it where production runs.** A key in your local `.env` file does not reach your host. Add it in your hosting provider's environment settings, for every environment you want tracked.
- **Redeploy after adding it.** Most hosts apply a new environment variable only to the next deployment.
- **Check the brand.** Each key belongs to one brand, and its visits appear on that brand's Traffic page only. A key copied from another brand sends your visits there. A key whose brand has been deleted is still accepted, and its visits are recorded under that brand, where no page shows them.

If the variable is missing, the Next.js snippet and the Cloudflare Worker send the word `undefined` as the key, and the other snippets send an empty key. Both are refused.

## 4. Check the snippet runs

**Next.js.** The middleware file must sit where Next.js looks for it: at the root of the project next to `app/` or `pages/`, or inside `src/` if your app lives there. On Next.js 16 the file is `proxy.ts` and the exported function is `proxy`. A project has one middleware file, so if you already have one, merge the Ranqo logic into it and combine the two `matcher` lists. See [Next.js](https://ranqo.ai/docs/integrations/site-tracking/nextjs).

**Express.** Register `app.use(ranqoIntake)` before your routes and before any static file handler, or requests answered earlier never reach it. The snippet uses the built-in `fetch`, which needs Node.js 18 or later. See [Express](https://ranqo.ai/docs/integrations/site-tracking/express).

**Cloudflare Worker.** The Worker must be attached to a route that covers your site's pages, and `RANQO_SITE_KEY` must be set as a variable or secret on that Worker. See [Cloudflare Worker](https://ranqo.ai/docs/integrations/site-tracking/cloudflare-worker).

**Other backends.** Fire the request after your handler has returned, in the background. See [Any backend](https://ranqo.ai/docs/integrations/site-tracking/any-backend).

## 5. Requests the snippet skips on purpose

The snippets count page views, not every request. These are skipped by design:

- **Anything but `GET`.** Form posts, `HEAD` and `OPTIONS` requests are not page views.
- **Prefetch and in-app navigation.** When a visitor hovers or clicks a link inside a Next.js app, the browser fetches the next page's data in the background rather than loading a new document. The snippet skips those requests, so a visitor who clicks around your site counts once per full page load. Crawlers load full pages, so they are unaffected.
- **API routes**, any path starting with `/api/`.
- **Images, fonts, scripts, styles and other `.txt`, `.xml` and `.json` files.** `robots.txt`, `llms.txt`, `llms-full.txt`, `ai.txt`, `sitemap.xml` and `/.well-known/*` are kept, because AI crawlers read them first.
- **Hosts in `SKIP_HOSTS`.** The list at the top of the snippet is for a dashboard or admin subdomain you do not want counted. If your public site's host is in it, nothing is sent.

## 6. Cached pages never reach your server

A snippet in your server only sees requests that reach your server. If a CDN or cache in front of it serves a page, that visit is never reported, and neither is a crawler served from the cache.

A snippet that runs at the edge ahead of the cache, like the [Cloudflare Worker](https://ranqo.ai/docs/integrations/site-tracking/cloudflare-worker), sees every request. If your pages are cached at Cloudflare, use it instead of middleware in your server.

## 7. Requests Ranqo drops after accepting them

A few requests are answered `{"ok":true}` and then dropped when they are processed, because they are never real visits:

- paths that vulnerability scanners probe, such as `/.env` files, `/wp-admin` or `/wp-login.php`;
- requests whose User-Agent is a URL, which only exploit probes send.

A test event sent to one of those paths succeeds and still shows nothing.

## Where events appear

**The install page** checks for your first event every few seconds. After you click **I've installed it — verify now**, it reads **Listening for your first event**.

When an event arrives, the page changes to **Working — first event received**, whether or not you clicked.

**The Traffic page** shows the Site Tracking view once the brand has an active key and at least one visit falls in the date range, which defaults to the last 30 days. Until then it links back to the install page: while neither source has data, the Site Tracking card reads **Continue install** once a key exists (**Set up Site Tracking** before that), and once Google Analytics has data the link is **Add Site Tracking**. Without an active key, visits recorded earlier are hidden too, until the brand has a new key.

## Related

- [Verify your install](https://ranqo.ai/docs/integrations/site-tracking/verify): Send a test event and read the result.
- [Site keys](https://ranqo.ai/docs/integrations/site-tracking/keys): Create, copy and look after your key.
- [Traffic](https://ranqo.ai/docs/guides/traffic): Read the Site Tracking view.
