# The script tag

> What one script tag does (traffic-source recording, form submission, GTM) and the list of attributes.

URL: https://siteon.dev/docs/script

Siteon is infrastructure for AI-built websites: it adds hosting, a CMS your client can edit, contact forms, analytics and control from AI agents (CLI and MCP) around static HTML built with AI or by hand, so it is ready to ship.

## Usage

Add one line with `defer`, either just before `</body>` or in `<head>`.

```html
<script src="https://cdn.siteon.dev/sitekit.js" data-site="hanaya" defer></script>
```

That alone enables three things:

- **Traffic-source (UTM) recording** — stores `utm_*` / `gclid` / `fbclid` for visitors arriving from ads and the like in the browser, and attaches them automatically when a form is submitted
- **Form submission** — sends any `<form>` marked with `data-sitekit-form` without leaving the page
- **GTM loading** — only when you set `data-gtm`

## Attributes

| Attribute | Required | Description |
|---|---|---|
| `data-site` | Required | Site ID. If missing, the script **exits silently** (no error either) |
| `data-locale` | | Language to fetch. Defaults to `<html lang>`, then `ja` |
| `data-gtm` | | GTM container ID (in the form `GTM-XXXXXXX`). Ignored if the format is wrong |
| `data-embed` | | Embeds CMS values at render time. For hosting that can't use the relay; **normally leave it off** ([Hosting and delivery](https://siteon.dev/docs/hosting)) |

- **The API origin is not set by an attribute.** The script connects to the origin of its own `src` (`https://cdn.siteon.dev`). If `src` is not `http(s)` (for example, when a file is opened directly), it does nothing
- **Don't add `integrity` (SRI).** The script is designed to be updated without touching your site's HTML
- Placing two script tags on one page is not a setup the script handles

## Recording traffic sources (UTM)

When a visitor arrives from an ad link or similar, the following values are recorded in the browser's `localStorage`.

| Recorded value | Contents |
|---|---|
| `utm_source` / `utm_medium` / `utm_campaign` / `utm_term` / `utm_content` | UTM parameters in the URL |
| `gclid` / `fbclid` | Google Ads / Meta ads click IDs |
| `landing` / `referrer` / `at` | Landing page, referrer, timestamp |

- Two sets are kept: the first visit (first) and the most recent visit (last). They are kept for 90 days
- When a form is submitted, they are saved with the inquiry. You don't need to add hidden fields
- Any value longer than 500 characters is truncated
- If the browser blocks `localStorage`, nothing is recorded (form submission still works)

## Loading GTM

Loads the container set in `data-gtm`.

```html
<script src="https://cdn.siteon.dev/sitekit.js" data-site="hanaya" data-gtm="GTM-XXXXXXX" defer></script>
```

You can also enter a GTM ID under "Settings → Advanced" in the dashboard. That route has the relay (Cloudflare Pages) inject the tag into `<head>`, and it takes effect after the public JSON cache (60 seconds) expires. **If you set both, the injected tag and the `data-gtm` container will conflict.** On sites that use the relay, leave out `data-gtm` and set the ID in the dashboard.

To track form submissions in GTM, see [Forms](https://siteon.dev/docs/forms#tracking-submissions-in-gtm).

## window.SiteKit

After loading, `window.SiteKit` is available. You normally don't need to touch it.

| Member | Description |
|---|---|
| `SiteKit.version` | Build version string |
| `SiteKit.attribution()` | The recorded traffic source, or `null` if none |
| `SiteKit.bindForms()` | Re-binds forms. Call it after adding forms with JavaScript |
| `SiteKit.refresh()` | Re-reads the traffic source from `localStorage` |

## Caching

The script (`https://cdn.siteon.dev/sitekit.js`) is cached for 5 minutes. Bug fixes reach all visitors in about 5 minutes without any change to your HTML. Conversely, it isn't suited to pinning a specific version.

## If you use CSP

With only the script tag (and `data-gtm`), allow these two origins:

```text
script-src  'self' https://cdn.siteon.dev https://www.googletagmanager.com;
connect-src 'self' https://cdn.siteon.dev;
```

If the relay injects GTM, the inline GTM snippet goes into `<head>`, so you need `'unsafe-inline'` or a nonce. If your site can't allow `'unsafe-inline'`, `data-gtm` is the simpler option. Add whatever the tags loaded by GTM require separately, following GTM's requirements.
