# Debugging

> Check the ClickClacks tracker is running, watch its requests, confirm events in Realtime, Events and source health, and fix the usual problems: ad blockers, unlisted hostnames, opt-outs, missing clicks and custom events that never arrive.

- Canonical URL: https://clickclacks.io/docs/debugging
- Section: Tracking
- Last updated: 2026-09-26

Events not showing up? Work down three checks, in order: is the tracker running, are requests going out, did they arrive. Most problems show up at the first one.

## 1. Is the tracker running? {#running}

Open your site on one of its listed domains, then the browser’s developer console:

```js title="console"
// In the browser console, on your site
typeof window.clickclacks?.optOut
// 'function'  → the tracker is running
// 'undefined' → it hasn't started (see below)

window.clickclacks?.q
// An array    → your queue stub is there, but c.js hasn't started yet

localStorage.getItem('cco')
// '1'         → this browser opted out; run clickclacks('optIn') to undo
```

If it hasn’t started, one of these is true:

- **The script didn’t load.** An ad blocker, a privacy extension or your [Content Security Policy](https://clickclacks.io/docs/install.md#csp) blocked `c.js`. Check the Network tab for it.
- **The hostname isn’t listed.** The page’s hostname must match an entry in `data-domains` exactly: `www.acme.com` and `acme.com` are different.
- **`data-key` is missing**, or was stripped by whatever inserted the tag. Compare the tag in the Elements panel with the one on the source’s page.
- **Storage is blocked.** The tracker needs local and session storage, and stays off quietly where the browser refuses them.

## 2. Are requests going out? {#network}

In the Network tab, filter for `ingest` (or `/e` on a [custom domain](https://clickclacks.io/docs/custom-domain.md)). Events are batched, so a request goes out every 5 seconds, as soon as 25 events are waiting, and when you switch tab.

```http title="request"
POST https://app.clickclacks.io/api/ingest?key=pk_live_3f9a1c7e5b2d4f6a8c0e1b3d
Content-Type: text/plain

HTTP/1.1 202 Accepted
{"accepted": 3}
```

| Response | What it means |
| --- | --- |
| `202 {"accepted": n}` | Received. n can be 0 when every event was filtered out: a known bot’s user agent, or clicks with click autocapture off. |
| `403` | Refused. The page’s origin isn’t in the source’s saved domains, or the key is wrong. Check the hostname in the address bar against the source’s domains. |
| `400` | The request body wasn’t valid. The tracker never sends one; look for a second, modified copy of it. |
| `410` | Your custom domain has been live for more than 30 days, and this page still loads c.js from app.clickclacks.io. Update its snippet. |
| `503` | Temporarily unavailable. The tracker keeps the events and retries with the next batch. |

## 3. Did they arrive? {#in-the-app}

- **Realtime** shows who is on your site now and every event as it arrives, over the last 30 minutes. Filter it to one source.
- **Events**, under Data, lists every event with its properties. Search for a custom event by its exact name.
- **Sources** shows each source’s health: _Waiting for events_ until the first one, _Receiving_ when the last event was under 30 minutes ago, _Quiet_ after that, and _Stopped sending_ after 24 hours without one.

Reports such as Overview and Insights fill in as traffic arrives, usually within a minute.

## Common problems {#problems}

### Nothing from my own browser {#own-browser}

Usually an ad blocker or privacy extension. Try a private window with extensions off. If you opted out while testing a consent banner, that choice is remembered: run `clickclacks('optIn')` or clear the site’s data.

### Nothing from localhost {#localhost}

`localhost` isn’t one of your listed domains, so the tracker stays off there, which also keeps development traffic out of your data. Test on a deployed preview whose hostname you’ve added to the source.

### Pageviews arrive but no clicks {#no-clicks}

Check **Autocapture clicks** is on in the source’s settings. The tracker also turns click capture off for a page when it can’t reach ClickClacks for its settings, which a Content Security Policy without `app.clickclacks.io` in `connect-src` causes.

### A custom event never arrives {#custom-event-missing}

Invalid calls are ignored without an error. Check that the name is 1 to 128 characters and doesn’t start with `$`, and that properties are a plain object (not `null`, an array or a class instance). If the call runs before `c.js` loads, add the [queue stub](https://clickclacks.io/docs/events.md#before-load) or it is skipped. An event whose properties are over 2 KB arrives without them.

### Every pageview counted twice {#double-counting}

The tag is on the page twice: in the HTML and again from a tag manager, a plugin or a component. Keep one.

### Every page shows the same path {#same-path}

Your app routes with the URL hash (`/#/settings`), which is never sent. See [hash routers](https://clickclacks.io/docs/single-page-apps.md#hash).

### One person shows up as several {#identity-split}

Call `identify` on every domain where they’re signed in, use the same ID everywhere (including your backend), and call `reset` on sign-out. Links between your domains carry identity only when both hostnames are listed; the carry-over rate on **Sources › Identity** tells you how often it works.

## Server-side events {#server}

Send the batch with `?validate=true`: the response shows every item exactly as it would be stored, with every error, and nothing is stored. Error responses carry a stable `code` and a link to its explanation. See [dry runs](https://clickclacks.io/docs/api.md#validate) and [errors](https://clickclacks.io/docs/api.md#errors).

## Next steps {#next}

- [Install the tracker](https://clickclacks.io/docs/install.md): placement in every framework.
- [Domains and identity](https://clickclacks.io/docs/domains.md): listing hostnames.
- [Limits](https://clickclacks.io/docs/limits.md): sizes and rates in one table.
