> ## Documentation Index
> Fetch the complete documentation index at: https://docs.wendung.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Static sites and the script tag

> Add Wendung to a site without a build step: one script tag from cdn.wendung.app initializes the SDK, tracks pageviews, and exposes Wendung for step calls.

If your site has no bundler (plain HTML, Hugo, Jekyll, Webflow, WordPress, or any page without an npm build), load the SDK from `cdn.wendung.app` instead of installing `@wendung/sdk`. The script initializes itself from the tag's data attributes and exposes `Wendung` as a global, so you can track steps from inline handlers or a plain `<script>`.

The file is the same code as the npm package at that version, built as a self-contained script of about 4 KB compressed.

## Setup

<Steps>
  <Step title="Add the script tag">
    Put the tag in `<head>` on every page you want tracked. Use `defer` so the SDK runs before your own deferred scripts and before `DOMContentLoaded`.

    ```html theme={null}
    <script
      defer
      src="https://cdn.wendung.app/sdk/v0/wendung.js"
      data-api-key="pk_your_publishable_key"
      data-track-pageviews
    ></script>
    ```

    Each attribute maps to an [`init()` option](/configuration/options):

    | Attribute | Option | Notes |
    | - | - | - |
    | `data-api-key` | `apiKey` | Required for automatic initialization. Leave it out to call `Wendung.init()` yourself. |
    | `data-track-pageviews` | `trackPageviews` | A bare attribute or `"true"` enables full pageviews with granted consent. `"auto"` enables aggregate pageviews while pending, then full pageviews after consent. Omitted or `"false"` disables automatic pageviews. |
    | `data-debug` | `debug: true` | Presence turns SDK lifecycle logging on. |
    | `data-endpoint` | `endpoint` | Only when you route ingest through your own domain. |
    | `data-consent` | `consent` | `pending` allows aggregate pageviews only with `data-track-pageviews="auto"`. `granted` enables full analytics; `denied` stops all collection. See the [consent guide](/guides/consent). |

    `flushInterval` and `maxBatchSize` have no attribute. To set them, omit `data-api-key` and call `Wendung.init()` from your own script with the full options object.

    <Warning>
      Do not use `async`. An async script can run after the inline code that calls `Wendung`, and those calls throw `[Wendung] Call .init() first`.
    </Warning>
  </Step>

  <Step title="Register the site">
    With pageview tracking enabled, the SDK records page loads according to the visitor's consent state. Open **Sites** in the dashboard and add your hostname so the pageviews show up as visitors, pages, and sources. The [web analytics guide](/guides/web-analytics) covers path rules and the site dashboard.

    <Note>
      Pageviews count against your plan's monthly pageview allowance, separate from events. The free plan has none. See [Plans and limits](/help/plans#monthly-pageviews).
    </Note>
  </Step>

  <Step title="Track steps and identify users">
    `Wendung` is available on `window` once the script has run. Inline handlers work because they fire after `DOMContentLoaded`:

    ```html theme={null}
    <button onclick="Wendung.step('demo_requested', { plan: 'starter' })">
      Request a demo
    </button>
    ```

    Scripts of your own that call `Wendung` must run after it. Give them `defer` too (deferred scripts run in document order), or wait for `DOMContentLoaded`:

    ```html theme={null}
    <script defer>
      document.addEventListener('DOMContentLoaded', () => {
        Wendung.identify('user_123', { plan: 'pro' })
      })
    </script>
    ```

    Every method from the [API reference](/api-reference/init) is available on the global with the same signature.
  </Step>
</Steps>

## Versions and caching

The CDN serves three paths for the current release:

| Path | What it serves | Cache |
| - | - | - |
| `/sdk/latest/wendung.js` | The latest published release, including new major versions | 5 minutes, with stale responses allowed for up to 24 hours while revalidating |
| `/sdk/v0/wendung.js` | The latest 0.x release | 5 minutes, with stale responses allowed for up to 24 hours while revalidating |
| `/sdk/0.2.0/wendung.js` | The pinned 0.2.0 release | One year, immutable |

Use `latest` to receive every SDK release automatically. Use `v0` to stay on the 0.x series, or pin an exact version to control when you update. Both `latest` and the major channel can change behavior when a new release is published.

To use the latest release, change the script's `src`:

```html theme={null}
<script
  defer
  src="https://cdn.wendung.app/sdk/latest/wendung.js"
  data-api-key="pk_your_publishable_key"
  data-track-pageviews="auto"
  data-consent="pending"
></script>
```

This example collects aggregate pageviews while pending. Calling `Wendung.setConsent('granted')` switches to full analytics; calling `Wendung.setConsent('denied')` stops collection. Use a bare `data-track-pageviews` attribute if you want to wait for consent before collecting anything. See the [consent guide](/guides/consent) to save and restore the visitor's choice.

## Content Security Policy

If your site sets a CSP, allow the script host and the ingest host:

```
script-src https://cdn.wendung.app;
connect-src https://ingest.wendung.app;
```

## What differs from the npm package

* You use the `Wendung` global instead of `import { Wendung } from '@wendung/sdk'`. The methods are identical.
* Initialization happens in the tag. Calling `Wendung.init()` again afterwards is safe and replaces the configuration, the same as in the package.
* There are no TypeScript types on the global. If you type-check inline scripts, declare `Wendung` yourself or move to the package.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.