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

# Validate and debug an implementation

> Find the failing boundary quickly, then prove loading, events, payloads, API scope, and MCP work.

Debug one boundary at a time. First prove Bily loaded. Then prove your application called the intended event. Finally, confirm the payload and Bily scope.

## Write the expected result first

Before you open developer tools, describe the expected result in one sentence.

```text theme={null}
After a successful checkout, one Order Completed event should contain order_789,
two products, USD 73 total, and no private payment fields.
```

A precise expectation makes duplicates, missing fields, and premature events easier to spot than a broad “tracking is broken” report.

## Prove the browser installation

For `@bilyai/js`, turn on lifecycle diagnostics temporarily:

```typescript theme={null}
import { init, ready } from "@bilyai/js";

init({
  scriptUrl: "https://tracking.example.com/b.js?shop=store.example.com",
  debug: true,
});

await ready();
```

Check each boundary in order:

1. The page contains exactly one Bily script.
2. Its full URL matches **Bily > Settings > Apps > More settings > Install tracking**, including query parameters.
3. The browser requests that URL once.
4. `ready()` resolves in client-mounted browser code.
5. The application reaches the intended `track()` call once.
6. The event appears with the expected name and safe payload in the selected Bily store.

`ready()` proves the browser runtime can accept queued calls. It does not acknowledge an event or prove ingestion.

## Prove each page view once

Test this sequence:

| Action                                | Expected result                    |
| ------------------------------------- | ---------------------------------- |
| Direct page load                      | One automatic `PageView`           |
| Browser reload                        | One new automatic `PageView`       |
| Later SPA navigation                  | One explicit `PageView`            |
| Component rerender without URL change | No new page view                   |
| Back or forward navigation            | One event per committed URL change |

If a direct load produces two events, check for both installation paths and remove the manual page-view call from the initial mount.

## Compare the payload with the plan

Compare the observed payload with your event plan—not only the TypeScript type.

* Is the event name spelled and capitalized exactly?
* Did it fire only after the outcome succeeded?
* Are IDs stable and from the intended environment?
* Are numbers finite and in the expected unit?
* Are product quantity and order totals correct?
* Is the customer context permitted for this event?
* Are secrets, raw errors, and unreviewed form values absent?

For order events, provide `order.total` when it is authoritative. Otherwise, the SDK calculates the total from `order.products`.

## Read each SDK signal correctly

| Observation                                        | Meaning                                                                        |
| -------------------------------------------------- | ------------------------------------------------------------------------------ |
| `ready()` times out                                | The script did not provide a usable Bily runtime before the configured timeout |
| `track()` returns                                  | The call was accepted locally; it is not an ingestion receipt                  |
| Debug warning about delivery                       | The browser delivery attempt failed                                            |
| `getBilyTrackingId()` returns `null` on the server | Expected server-rendering behavior                                             |
| Oldest early event is missing                      | The bounded pre-load queue may have reached `maxQueueSize`                     |

The default queue holds 100 calls and can be configured from 1 to 1,000. The default load timeout is 15 seconds and can be configured from 1,000 to 60,000 milliseconds.

## Start API validation with discovery

Discover your scope before you call a store-specific endpoint:

1. `GET /context` without `organizationId` for an ordinary store-scoped key
2. An exact `organizations[].stores[].url` from the response
3. A read-only store endpoint using that returned store URL

Use the optional `organizationId` query only when the authenticated identity can access multiple organizations and the workload intentionally selects one.

Save `x-request-id` from every response.

| Status              | First check                                                                                                                |
| ------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| `400`               | Path, query, body, organization header, and store URL format                                                               |
| `401`               | Missing, expired, revoked, or invalid credential                                                                           |
| `403`               | Permission and organization/store scope; regenerate an older settings-generated key when the response requires store scope |
| `404`               | Returned resource ID or accessible store scope                                                                             |
| `429`               | Request rate and retry backoff                                                                                             |
| `500`, `502`, `504` | Request ID, safe retry policy, and requested range                                                                         |

Before you retry a write, use a read to prove whether the first request took effect.

## Separate MCP discovery from execution

Follow this sequence:

1. Confirm the endpoint is exactly `https://api-dispatcher.bily.ai/mcp`.
2. Confirm the client completed Bily Connect or uses one valid fallback key.
3. Call `search` with the outcome, store URL when relevant, and a limit from 1 to 20.
4. Inspect the returned helper, schema, risk guidance, and verification step.
5. Review the complete async function before approving `execute`.
6. Verify any write with the recommended read.

An `execute` function can contain several helper calls. It has no direct outbound network access and can run for at most 20 seconds.

## Make a support report actionable

Provide:

* environment and selected Bily store;
* SDK or client version;
* exact safe event or operation name;
* expected and observed result;
* minimal reproduction steps;
* timestamp and Bily request ID when available;
* browser or client error text with customer data removed.

Never include credentials, raw customer payloads, session data, or full request headers.

<CardGroup cols={2}>
  <Card title="SDK troubleshooting" icon="screwdriver-wrench" href="/troubleshooting" />

  <Card title="Customer FAQ" icon="circle-question" href="/troubleshooting/faqs" />
</CardGroup>
