# Troubleshooting for developers

> Every answer the collector, the server API and the raw event API give, and the common reasons a website sends nothing, with the cause and the fix.

Source: https://docs.bifrostorbit.com/insights/developers/troubleshooting/

Start with the browser's developer tools. On the **Network** tab, find the `POST` to `collect` (on `api.bifrostorbit.com`, or your own address with a proxy) and read its status and answer. Errors answer with `{ "error": { "code", "message" } }`.

## The script sends nothing

If there is no request to `collect` at all:

| Cause | Fix |
| --- | --- |
| The script tag has no `data-site`, or the script didn't load | Check the tag. In **Network**, `script.js` should answer `200` or `304`. |
| An ad blocker or browser privacy setting blocked `script.js` | Try a private window without extensions. To lose fewer visitors, [serve it from your own domain](https://docs.bifrostorbit.com/insights/developers/first-party-proxy/). |
| Your `Content-Security-Policy` blocks it | The console says so. Allow `https://api.bifrostorbit.com` in `script-src` and `connect-src`. |
| The browser sends Do Not Track or Global Privacy Control | By design, nothing is sent. Switch it off to test. |
| The browser is automated, such as Playwright, Puppeteer or Selenium (`navigator.webdriver`) | By design, nothing is sent from end-to-end tests. |
| The browser opted out, or was marked as your team's | `localStorage['insights:off']` is set on your website. Open a page with `#insights-on` at the end of the address and confirm, or run `insights.optIn()` in the console. |
| The script has `data-consent="wait"` and the page hasn't called `insights.consent()` | Call it once the visitor agrees, on every page. See [The script](https://docs.bifrostorbit.com/insights/developers/the-script/). |
| The tab is in labelling mode (`?insights-label=` in the address) | Labelling mode counts nothing. Open the page without it. |
| A Next.js website reads the site key from `NEXT_PUBLIC_INSIGHTS_SITE`, but the build ran without it | `NEXT_PUBLIC_` settings are fixed at build time, and `CmsInsights` renders nothing without a key. Set it for the build, or read the key as a server setting when the page renders. |

The script sends events up to two seconds after they happen, and at once when the page is hidden, so a request can appear a moment after the page loads.

## Answers from collect

| Status and code | Cause | Fix |
| --- | --- | --- |
| `202` with `accepted` above 0 | Taken. Reports show it within a few seconds. | |
| `202` with `accepted: 0` | Taken but left out on purpose: Do Not Track or Global Privacy Control, a bot (or a request without a `User-Agent`, as from a proxy that doesn't pass it on), one of the site's excluded addresses, referrer spam, a data-centre address, or automatic events the site switched off | **What was left out** on the overview counts each reason. From your own server or a VPN, the data-centre filter is the usual cause. |
| `400` `invalid_json` or `invalid_events` | The body isn't a batch the collector takes: over 50 events, a detail over the limits in [Send your own events](https://docs.bifrostorbit.com/insights/developers/send-events/), or `revenue` without `currency` | Check what you send with `insights.track`. One bad event refuses the whole batch. |
| `403` `wrong_origin` | The page's address or the request's `Origin` isn't one of the site's addresses | Add the address under **Site settings**. `www.` and the bare domain count as one, but `*.northwilds.com` doesn't include `northwilds.com`. For testing on your computer, add `localhost`. |
| `403` `wrong_proxy_token` | Your proxy sent a token that isn't this site's, or one that was replaced or removed | Copy a new token from **Site settings**, **First-party proxy**, into `INSIGHTS_PROXY_TOKEN` and redeploy. See [Serve Insights Orbit from your own domain](https://docs.bifrostorbit.com/insights/developers/first-party-proxy/). |
| `404` `unknown_site` | Wrong site key, or the site is in the bin | Copy the key from **Install**. Restore the site from **Bin**. |
| `413` `too_large` | The request is over 64 KB | Send fewer or smaller details. |
| `429` `rate_limited` | More than 120 requests a minute from one address | Usually a proxy without a token: every visitor shares your server's address. Add the proxy token. |

## Visits arrive, but the numbers look wrong

| Symptom | Cause | Fix |
| --- | --- | --- |
| Every visit is in your server's country, and visitors are low | A proxy or rewrites pass visits on without the visitor's address | Use a proxy route with the proxy token. |
| Visits stop after adding a proxy, and **What was left out** shows data centres | The collector sees your server's address, which is in a data centre | Add the proxy token, or switch **Leave out data centres and hosting networks** off. |
| The proxy has a token, but visits still show the server's country | Your website isn't behind a proxy that sets `CF-Connecting-IP`, `X-Real-IP` or `X-Forwarded-For`, so there is no address to pass on | Run it behind one, or pass the address yourself in `X-Insights-Forwarded-For`. |
| Events go to `/insights/v1/collect` on your own domain and answer `404` | `src` points to your domain, but `data-api` (`api` in `CmsInsights`) isn't set | Set it to your collect address, such as `/stats/collect`. |
| `POST` to `/stats/collect` is redirected | `trailingSlash: true` in `next.config.ts` | Use `/stats/collect/`. |
| A website that changes pages without reloading counts only the first page | The script follows `history.pushState` and the back and forward buttons. A router that changes the address another way isn't followed. | Change pages with `history.pushState`, as Next.js, React Router and most routers do. |
| Page views aren't tied to CMS Orbit entries | No `<meta name="insights-content">` | Add `insightsMetadata(page)` or `CmsInsights page={page}`. See [Connect Insights Orbit with the CMS Orbit SDK](https://docs.bifrostorbit.com/insights/developers/cms-orbit-sdk/). |
| Known users don't show | The site doesn't have known users switched on, or the script has no `data-known-users` | See [Send user ids for known users](https://docs.bifrostorbit.com/insights/developers/known-users/). |

## Labelling mode

| Message | Fix |
| --- | --- |
| `This labelling link has ended. Open labelling mode again from Insights Orbit.` | Labelling passes are short-lived. Open it again from **Labels**. |
| `Labelling mode only works on the site's own addresses` | Open the page on one of the site's addresses. |
| `Labelled events are not in your organisation's plan.` | Labels come with Growth and up. |

With your own proxy, pass on `/labels`, `/label.js` and `/labelling` as well as `script.js` and `collect`. `createInsightsProxy` and `insightsRewrites` do.

## Server API, raw event API and GraphQL

| Status and code | Cause |
| --- | --- |
| `401` `unauthorized` | No key, a wrong key, or a removed one. Send `Authorization: Bearer ins_live_…`. |
| `403` `wrong_scope` | The key may only send events, or only read them. Make a key that may do both under [API keys](https://docs.bifrostorbit.com/insights/developers/api-keys/). |
| `403` `not_in_plan` | Reading raw events comes with Growth and up. |
| `404` `unknown_site` | No site with that key in the key's organisation, or it is in the bin. |
| `400` `invalid_events` | A server event isn't valid: the message names the field, such as an event more than 7 days old, in the future, or with an address that isn't the site's. |
| `400` `invalid` or `invalid_cursor` | A date or `type` isn't valid, `from` isn't before `to`, or a cursor came from somewhere else. |
| `429` `rate_limited` | Over the key's limit per minute. Wait a minute. |

The [API playground](https://docs.bifrostorbit.com/insights/developers/api-playground/) shows the same answers from your browser.
