# Installation

URL: https://supapulse.app/docs/installation

Install the Supapulse tracker with a script tag or from npm, check that it works, and fix the usual setup problems.

There are two ways to add the tracker. Both load the same code from `@supapulse/core`.

| | Script tag | npm |
| --- | --- | --- |
| Good for | Static sites, CMSs, server-rendered pages | Apps with a bundler |
| Setup | Paste one tag | `npm install` and call `init()` |
| Global | `window.supapulse` | The instance you create |
| Options | `data-token`, `data-endpoint`, `data-debug` | Every [config option](https://supapulse.app/docs/core/configuration) |

## Script tag [#script-tag]

Add this to the `<head>` of every page, with your site's public token:

```html
<script
  defer
  src="https://cdn.jsdelivr.net/npm/@supapulse/core@1/dist/browser.js"
  data-token="YOUR_PUBLIC_TOKEN"
></script>
```

The script is the UMD build of `@supapulse/core`, served by jsDelivr. When it runs it creates one tracker, exposes it as `window.supapulse`, and initializes it from the script tag's attributes:

| Attribute | Maps to | Notes |
| --- | --- | --- |
| `data-token` | `apiToken` | Required. Without it the tracker is not initialized. |
| `data-endpoint` | `endpoint` | Optional. Defaults to `https://supapulse.app/api/ingest`. |
| `data-debug` | `debug` | Set to `"true"` to log to the console. |

Automatic pageviews are always on with the script tag. If you need manual pageviews, use the npm package instead.

`@1` pins the major version, so you get fixes without breaking changes. To pin an exact version, use `@supapulse/core@1.0.1`.

### Sending events with the script tag [#sending-events-with-the-script-tag]

`defer` scripts run after the HTML is parsed. Code that runs before that, or in a script without `defer`, should check that the tracker exists:

```html
<button id="signup">Sign up</button>
<script>
  document.getElementById('signup').addEventListener('click', function () {
    if (window.supapulse) {
      window.supapulse.event('signup_click', { location: 'header' });
    }
  });
</script>
```

## npm [#npm]

```bash
npm install @supapulse/core
```

```ts
import { Supapulse } from '@supapulse/core';

const supapulse = new Supapulse();
supapulse.init({ apiToken: 'YOUR_PUBLIC_TOKEN' });

supapulse.event('signup_click', { location: 'header' });
```

Create one instance per page and call `init()` once. The package ships ES module and CommonJS builds with TypeScript types. `init()` throws outside a browser, so call it from client-side code only.

For React apps, `@supapulse/react` wraps this in a provider and hooks. See [React installation](https://supapulse.app/docs/react/installation).

## Check that it works [#check-that-it-works]

1. Open your site with the browser's developer tools on the **Network** tab.
2. Filter by `ingest`. Each pageview and event is a `POST` to `https://supapulse.app/api/ingest`. The tracker uses `navigator.sendBeacon`, so requests can show as type `ping`.
3. Open the site in the dashboard. The first pageview appears within a few seconds.

Turn on debugging to log each send:

```html
<script
  defer
  src="https://cdn.jsdelivr.net/npm/@supapulse/core@1/dist/browser.js"
  data-token="YOUR_PUBLIC_TOKEN"
  data-debug="true"
></script>
```

With debugging on, the console shows `[Supapulse] Initialized` and `[Supapulse] Event sent` lines.

## Troubleshooting [#troubleshooting]

### The script doesn't load [#the-script-doesnt-load]

- A Content Security Policy must allow the script and the endpoint: `script-src https://cdn.jsdelivr.net` and `connect-src https://supapulse.app`.
- Some ad blockers block analytics scripts. There's no workaround in the tracker; check with the blocker turned off.

### Requests fail with 403 Origin not allowed [#requests-fail-with-403-origin-not-allowed]

The page's domain must match the domain set for the site, or be a subdomain of it. A site set to `acme.com` accepts `acme.com` and `app.acme.com`. `localhost` is rejected unless the site's domain is `localhost`.

### Requests fail with 401 [#requests-fail-with-401]

The token is missing, mistyped or was regenerated. Copy the public token again from the site's settings. Public tokens start with `pub_`.

### Pageviews are counted twice [#pageviews-are-counted-twice]

You're calling `pageview()` yourself while automatic pageviews are on. Either remove your calls or set `autoPageviews: false`. See [SPA support](https://supapulse.app/docs/core/spa-support).

More checks are in [Debugging](https://supapulse.app/docs/debugging).
