# Quick start

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

From a new site to your first pageview, event and purchase in about five minutes.

<Steps>
<Step>

### Create a site [#create-a-site]

In the dashboard, add a website. Enter its name, the domain without a protocol (like `acme.com`) and its timezone. Every site gets two tokens:

- a **public token** (`pub_…`) for the browser, shown with the install snippet;
- a **secret token** (`sec_…`) for your server, used only for revenue. Regenerate it in the site's settings to see it; it's shown once.

</Step>
<Step>

### Install the tracker [#install-the-tracker]

Pick how your site is built. Every option sends a pageview on load and on each client-side navigation.

<Tabs items={['Script tag', 'Next.js', 'React', 'Remix', 'React Router']}>
<Tab value="Script tag">

Paste this into the `<head>` of every page.

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

</Tab>
<Tab value="Next.js">

```bash
npm i @supapulse/core @supapulse/react
```

Wrap the provider in a client component and use that in the root layout. Recent releases of `@supapulse/react` are marked as a client module, but the wrapper works with every version.

```tsx title="app/analytics.tsx"
'use client';

import { SupapulseProvider } from '@supapulse/react';
import type { ReactNode } from 'react';

const config = { apiToken: process.env.NEXT_PUBLIC_SUPAPULSE_TOKEN! };

export function Analytics({ children }: { children: ReactNode }) {
  return <SupapulseProvider config={config}>{children}</SupapulseProvider>;
}
```

```tsx title="app/layout.tsx"
import { Analytics } from './analytics';

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        <Analytics>{children}</Analytics>
      </body>
    </html>
  );
}
```

</Tab>
<Tab value="React">

```bash
npm i @supapulse/core @supapulse/react
```

```tsx title="src/main.tsx"
import { SupapulseProvider } from '@supapulse/react';
import { createRoot } from 'react-dom/client';
import { App } from './App';

const config = { apiToken: import.meta.env.VITE_SUPAPULSE_TOKEN };

createRoot(document.getElementById('root')!).render(
  <SupapulseProvider config={config}>
    <App />
  </SupapulseProvider>,
);
```

</Tab>
<Tab value="Remix">

```bash
npm i @supapulse/core @supapulse/react
```

```tsx title="app/root.tsx"
import { SupapulseProvider } from '@supapulse/react';
import { Outlet } from '@remix-run/react';

const config = { apiToken: 'YOUR_PUBLIC_TOKEN' };

export default function App() {
  return (
    <SupapulseProvider config={config}>
      <Outlet />
    </SupapulseProvider>
  );
}
```

</Tab>
<Tab value="React Router">

```bash
npm i @supapulse/core
```

```ts title="src/analytics.ts"
import { Supapulse } from '@supapulse/core';

export const supapulse = new Supapulse();
supapulse.init({ apiToken: import.meta.env.VITE_SUPAPULSE_TOKEN });
```

Import this module once from your entry file. The tracker listens to the History API, so route changes are tracked without any router code.

</Tab>
</Tabs>

</Step>
<Step>

### Verify your first pageview [#verify-your-first-pageview]

Deploy, then open your site in a new tab. The dashboard switches from waiting for the first pageview to live within a few seconds, and you get an email about it.

<Callout type="warn" title="Nothing showing up?">
  Requests from a domain that doesn't match the site return `403 Origin not allowed`. Check the domain in the site's settings, and turn on debugging (`data-debug="true"` on the script tag, or `debug: true` in the config) to log every send to the console.
</Callout>

</Step>
<Step>

### Track an event [#track-an-event]

Call `event()` with a name and optional properties. Names are free-form, up to 255 characters; short snake case names read best in reports.

```ts title="signup-form.ts"
supapulse.event('signup', {
  plan: 'growth',
  source: 'pricing_page',
});
```

With the script tag, the tracker is `window.supapulse`. In React, use [`useEvent()`](https://supapulse.app/docs/react/hooks#useevent).

</Step>
<Step>

### Track revenue [#track-revenue]

Revenue is sent from Stripe or your server, never from the browser. Identify the customer after login or signup, then connect Stripe or post `revenue` events from your server with the secret token.

<Callout title="Public vs secret token.">
  The `pub_` token is safe in the browser and can send pageviews, events and identify calls. The `sec_` token can also send revenue. Keep it in a server environment variable and never ship it to the client.
</Callout>

```ts title="login.ts (browser)"
supapulse.identify(user.id);
```

With Stripe, paste the endpoint from the site's settings into the Stripe dashboard and you're done. For other processors, post from your webhook:

```ts title="webhook.ts (server)"
await fetch('https://supapulse.app/api/ingest', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-API-Token': process.env.SUPAPULSE_SECRET_TOKEN!,
  },
  body: JSON.stringify({
    type: 'revenue',
    data: {
      customer_id: user.id,
      amount: 49.9,
      currency: 'USD',
      transaction_id: invoice.id,
      event_type: 'purchase',
    },
  }),
});
```

The [Stripe](https://supapulse.app/docs/guides/stripe) and [Paddle](https://supapulse.app/docs/guides/paddle) guides show the full setup.

</Step>
</Steps>
