# Add CLItrail to Webflow

Where the CLItrail tag goes in Webflow, in its own idiom, with the consent, CSP and client-side routing details and how to check it works.

Written for Webflow (hosted sites)

## Where the tag goes

Edit `Site settings → Custom code → Head code`. Put the tag on every page that shows your install command; site-wide is best, after your existing analytics tags.

```html
<script defer src="https://YOUR_SERVICE/browser.js" data-website="YOUR_WEBSITE_ID"></script>
```

## Only after consent

Use this in Head code instead of the tag: it defines `startClitrail()` for your consent manager to call.

```html
<script>
  // Loads CLItrail only after the visitor agrees. Call startClitrail() from your
  // consent manager's "accepted" callback; nothing is fetched or stored before that.
  window.startClitrail = () => {
    if (document.getElementById('clitrail')) return;
    const tag = document.createElement('script');
    tag.id = 'clitrail';
    tag.src = 'https://YOUR_SERVICE/browser.js';
    tag.dataset.website = 'YOUR_WEBSITE_ID';
    document.head.append(tag);
  };
</script>
```

## Client-side routing

Every page is a full page load, so the tag records each page by itself. Nothing else to add.

## Content Security Policy

Webflow serves the pages. If you put a Content-Security-Policy in front of them (for example through your own proxy), add `https://YOUR_SERVICE` to `script-src` and `connect-src`, and `blob:` to `worker-src` (only Safari before 26 needs that one).

```
script-src 'self' https://YOUR_SERVICE;
connect-src 'self' https://YOUR_SERVICE;
worker-src 'self' blob:;
```

## Verify it works

1. Publish the site (custom code does not run in the Designer).
2. Open a page with the tag in Chrome or Firefox (accept analytics first if you gate CLItrail on consent), open the developer console and run `await InstallAttribution.ready`. It resolves to `{ ok: true, urlId, hasAnalyticsContext, expiresAt }`.
3. In the CLItrail dashboard, open Visits & identities: the visit is listed.
4. Anything else names the cause: `disabled` (no consent yet, or `data-enabled="false"`), `opfs_unavailable` (the page is not served over https or from localhost), `Error` (the service refused the visit: add the page's origin, including a development origin such as `http://localhost:3000`, under Settings → Additional domains). If `InstallAttribution` is undefined, the tag did not load: check the Network tab and your Content-Security-Policy.

Then run your installer on the same computer and check **Install events**, or run the hook with [`--doctor`](https://clitrail.com/docs/doctor).

> Tip
> 
> If `InstallAttribution.ready` is undefined on the published site, use the [manual start](https://clitrail.com/docs/frameworks/webflow#if-a-visit-is-not-recorded).

## If a visit is not recorded

Start the SDK yourself: this adds the tag without `data-website` and calls `InstallAttribution.init` once it loads.

Manual start

```html
<script>
  (() => {
    if (window.InstallAttribution) return;
    const tag = document.createElement('script');
    tag.src = 'https://YOUR_SERVICE/browser.js';
    tag.onload = () => {
      const sdk = window.InstallAttribution;
      sdk.ready = sdk.init({ service: 'https://YOUR_SERVICE', project: 'YOUR_WEBSITE_ID' });
    };
    document.head.append(tag);
  })();
</script>
```

## Notes

- Custom code needs an active paid Site plan.
- Page settings has its own custom code field if you want the tag on a few pages only; site-wide is better.

Webflow documentation: [help.webflow.com/hc/en-us/articles/33961357265299-Custom-code-in-head-and-body-tags](https://help.webflow.com/hc/en-us/articles/33961357265299-Custom-code-in-head-and-body-tags)

Using other install paths or destinations? The [setup generator](https://clitrail.com/docs/setup-generator) puts this snippet together with your hooks and destination checklist.
