# Add the website script

> Measure a website with Tapll through one script tag: page views, sources and campaigns, feature funnels and revenue, cookieless by default.

Source: https://tapll.com/docs/web-sdk · Updated 2026-10-25

The website script is one tag served from `https://cdn.tapll.com/v0/u.js`: under 5 KB gzipped, no dependencies, source on [GitHub](https://github.com/tapll/tapll-web). The `v0` in the URL is a major version, so fixes reach your site without a snippet change. There is no npm package: keep the tag on the CDN rather than bundling it.

## Add a website to a project

An app and its website share one project, so they share one write key and one privacy mode. In **Settings → General → Platforms**, choose **Add website** (with the domains it will run on, or none yet).

## Install the tag

Put this once in the `<head>` of every page. The key is a **client** key: it is public by design and safe to commit.

```html
<script defer src="https://cdn.tapll.com/v0/u.js"
        data-key="av_…"></script>
```

- Page views come from the page load and from `history.pushState` navigation, so single-page apps need no router hook. Only the **path** is sent: never the query string or the fragment. UTM parameters are read from the landing URL by the script.
- Outbound links and file downloads are tracked on their own. `data-auto="false"` turns that off.
- If the project lists **domains**, a page on any other host is refused, so a copied snippet cannot report into your project.
- `localhost`, `127.*` and `*.local` report as development (the Sandbox scope). `data-env="development"` forces it for a staging host.
- Optional: `data-version="<deploy id>"` turns on Releases for the site, and `data-exclude="/admin/*"` skips paths.

## Privacy modes on the web

| | Strict anonymous | Product analytics |
| --- | --- | --- |
| Stored in the browser | Nothing: no cookie, no localStorage | An anonymous id and the session, in localStorage |
| Visitor recognised | Within one UTC day, by a server-side hash with a daily salt | Across visits and, after `tapll.identify`, across devices |
| Consent banner | Not needed | Needed where the law asks for it |
| Retention and people | No | Yes |

Strict anonymous is the default. In product analytics, add `data-mode="product_analytics"` and let Tapll ask:

```html
<script defer src="https://cdn.tapll.com/v0/u.js"
        data-key="av_…"
        data-mode="product_analytics"></script>
```

Tapll's consent banner is optional and off by default. Add `data-consent="banner"` and nothing is stored and nothing is sent until the visitor chooses. Accept and Decline carry equal weight, and the answer is remembered. If the site already has a consent tool, use `data-consent="required"` and call `tapll.consent(true)` or `tapll.consent(false)` from its callbacks.

## Events and features

Name the moments that matter and declare the funnels in code:

```js
const signup = tapll.feature('signup');
signup.start('signup_started');
signup.success('signup_completed', { plan: 'pro' });

tapll.track('pricing_toggled', { period: 'yearly' });
```

A button can also carry `data-tapll-event="cta_clicked"` and send the event without any JavaScript. Event names are lowercase `snake_case`; an invalid event is dropped with a console warning, never sent truncated, and the script never throws into your page.

## Revenue from the site

Connect **Stripe** or **Paddle** in Settings, then pass the visit into checkout: `tapll.sessionId()` goes into Stripe Checkout `metadata` or Paddle.js `customData` as `tapll_session_id`. Tapll ties the payment to that visit and its first-touch channel and campaign. See [Connect revenue](/docs/revenue).

## Ad blockers

Some blockers stop third-party analytics hosts. If your site has a server or edge layer, proxy the script and the endpoint through your own domain and point the tag at it with `data-api`:

```js
// next.config.js
async rewrites() {
  return [
    { source: '/_tapll/u.js', destination: 'https://cdn.tapll.com/v0/u.js' },
    { source: '/_tapll/v1/:path*', destination: 'https://in.tapll.com/v1/:path*' },
  ];
}
// <script defer src="/_tapll/u.js" data-api="/_tapll" data-key="…"></script>
```

## What the script does not do

It does not measure Web Vitals, report JavaScript errors, record sessions or draw heatmaps, and it ships no framework plugins.

> **Using Claude Code, Cursor or Codex?**
> Settings → SDK setup has a setup prompt filled in with your project's key, privacy mode and domains. A generic version is in [llms.txt](/llms.txt).
