Docs

Any other site

If your stack is not listed, one of two patterns fits: the script tag in the shared HTML layout (server-rendered sites, static site generators) or init() in the client entry (bundled SPAs).

Install

Script tag in the layout every page uses:

layout.html
<script>window.x3=window.x3||function(){(window.x3q=window.x3q||[]).push(arguments)}</script>
<script async src="{{API_ORIGIN}}/v1/s/x3.full.js?k={{PUBLISHABLE_KEY}}" data-key="{{PUBLISHABLE_KEY}}"></script>

Or, with a bundler:

npm install {{API_ORIGIN}}/v1/sdk/3x-engine-sdk-0.1.0.tgz
src/analytics.ts
import { init } from "@3x-engine/sdk";
import { forms, sections, video } from "@3x-engine/sdk/plugins";

init({ key: "{{PUBLISHABLE_KEY}}", host: "{{API_ORIGIN}}", plugins: [video(), sections(), forms()] });

Import src/analytics.ts once from your client entry (Nuxt: a client-only plugin; SvelteKit: hooks.client.ts; Remix: entry.client.tsx).

Verify

  1. Open the site in a normal browser and navigate.
  2. POST {{API_ORIGIN}}/v1/e → 204.
  3. The dashboard's install page shows the live pageviews; or ask Claude to run setup_verify_installation with your URL.

Proxy (optional)

Pick the recipe for whatever serves your site and route {{PROXY_PATH}}/* to the 3x API with the proxy key in {{PROXY_KEY_ENV}}: Nginx, Cloudflare Worker, Netlify, or any server framework using the Fetch-API handler from @3x-engine/sdk/next/proxy (Next.js proxy shows its contract). Then:

layout.html
<script async src="{{PROXY_PATH}}/v1/s/x3.full.js?k={{PUBLISHABLE_KEY}}" data-key="{{PUBLISHABLE_KEY}}" data-host="{{PROXY_PATH}}"></script>
layout.html
<script>
  // call from your banner's accept / decline handlers
  function onConsentAccepted() { x3("consent", "granted"); }
  function onConsentDeclined() { x3("consent", "denied"); }
</script>

Or configure the consent key, window event or CMP in the project settings (Consent).

Events

layout.html
<a href="/signup" data-x3-cta>Sign up</a>
<button data-x3-event="demo_request" data-x3-prop-source="header">Request a demo</button>
x3("track", "video_cta_clicked", { position: "end_screen" });