# Install on Webflow

Paste one script tag into your site's head code, save, publish, and open the published site.

Platform steps checked against the official Webflow documentation on 2026-11-03: [Custom code in head and body tags](https://help.webflow.com/hc/en-us/articles/33961357265299), [User Accounts sunset](https://help.webflow.com/hc/en-us/articles/36046006227731), [Developer changelog: User Accounts APIs removed](https://developers.webflow.com/data/changelog/2026/1/29).

## Quick install

Settings › Channels in the Telltale dashboard shows this tag with your real key already filled in. Copy it from there.

```html
<script src="https://app.trytelltale.dev/sdk/v1.js" data-telltale-key="YOUR_SITE_PUBLISHABLE_KEY"></script>
```

You need a paid plan to add custom code: an active Site plan on the site, or a Core, Growth, Agency or Freelancer Workspace plan.

1. Open your site's **Site settings**.
2. Open the **Custom code** tab.
3. Paste the tag into **Head code**.
4. Choose **Save changes**.
5. **Publish** the site. Custom code does not go live until you publish.

To add it to one page only, open that page's **Page settings** and paste it into **Inside `<head>` tag** under **Custom code** instead, then save and publish. For a site you want to measure everywhere, use Site settings.

## Consent

The tag records from page load. That is right for sites without a cookie or consent banner.

If your site shows a banner, hold the tag: add `data-telltale-wait-for-consent`. A held tag sends nothing at all until you call `optIn()`.

```html
<script src="https://app.trytelltale.dev/sdk/v1.js" data-telltale-key="YOUR_SITE_PUBLISHABLE_KEY" data-telltale-wait-for-consent></script>
```

Then, wherever your banner tool reports the visitor's choice (most offer a JavaScript callback or event), call:

```javascript
// When the banner allows measurement:
window.Telltale.getClient().optIn();
// When the visitor refuses or withdraws:
window.Telltale.getClient().optOut();
```

Apply the saved decision on every page load, and again each time it changes. Signing in is not consent. For OneTrust, Cookiebot or Sourcepoint, use the [Consent bridge guide](/docs/consent) and the [OneTrust](/docs/consent-onetrust), [Cookiebot](/docs/consent-cookiebot) or [Sourcepoint](/docs/consent-sourcepoint) recipe.

## Identify the signed-in member

Webflow's own User Accounts feature was retired on January 29, 2026, so sign-in on a Webflow site now comes from a membership tool such as Memberstack or Outseta. Link each session to the member's ID from that tool, which is stable and opaque. Never send the e-mail address, name or phone number.

**From your server (recommended).** If your membership tool calls your own backend (for example with a webhook or an API), link the session there. This is the identity Telltale trusts. See [Quickstart step 2](/docs/quickstart#2-attach-identity-from-your-own-authentication) and [Server API › Associate identity](/docs/server#associate-identity).

**In the browser (a label).** In your membership tool's "member loaded" or "logged in" JavaScript callback, call `identify()` with the member's ID, and `reset()` when they log out. Put this in **Footer code**, after the tool's own script:

```html
<script>
  // Replace onMemberReady and onMemberLogout with your membership tool's own callbacks.
  onMemberReady(async member => {
    try {
      await window.Telltale.getClient().identify({ userId: member.id });
    } catch (error) {
      // Rejects while the tag is held for consent, or when the Telltale server is unreachable.
    }
  });
  onMemberLogout(async () => {
    try { await window.Telltale.getClient().reset(); } catch (error) {}
  });
</script>
```

If members belong to a team or company, add `accountId` with that group's ID. A held tag forgets identity until `optIn()`, so identify again after the visitor allows measurement.

## Content Security Policy

Most Webflow sites send no Content Security Policy that limits scripts. If yours does (for example through a proxy in front of Webflow), allow the Telltale server for scripts and for connections:

```http
Content-Security-Policy: script-src 'self' https://app.trytelltale.dev; connect-src 'self' https://app.trytelltale.dev
```

Keep the sources your policy already lists. Never add `'unsafe-inline'` or `'unsafe-eval'` for Telltale. An inline footer script like the one above then needs its hash in `script-src`; see the [Content Security Policy guide](/docs/csp).

## Check it worked

1. In the Telltale dashboard, open Settings › Channels and leave the **Is it working?** check open.
2. Choose **Open my site to test it**, or open your **published** site in a new tab yourself. Browse a page or two.
3. Watch the check move through **Script loaded on** your address, **First session received** and, if you set up identify, **Signed-in user linked** (log in as a test member to see it). When the first session arrives, it links to it.

You can also look in your browser's DevTools › Network: `sdk/v1.js` should answer 200, and so should `api/sdk/init`. If it stays at the first step, see [It's not working](/docs/troubleshooting).

## Common mistakes

- **Checking in the Designer.** Custom scripts are switched off in the Designer canvas. Check on the published site.
- **Saving without publishing.** Choose Publish after Save changes.
- **No paid plan.** Without a Site plan or a paid Workspace plan, the Custom code fields are not available.
- **The `webflow.io` address versus your own domain.** `https://your-site.webflow.io`, `https://example.com` and `https://www.example.com` are all different addresses. Add each one you publish to under Settings › Channels › Website addresses.
- **Wrapping it in `<head>` tags.** Paste only the `<script>` line; Webflow adds the head and body tags itself.
- **Ad blockers.** Some privacy extensions block third-party scripts. Test in a window without extensions.
