Astro
Install
---
const key = "{{PUBLISHABLE_KEY}}";
---
<html lang="en">
<head>
<script is:inline>window.x3=window.x3||function(){(window.x3q=window.x3q||[]).push(arguments)}</script>
<script is:inline async src={`{{API_ORIGIN}}/v1/s/x3.full.js?k=${key}`} data-key={key}></script>
</head>
<body>
<slot />
</body>
</html>is:inline keeps Astro from bundling the tags. With <ClientRouter /> (view transitions) the
History API patch reports every transition as an spa pageview; the script runs once.
Verify
npm run dev, open the site, follow a link.POST {{API_ORIGIN}}/v1/e→ 204 in the network tab.- The dashboard's install page shows the pageviews.
Proxy (optional)
With an SSR adapter (Node, Vercel, Netlify, Cloudflare) add an endpoint; static builds use a host-level proxy instead (Cloudflare Worker, Netlify).
npm install {{API_ORIGIN}}/v1/sdk/3x-engine-sdk-0.1.0.tgzX3_API_ORIGIN={{API_ORIGIN}}
{{PROXY_KEY_ENV}}=sk_3x_YOUR_PROXY_KEYimport type { APIRoute } from "astro";
import { createX3ProxyHandler } from "@3x-engine/sdk/next/proxy";
export const prerender = false;
const handler = createX3ProxyHandler({ apiOrigin: import.meta.env.X3_API_ORIGIN, proxyKey: import.meta.env.{{PROXY_KEY_ENV}} });
export const GET: APIRoute = ({ request }) => handler.GET(request);
export const POST: APIRoute = ({ request }) => handler.POST(request);
export const OPTIONS: APIRoute = ({ request }) => handler.OPTIONS(request);<script is:inline async src={`{{PROXY_PATH}}/v1/s/x3.full.js?k=${key}`} data-key={key} data-host="{{PROXY_PATH}}"></script>The handler only uses the Fetch API, so it runs on every Astro adapter despite the next in its
import path.
Consent
<div id="consent">
<button data-consent="granted">Accept</button>
<button data-consent="denied">Decline</button>
</div>
<script is:inline>
document.querySelectorAll("#consent [data-consent]").forEach((button) =>
button.addEventListener("click", () => window.x3("consent", button.dataset.consent)),
);
</script>Events
<a href="/contact" data-x3-cta data-x3-section="hero">Talk to us</a>
<button data-x3-event="pricing_toggle" data-x3-prop-period="yearly">Yearly</button>Script alternative: window.x3("track", "pricing_toggle", { period: "yearly" }).