# Install the snippet

The snippet is the one piece of code TryFast needs on your website. It loads your project's script from `cdn.tryfast.eu`, applies the variations of your running experiments before the page shows, and counts visitors and conversions. One request delivers the engine together with your experiments, and the engine is about 12 KB compressed.

Every project has its own snippet. You find it in the app under **Project settings, Install** (or on the setup page right after creating a project), from the API (`GET /api/v1/projects/{project_id}/snippet`) and from your AI agent (`get_install_snippet`). It always contains your project key in place of `KEY` below.

## The recommended snippet

Paste both tags as high as possible in the `<head>` of every page, before your analytics and tag manager tags:

```html
<script>!function(w,d,t){var q=w.tryfast=w.tryfast||[],l=w.location,u,m;q.t0=Date.now();try{u=new URL(l.href);["tf_preview","tf_editor"].forEach(function(k){if(m=u.searchParams.get(k)){w.sessionStorage.setItem(k=="tf_preview"?"tf_pv":"tf_el",m);u.searchParams.delete(k)}});u.href!=l.href&&history.replaceState(history.state,"",u.href)}catch(e){}if(!d.getElementById("tf-hide")){var s=d.createElement("style");s.id="tf-hide";s.textContent="html{opacity:0!important}";(d.head||d.documentElement).appendChild(s);q.hide=setTimeout(function(){var e=d.getElementById("tf-hide");e&&e.parentNode.removeChild(e);q.timedOut=1},t)}}(window,document,800)</script>
<script src="https://cdn.tryfast.eu/s/KEY.js" async fetchpriority="high"></script>
```

The first tag is small inline code. It creates the `window.tryfast` queue so your code can call TryFast before the script has loaded, hides the page for at most 800 milliseconds while variations load (the anti-flicker style), and removes TryFast's preview and editor tokens (`tf_preview`, `tf_editor`) from the address bar before analytics tags that load later can record them. The second tag loads your project's script without blocking the page.

Optionally add a preconnect hint right above it, so the browser opens the connection early:

```html
<link rel="preconnect" href="https://cdn.tryfast.eu" crossorigin>
```

Placement matters. A snippet at the end of `<body>`, behind a tag manager, or behind a script optimizer that delays scripts applies variations later, and visitors may see the original page flash before the variation.

## Snippet variants

| Variant | Use it when | Anti-flicker |
|---|---|---|
| Recommended (`async_anti_flicker`) | You can edit the `<head>` of your pages. Best for most sites. | Yes, at most 800 ms by default |
| Without anti-flicker (`async`) | Your experiments change only things below the fold, or you test redirects only. | No |
| Synchronous (`sync`) | You want the script to block rendering until it has run. It delays every page by one request. | Not needed |
| Google Tag Manager (`gtm`) | You can only add code through Google Tag Manager. Use a Custom HTML tag on the earliest trigger (Initialization, All Pages). Tag managers run later than the page, so changes can flicker. | No |

Every variant contains the same token-removal code. Copy the exact text from the app or the API rather than typing it.

## Anti-flicker

With the recommended snippet the page is invisible (`opacity: 0`) until TryFast has applied the variations, and never longer than the timeout. The timeout is a project setting (**Project settings, Performance**, 100 to 3,000 ms, default 800). It is written into the snippet text, so after changing it, update the snippet on your site.

When the timeout fires before the script arrives (a slow network, an ad blocker), the project setting **If loading takes longer** decides what happens on that page view:

- **Show the original and skip experiments on that page view** (default, `skip_page`): the visitor sees your page unchanged, and that page view does not count as a visit to the experiment. Their next page view works normally.
- **Apply variations late** (`run`): variations apply when the script arrives, which may flicker.

The page is shown immediately on pages without an experiment.

## Frameworks and platforms

The snippet response includes step-by-step instructions for HTML, Next.js, React and Vue apps, WordPress, Shopify and Google Tag Manager (the app's framework picker, or `framework=` on the snippet endpoint). In short:

- **HTML**: paste both tags into the `<head>` of your page template.
- **Next.js**: add both tags to the `<head>` of your root layout as plain `<script>` elements. Do not load them with a lazy loading strategy, which runs them after the page is shown.
- **React, Vue and other single-page apps**: paste both tags into the `<head>` of `index.html`. Route changes are detected automatically (see [Single-page apps](#single-page-apps)).
- **WordPress**: add both tags to your theme's `<head>`, before other scripts. Exclude them from "delay JavaScript", "defer" and "combine" options of caching plugins such as WP Rocket and LiteSpeed Cache.
- **Shopify**: paste both tags into `theme.liquid` right after the opening `<head>` tag.
- **Cloudflare Rocket Loader**: add `data-cfasync="false"` to both tags so Rocket Loader does not delay them.

## Content Security Policy

If your site sends a `Content-Security-Policy` header, allow TryFast's host:

```text
script-src https://cdn.tryfast.eu
connect-src https://cdn.tryfast.eu
```

The inline part of the snippet is an inline script: allow it with a nonce attribute or with the SHA-256 hash of its exact text in `script-src`. The anti-flicker style and variation CSS are inline styles and need `style-src 'unsafe-inline'`. TryFast never uses `eval`: variation code is checked and built into your project's script ahead of time, so you do not need `'unsafe-eval'`.

## Check that it works

The app shows the installation status of each project, and your agent reads the same with `check_installation`:

| Status | Meaning |
|---|---|
| `not_seen` | The script was never loaded and no event arrived yet. Open your site in a new tab after pasting the snippet. |
| `loaded_awaiting_consent` | The script loads on your site, but no event arrived in the last 24 hours. With the default consent mode nothing is sent until a visitor accepts your cookie banner: connect your banner (below). |
| `receiving` | Events arrived in the last 24 hours. |
| `stale` | Events arrived before, but none and no script loads in the last 24 hours. The snippet may have been removed. |

To check one page right now, use **Check a page** in the app, `verify_installation` in your agent, or `POST /api/v1/projects/{project_id}/install-check` with a URL on one of your project's domains. The [TryFast inspector](inspect.md) fetches that page and reports problems such as these:

| Issue | What to do |
|---|---|
| `snippet_not_found` | The snippet is not in the page's HTML. Paste it into the `<head>`. If your page is rendered in the browser (`client_rendered`), open it once yourself: the passive check above sees the visit. |
| `wrong_project_key` or `multiple_projects` | The page loads another project's script, or two. Use one project per site. |
| `late_placement` | The tag is in `<body>` or after other scripts. Move it to the top of `<head>`. |
| `optimizer_rewrite` | A script optimizer rewrote the tag. For Cloudflare Rocket Loader add `data-cfasync="false"`; for WordPress optimizers exclude the tags. |
| `csp_blocks_script`, `csp_blocks_connect` | Your Content Security Policy blocks TryFast. Add the directives above. |
| `fetch_blocked` | Bot protection or an error status stopped the check. Open the page yourself; the passive check sees the visit. |

## Connect your cookie banner

By default TryFast waits for consent: before a visitor accepts your cookie banner it stores nothing, sends nothing and shows everyone your original page. Add one line to your banner's accept callback:

```js
window.tryfast = window.tryfast || [];
window.tryfast.push(["consent", true]);
```

Testing without a banner? Open your site and run `tryfast.push(["consent", true])` in the browser console.

Recipes for Cookiebot, Usercentrics, OneTrust, Didomi and IAB TCF are in [Privacy and consent](privacy-and-consent.md#connect-your-cookie-banner). The consent modes, and when each one needs a banner, are explained in [Privacy and consent](privacy-and-consent.md).

## Exclude your own visits

Open `https://your-site.example/?tf_optout=1` once in each browser you use for work. That browser then sees your original pages and is never counted. `?tf_optout=0` undoes it. Previews still work in an excluded browser.

## Single-page apps

TryFast detects route changes in React, Next.js, Vue and other single-page apps (`pushState`, `replaceState`, back and forward navigation). On every route change it checks which experiments match the new page, applies new ones, reverts the changes of experiments that no longer match and counts a page view. Visitors keep their variation. If your app renders content later without changing the URL, call `tryfast.refresh()` after rendering. You can switch route detection off under **Project settings, Performance**.

## Domains

A project accepts events, previews and editor sessions only from its domains. Each entry is an exact host such as `shop.example.com` or a wildcard such as `*.example.com` (every subdomain, not the bare host). Creating a project from a URL adds the host and its `www.` or bare counterpart. Events from other hosts are dropped and shown in the installation status, so a copied snippet on someone else's site never counts in your results.

Next: [create your first experiment](experiments/index.md).
