MIRA FIVE

Verify and debug

Confirm an install works, read the server's receipt and refusals, and find out why events or flags are missing.

Use this page to confirm that events reach MIRA FIVE, and to find out why they do not. Every check below works without the dashboard except the last step, the live view. For the codes themselves, see Errors.

Check an install

In the browser:

  1. Open the site on its real domain. From localhost, nothing is sent unless you allow it (see Localhost).
  2. Open the browser's developer tools on the Network tab.
  3. Send the queue now instead of waiting up to 5 seconds: run mirafive('flush') in the console for the script tag, or call mira.flush() in your code.
  4. Find POST https://events.mirafive.io/v1/batch/mf_…. It answers 202 with a receipt:
{ "batch": "0192d4a8-7b1c-4e8a-9c1d-2b3e4f5a6b7c", "accepted": 1, "dropped": 0 }
  1. Open the source's live view in MIRA FIVE and find the event.
Receipt fieldMeaning
batchThe batch id the SDK sent
acceptedEvents stored
droppedEvents not stored
reasonPresent when nothing was kept: bot, install_check, ingestion_paused or allowance_exhausted

A 202 is final, also when it kept nothing. The reasons:

ReasonCause and fix
botA website key received a batch from a bot user agent: a crawler, a headless or automated browser (Playwright, Puppeteer, Selenium, Lighthouse), or a request without a user agent. Test with a normal browser.
install_checkThe batch held only $install_check events. Expected, see Install check.
ingestion_pausedYour organization's ingestion is paused.
allowance_exhaustedThe plan's monthly event allowance is used up.

For a server, send an install check and read the receipt, or pass onError and watch it.

Localhost

Browser SDKs send nothing from localhost, 127.*, [::1], *.local or a file: page, so development does not pollute your numbers. To send from there:

<script defer src="https://cdn.mirafive.io/mira.js" data-key="mf_…" data-track-localhost></script>

The Astro integration is also off in astro dev unless you pass dev: true (see Astro).

The server always accepts localhost and 127.0.0.1 as origins, so you do not add them to a source's allowed origins. Use a separate source for development if you want to keep test events apart.

Install check

$install_check is an event that proves a key and a host work. The server answers it with a receipt and never stores or bills it:

curl https://events.mirafive.io/v1/batch \
  -H "Authorization: Bearer $MIRAFIVE_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{"v":1,"batch":"0192d4a8-7b1c-4e8a-9c1d-2b3e4f5a6b7c","mode":"full","events":[{"name":"$install_check"}]}'

The answer:

{ "batch": "0192d4a8-7b1c-4e8a-9c1d-2b3e4f5a6b7c", "accepted": 0, "dropped": 1, "reason": "install_check" }

mirafive:check prints the host, the key's namespace and the mode, sends the check and fails unless the reason is install_check. The install check runs before the bot filter, so curl works with a website key too: POST /v1/batch/mf_… with the same body and no Authorization header.

Refusals

A refused batch answers with an error body, { "code": "…", "detail": "…" }:

Status and codeCauseFix
401 unauthorizedThe key is missing, unknown, revoked or archivedCopy the key again from Keys. Servers read MIRAFIVE_SECRET_KEY
403 origin_not_allowedThe page's origin is not in the source's allowed originsAdd the site's domain to the source. www. and the bare domain count as one site
403 website_key_as_bearerA website key was sent as Authorization: BearerServer code needs the secret key of a server source
403 secret_key_in_pathA secret key was put in a browser URL. The key is now marked exposedBrowsers use the website key. Rotate the secret key
403 secret_key_exposedFlags only: a secret key arrived with browser headersRotate the key, and keep it out of browser code
403 lookup_not_allowedFlags only: a segment lookup on a consentless sourceUse a full source, or no targeting consent in the page
400 collection_mode_not_allowedA full batch to a consentless sourceSwitch the source to full, or send consentless
400 validation_failedAn event breaks a rule; errors names it, such as events.0.nameSee event names and property limits
400 invalid_jsonThe body is not valid JSON, often a string cut inside a characterUse an SDK, or send well-formed UTF-8
413 payload_too_largeThe body is over 1 MiBSend fewer events per batch
429 rate_limitedToo many requests or eventsWait for Retry-After; the SDKs do

The browser SDKs show the code as a development warning ([mirafive] batch: origin_not_allowed). MIRA FIVE also records refusals that come after the key check on the source, so you can see them there.

Nothing arrives

Work down this list:

  1. The page runs on localhost or another local host without trackLocalhost (see Localhost).
  2. Do Not Track or Global Privacy Control is on in your browser. The browser SDKs then send nothing, by design. Test in a profile without them.
  3. window.__mirafive_ignore is set, for example because you are signed in as an admin (see Ignore your own visits).
  4. The page is in full mode and no statistics consent was given. Full mode sends nothing before the grant (see Consent).
  5. The page's Content Security Policy blocks the request. Allow connect-src https://events.mirafive.io (or your host), and for the script tag script-src https://cdn.mirafive.io.
  6. The receipt says dropped with a reason, or the request is refused (see above).
  7. Server events: the process ended before the buffer was sent (see Batching and flushing), or onError reports a failure.

Development warnings

Browser SDKs log warnings starting with [mirafive] only on a local host name (localhost, 127.*, [::1], *.local, file:), once per message. To see warnings about the server's answers, develop on localhost with trackLocalhost: true.

WarningMeaning
local host: set trackLocalhostNothing is sent from this host
bad name: …track() got an empty, too long or $ name
event dropped: …The event's properties break a limit, so it was dropped alone
batch: …The server refused the batch (the code) or kept nothing (the reason)
batch droppedA batch failed three times and was given up
consent() needs its plugin (or another method)The client lacks the plugin: identity(), flags(), siteSearch()
identity() needs mode "full"identity() is in a consentless client
siteSearch() does nothing in mode "consentless"Site search needs full mode
identify() needs a user id of 1–256 charactersThe user id is empty or too long
identify(): the id looks like an emailPass your internal id instead
flag "…" is unknownThis source's flags have no such key
second client stays inertcreateMira() ran twice on one page; the second client does nothing

The script tag logs these on every host, since they mean a broken install: [mirafive] no data-key, [mirafive] bad key (the data-key is not a website key), [mirafive] no script tag, and [mirafive] <feature> chunk failed (a part of the script was blocked by the network, a Content Security Policy or an integrity check).

createMira() throws a TypeError for a secretKey option, a host without a scheme, and mode: 'full' without identity(). Server SDKs report failures to onError, or log [mirafive] … without one.

Tests

Keep tests from sending events:

SDKIn tests
LaravelMira::fake(), then assertTracked(), assertNotTracked(), assertIdentified(), assertNothingTracked(). See Laravel
Symfonymirafive: { test: true } under when@test, then the InteractsWithMira trait and MiraFake. See Symfony
PHPnew Mira(enabled: false) sends nothing and needs no key, but still refuses bad input. See PHP
@mirafive/sdk-serverPass a fetch function to new Mira() and assert on the requests it receives. See Node.js and edge

The fakes still check every event, so an event MIRA FIVE would refuse fails the test as it would fail in production.

On this page