# Pintail SDK

The Pintail SDK is a lightweight TypeScript client for sending events to the
[Pintail](https://pintail.io) event-tracking API. It exposes a small `Client`
class — and a ready-to-use default instance — that lets your application record
named events, optionally enriched with structured extras, with a single
`track()` call. The SDK is dependency-free at runtime, uses the platform's
built-in `fetch`, and ships with full TypeScript type definitions.

## Usage

### Server Side

Install the package:

```bash
npm install @basetime/pintail-sdk-ts
```

Then, use the `pintail` instance to track events:

```ts
import { pintail } from '@basetime/pintail-sdk-ts';

// The first argument is the campaign codename.
// The second argument is the event extras and can be anything
// you want to send to the event endpoint.
await pintail.track('tic6QBYHSJDdd55ao', {
  plan: 'pro',
  referrer: 'newsletter',
  vip: true,
});
```

The optional third argument lets you forward the originating client request so
the event is attributed to the end user instead of your server. Pass an object
containing the request `headers` and the client `ip`:

```ts
import { pintail } from '@basetime/pintail-sdk-ts';

// Example using an Express-style request object.
app.post('/signup', async (req, res) => {
  await pintail.track(
    'tic6QBYHSJDdd55ao',
    {
      plan: 'pro',
      referrer: 'newsletter',
      vip: true,
    },
    {
      headers: req.headers,
      ip: req.ip,
    },
  );

  res.sendStatus(204);
});
```

### Browser Side

Using the client in the browser:

<!-- prettier-ignore -->
```html
<!-- Begin Pintail Code -->
<script>
  (function(t,n,i,r){
    t.pintail=t.pintail||{q:[],track:function(){t.pintail.q.push(arguments)}};
    var e=n.createElement(i);e.async=!0,e.src=r;
    var a=n.getElementsByTagName(i)[0];a.parentNode.insertBefore(e,a)
  })(window,document,"script","https://cdn.pintail.io/event/latest.js");

  // The first argument is the campaign codename.
  // The second argument is the event extras and can be anything
  // you want to send to the event endpoint.
  pintail.track('tic6QBYHSJDdd55ao', {
    plan: 'pro',
    referrer: 'newsletter',
    vip: true,
  });
</script>
<!-- End Pintail Code -->
```

Place this snippet anywhere in your HTML (including `<head>`). The loader
installs a `window.pintail` stub immediately, so any `pintail.track(...)`
calls you make are queued and replayed once the bundle finishes downloading.
The script is loaded asynchronously and does not block page rendering.

Note: when you call `pintail.track(...)` before the bundle has loaded, the
call is queued and returns `undefined` (not a `Promise`). After the bundle
loads, calls return `Promise<{ success: boolean }>` as documented under
[API](#api).

### Reliability and error handling

`track()` is built to be safe to call from anywhere — it never throws and
never rejects. Any transport, serialization, timeout, or server-side error
is surfaced through `console.warn` and reported back as
`{ success: false }`, so you can use it inside event handlers, lifecycle
hooks, and unload paths without `try`/`catch`.

In the browser, the SDK prefers `navigator.sendBeacon` when available,
which is highly reliable through corporate proxies and during page unload.
Because `sendBeacon` is fire-and-forget, a `{ success: true }` result on
that path reflects a successful enqueue rather than a server
acknowledgement. When `sendBeacon` is unavailable or refuses the payload,
the SDK falls back to `fetch` with a 5-second timeout and a CORS-safelisted
content type so the request does not trigger a preflight `OPTIONS`.
