# SDK — Web / JavaScript (/docs/sdk/web)



<Callout type="warn">
  **Status: alpha.** `@layers/client` is published to npm (current version
  at the time of writing: `2.2.0`). It is a thin wrapper over a Rust core
  compiled to WebAssembly.
</Callout>

## Install [#install]

```bash
npm i @layers/client
```

There is no `<script src="https://in.layers.com/sdk.js">` drop-in
snippet — that endpoint does not exist. The npm package is the only
supported install path for the web.

## Initialize [#initialize]

```ts
import { LayersClient } from '@layers/client';

const layers = new LayersClient({
  apiKey: 'unused-but-required-by-type',
  appId: 'app_xxx',
  environment: 'production', // or 'development' | 'staging'
  enableDebug: false,
});

await layers.init();
```

Notes:

* The constructor takes a `LayersConfig` object. `apiKey` is required by
  the TypeScript type but currently ignored by the server — pass any
  non-empty string.
* `baseUrl` defaults to `https://in.layers.com`. Override for a
  [custom domain](/docs/sdk/custom-domain).
* `queueOptions` controls batch flushing, retries, and on-disk
  persistence.

## Track events [#track-events]

```ts
await layers.track('purchase_success', {
  revenue: 9.99,
  currency: 'USD',
  product_id: 'premium_yearly',
});
```

```ts
// Screen / pageview
await layers.screen('Checkout', { cart_size: 3 });
```

Canonical event names ship in [Standard events](/docs/sdk/standard-events).
Events outside that list are stored but dropped at the CAPI relay.

## Identify [#identify]

```ts
layers.setAppUserId('user_42');
await layers.setUserProperties({ plan: 'premium' });

// On logout
layers.setAppUserId(undefined);
```

There is no `layers.identify(id, traits)` / `layers.reset()` shortcut —
use the two calls above.

## Consent [#consent]

```ts
await layers.setConsent({ advertising: true, analytics: true });
```

`setConsent` takes an object, not a boolean. The remote-config response
can also disable advertising / analytics globally via killswitches.

## Server-side (Node) [#server-side-node]

For backend event firing, use `@layers/node`:

```bash
npm i @layers/node
```

Same API as `@layers/client`. Use cases: post-purchase webhooks, CRM
pipelines, batch backfill.

## Single-page app routing [#single-page-app-routing]

Call `layers.screen(routeName)` manually from your router on every route
change. There is no automatic listener wired to `popstate` /
`pushState`.

```tsx
import { useLocation } from 'react-router-dom';
import { useEffect } from 'react';

function PageTracker({ layers }) {
  const location = useLocation();
  useEffect(() => {
    layers.screen(location.pathname);
  }, [location]);
  return null;
}
```

## Custom domain [#custom-domain]

For ad-blocker resilience, [configure a custom domain](/docs/sdk/custom-domain)
and pass it as `baseUrl`:

```ts
const layers = new LayersClient({
  apiKey: 'unused',
  appId: 'app_xxx',
  environment: 'production',
  baseUrl: 'https://events.yourdomain.com',
});
```

## Bundle size [#bundle-size]

Reported at publish time: \~200 KB unpacked (includes a Rust
`core-wasm` dependency). The exact gzipped size depends on your
bundler's WASM handling.

## Browser support [#browser-support]

Modern browsers with WebAssembly support. IE11 is not supported.
