# Install the script

The script is one tag. It is about 5 KB gzipped, loads with `defer`, and does not block the page. Put it in the `<head>` so it loads on every page.

~~~html
<script defer data-website-id="tb_YOUR_SITE_ID" data-domain="example.com" src="https://twelvebit.app/js/script.js"></script>
~~~

Find your site id on the site's setup page in the dashboard. It starts with `tb_`.

## Plain HTML

Paste the tag into the `<head>` of every page, or of your shared template.

## Next.js (App Router)

Use `next/script` in the root layout. `afterInteractive` loads the script after hydration.

~~~tsx
// app/layout.tsx
import Script from "next/script";

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        {children}
        <Script
          src="https://twelvebit.app/js/script.js"
          data-website-id="tb_YOUR_SITE_ID"
          data-domain="example.com"
          strategy="afterInteractive"
        />
      </body>
    </html>
  );
}
~~~

## Next.js (Pages Router)

~~~tsx
// pages/_app.tsx
import type { AppProps } from "next/app";
import Script from "next/script";

export default function App({ Component, pageProps }: AppProps) {
  return (
    <>
      <Script
        src="https://twelvebit.app/js/script.js"
        data-website-id="tb_YOUR_SITE_ID"
        data-domain="example.com"
        strategy="afterInteractive"
      />
      <Component {...pageProps} />
    </>
  );
}
~~~

You can also put a plain `<script defer …>` tag inside `<Head>` in `pages/_document.tsx`.

## React with Vite (or Create React App)

Add the tag to `index.html` in the project root (`public/index.html` for Create React App):

~~~html
<!-- index.html -->
<head>
  <script defer data-website-id="tb_YOUR_SITE_ID" data-domain="example.com" src="https://twelvebit.app/js/script.js"></script>
</head>
~~~

The script follows client-side navigation by itself (`pushState`, `replaceState` and the back button).

## Vue and Nuxt

Vue with Vite: add the tag to `index.html`, as for React.

Nuxt 3 and 4:

~~~ts
// nuxt.config.ts
export default defineNuxtConfig({
  app: {
    head: {
      script: [
        {
          src: "https://twelvebit.app/js/script.js",
          defer: true,
          "data-website-id": "tb_YOUR_SITE_ID",
          "data-domain": "example.com",
        },
      ],
    },
  },
});
~~~

## Svelte and SvelteKit

SvelteKit: add the tag to `src/app.html`, inside `<head>`, before `%sveltekit.head%`. Svelte with Vite: add it to `index.html`.

~~~html
<!-- src/app.html -->
<head>
  <script defer data-website-id="tb_YOUR_SITE_ID" data-domain="example.com" src="https://twelvebit.app/js/script.js"></script>
  %sveltekit.head%
</head>
~~~

## Astro

Add the tag to the `<head>` of your base layout. `is:inline` tells Astro to leave the tag as it is.

~~~astro
---
// src/layouts/Layout.astro
---
<html lang="en">
  <head>
    <script is:inline defer data-website-id="tb_YOUR_SITE_ID" data-domain="example.com" src="https://twelvebit.app/js/script.js"></script>
  </head>
  <body><slot /></body>
</html>
~~~

With view transitions (`<ClientRouter />`), the script still counts each page, because Astro changes the URL with `pushState`.

## Remix and React Router 7

~~~tsx
// app/root.tsx
import { Links, Meta, Outlet, Scripts, ScrollRestoration } from "react-router"; // "@remix-run/react" in Remix 2

export function Layout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <head>
        <Meta />
        <Links />
        <script defer data-website-id="tb_YOUR_SITE_ID" data-domain="example.com" src="https://twelvebit.app/js/script.js" />
      </head>
      <body>
        {children}
        <ScrollRestoration />
        <Scripts />
      </body>
    </html>
  );
}

export default function App() {
  return <Outlet />;
}
~~~

## Gatsby

~~~jsx
// gatsby-ssr.jsx
import * as React from "react";

export const onRenderBody = ({ setHeadComponents }) => {
  setHeadComponents([
    <script
      key="twelvebit"
      defer
      data-website-id="tb_YOUR_SITE_ID"
      data-domain="example.com"
      src="https://twelvebit.app/js/script.js"
    />,
  ]);
};
~~~

## WordPress

Use a header code plugin (for example WPCode: Code Snippets → Header & Footer → Header) and paste the tag. Or add it from your theme's `functions.php` (use a child theme, so theme updates keep it):

~~~php
// functions.php
add_action('wp_head', function () {
  echo '<script defer data-website-id="tb_YOUR_SITE_ID" data-domain="example.com" src="https://twelvebit.app/js/script.js"></script>';
});
~~~

You can also paste the tag into `header.php`, before `</head>`.

For a WooCommerce store, use the [twelvebit plugin](/docs/revenue#woocommerce) instead: it adds the tag, the cart and checkout goals, and the orders.

## Shopify

Online Store → Themes → … → Edit code → `layout/theme.liquid`. Paste the tag before `</head>` and save. Checkout pages on Shopify do not load theme code, so use [Revenue](/docs/revenue) to count orders.

Or skip the theme edit: [connect the store](/docs/revenue#shopify) with a custom app. twelvebit then installs the script itself, sends `add_to_cart` and `initiate_checkout` goals, and records each paid order.

## Webflow

Site settings → Custom code → Head code. Paste the tag, save, and publish the site. Custom code needs a paid site plan.

## Framer

Site Settings → General → Custom Code → "End of `<head>` tag". Paste the tag and publish.

## Google Tag Manager

GTM can drop `data-*` attributes from a plain script tag. Use a **Custom HTML** tag that creates the script element, with the trigger **All Pages**:

~~~html
<script>
  (function () {
    var s = document.createElement("script");
    s.defer = true;
    s.src = "https://twelvebit.app/js/script.js";
    s.setAttribute("data-website-id", "tb_YOUR_SITE_ID");
    s.setAttribute("data-domain", "example.com");
    document.head.appendChild(s);
  })();
</script>
~~~

## After you install

- Open the site and check the dashboard, or run the install check in [Quickstart](/docs#3-check-that-it-works).
- To send events before the script has loaded, add the queue stub from the [Script reference](/docs/script#queue-calls-before-the-script-loads).
- If ad blockers are common with your visitors, serve the script from your own domain. See [Proxy](/docs/proxy).

---

Source: https://twelvebit.app/docs/install · All docs: https://twelvebit.app/llms.txt
