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.
<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.
// 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)#
// 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):
<!-- 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:
// 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.
<!-- 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.
---
// 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#
// 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#
// 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):
// 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 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 to count orders.
Or skip the theme edit: connect the store 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:
<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.
- To send events before the script has loaded, add the queue stub from the Script reference.
- If ad blockers are common with your visitors, serve the script from your own domain. See Proxy.