# askbowtie tracking reference

Machine-friendly reference for the askbowtie tracker. Everything here is current and verified against the shipped tracker (v6.0). Human-readable version: https://askbowtie.com/docs/

## Install

One tag, in `<head>`, on every page:

```html
<script src="https://askbowtie.com/bowtie.js" async></script>
```

`async`, not `defer`: the tracker captures errors that happen during page parse. Never version the URL. The domain must be registered at askbowtie.com or the tracker disables itself.

## Tracked automatically (zero config)

| Signal | Event types |
|--------|-------------|
| Page views and sessions | `page_load`, `session_start`, `page_hidden` |
| Clicks | `click`, `external_link_click`, `rage_click` |
| Forms | `form_submit` |
| Errors | `console_error`, `resource_error`, `network_error`, `csp_violation` |
| Performance | `web_vitals` (LCP, CLS, INP, TTFB) |

UTM parameters and ad click IDs (gclid, msclkid, fbclid) are captured on landing and survive internal navigation. No cookies. No PII: input values are never read, query-string PII is redacted.

## Public API

The API lives at `window.bowtie` after the script loads. The script is async, so guard calls that could run before load with optional chaining: `window.bowtie?.track(...)`. In user-action handlers (clicks, submits) the tracker is always ready.

### Custom events

```js
bowtie.track(eventType, data?)

bowtie.track('signup_started', { source: 'homepage_cta' });
bowtie.track('plan_selected', { plan: 'agency', seats: 5 });
```

`eventType` is a string you choose. `data` is a flat object of context, queryable later through MCP.

### Conversions and revenue

```js
bowtie.converted(goalName, details?)

bowtie.converted('purchase', { value: 99.00, currency: 'USD', transaction_id: 'ord_1842' });
bowtie.converted('lead_captured', { source: 'contact_form' });
bowtie.converted('trial_started');
```

| Field | Type | Notes |
|-------|------|-------|
| `value` | number | Revenue or goal value. Optional. |
| `currency` | string | ISO code, default `USD` |
| `transaction_id` | string | Dedupe key: the same conversion never counts twice |
| `pixels` | boolean or string | Also fire to connected ad platforms. `true` = primary Google Ads label, `'secondary'` = secondary label, default off |
| `email`, `phone` | string | Enhanced conversions, hashed by gtag before leaving the page. Only used when `pixels` fires |

Any other keys you pass are stored with the event.

### Application errors

```js
bowtie.error(code, details?)

bowtie.error('payment_declined', { reason: 'insufficient_funds', amount: 99.00 });
bowtie.error('validation_failed', { field: 'email' });
```

For errors your own code catches. Uncaught JS errors, failed resources, and failed fetches are captured automatically.

### Guardrails

```js
bowtie.guardrail(code, details?)

bowtie.guardrail('rate_limited', { endpoint: '/api/checkout', limit: '10/min' });
bowtie.guardrail('geo_blocked', { country: 'XX' });
```

Intentional blocks that are not failures: rate limits, quota, access denied, feature flags. Kept separate from errors so error rates stay honest.

### Utilities

```js
bowtie.getSessionId()   // current session id (for support/debugging)
bowtie.flush()          // send the queue now (before a hard navigation)
bowtie.debug(true)      // tag this tab's events debug:true; persists across pages
bowtie.debug(false)     // off
```

### Legacy

`window.itbroke` is an alias of `window.bowtie`. Sites migrated from itbroke.dev keep working unchanged.

## Querying the data

All of it is queryable by an AI agent through MCP:

```
claude mcp add --transport http askbowtie https://askbowtie.com/mcp \
  --header "Authorization: Bearer YOUR_TOKEN"
```

Tools: `list_domains`, `get_summary`, `get_traffic`, `get_conversions`, `get_incidents`, `get_alerts`, `get_performance`, `get_page`. Custom events, conversions with revenue, errors, and guardrails all come back with their data fields intact.

## Event payload (reference)

Each event the tracker sends:

```json
{
  "event_type": "conversion",
  "page": "/pricing",
  "ts": 1781157492.3,
  "goal": "purchase",
  "value": 99.00,
  "currency": "USD",
  "transaction_id": "ord_1842"
}
```

Events batch into `POST https://askbowtie.com/api/ingest` as `{ domain, session_id, events: [...] }`. You normally never call this directly; the tracker does.
