typed sdk
The TracerKit SDK
@tracerkit/js and @tracerkit/react — typed wrappers over window.tracerkitLayerand the loader API. Integrate with autocomplete instead of copy-pasted snippets. Zero runtime dependencies; every call is SSR-safe and no-ops when the loader isn't present.
Install
Publishing to npm is a manual ops step — the packages are ready-to-publish from packages/sdk-js and packages/sdk-react in the TracerKit repo. Until they land on the registry, install from a checkout (npm install <path>) or keep using the plain snippets.
npm install @tracerkit/js # framework-agnostic core npm install @tracerkit/react # React/Next component + hook (includes the core)
@tracerkit/js
The framework-agnostic core. Types mirror the data layer spec field-for-field.
| Function | Returns | Notes |
|---|---|---|
| pushEvent(name, opts?) | void | Pushes { event: name, ...opts } onto window.tracerkitLayer. name autocompletes the five canonical events (page_view, view_item, add_to_cart, begin_checkout, purchase) and accepts any custom-trigger name. opts: { value?, currency?, items?, page_location?, page_title? } — extra fields pass through (the spec ignores unknown fields). |
| pushPurchase({ order_id, value, currency, items, email?, phone? }) | void | The purchase event, typed field-for-field from the data layer spec. Push exactly once per order — TracerKit dedupes on order_id. email/phone are optional enhanced-matching fields, hashed in-browser by the loader. |
| identify({ email?, phone? }) | void | Enhanced matching. Values are hashed in-browser (SHA-256) by the loader — raw values never leave the page. Works before the loader boots (queued on the layer). |
| consent(state) | void | Same contract as tracerkit.consent(): TracerKit categories ({ analytics, marketing }) or GCMv2 signal names ({ ad_storage, analytics_storage, ad_user_data, ad_personalization }), booleans or "granted"/"denied". Loader present → forwarded to tracerkit.consent() (blocked tags replay). Before the loader boots → normalized onto window.__tkConsent, the preset the loader applies on boot. |
| lastEventId() | string | undefined | The loader's per-fire event id. Pass it to a browser pixel (fbq eventID / ttq event_id) so the platform dedupes pixel + server into one conversion. undefined until the loader has fired an event. |
import {
pushEvent,
pushPurchase,
identify,
consent,
} from "@tracerkit/js";
// funnel events — typed to the data layer spec
pushEvent("add_to_cart", {
value: 79.98,
currency: "USD",
items: [{ id: "SKU-123", name: "Canvas Tote", price: 39.99, quantity: 2 }],
});
// exactly once per order, on the confirmation page
pushPurchase({
order_id: "1001",
value: 129.97,
currency: "USD",
items: [
{ id: "SKU-123", name: "Canvas Tote", price: 39.99, quantity: 2 },
{ id: "SKU-456", name: "Wool Beanie", price: 49.99, quantity: 1 },
],
email: "jane@example.com", // optional — hashed in-browser
});
// enhanced matching outside of purchase (e.g. after login)
identify({ email: "jane@example.com" });
// consent — categories or GCMv2 signal names, before or after the loader
consent({ analytics: true, marketing: false });
consent({ ad_storage: "granted", ad_user_data: "granted" });Pixel dedup
Share the loader's per-fire event id with your browser pixel so the platform collapses pixel + server into one conversion.
import { lastEventId, pushPurchase } from "@tracerkit/js";
pushPurchase(order);
// if you also run a browser pixel, share the event id so the platform
// dedupes pixel + server into ONE conversion:
fbq("track", "Purchase", { value, currency }, { eventID: lastEventId() });Loader-optional semantics
- During SSR (no
window) every call is a silent no-op. - Layer pushes made before the loader boots queue on the plain
window.tracerkitLayerarray and are drained on boot. consent()before boot stages normalized state onwindow.__tkConsent— the site preset the loader applies first on boot. Normalization uses the exact same helper as the loader, so category expansion (marketing ⇔ ad_storage + ad_user_data + ad_personalization) and last-write-wins ordering behave identically before and after boot.
@tracerkit/react
A component that renders the loader snippet (plain async script — no next/script) and a hook exposing the typed API.
| Function | Returns | Notes |
|---|---|---|
| <TracerKit siteKey="tk_..." api? preview? /> | JSX (a plain async <script> tag) | Renders the loader snippet — no next/script, works in React 18+ and in Next.js App Router server components. api sets a verified custom-domain origin (script src + data-api); preview sets data-preview for draft configs. |
| useTracerKit() | { pushEvent, pushPurchase, identify, consent, lastEventId } | The typed @tracerkit/js API as a stable object for event handlers and effects. All methods SSR-safe. The same functions are also re-exported from @tracerkit/react directly. |
Next.js App Router: inside <head> in the root layout
// app/layout.tsx (Next.js App Router)
import { TracerKit } from "@tracerkit/react";
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<head>
{/* the loader ships in the initial HTML — the plain-script
equivalent of next/script's beforeInteractive placement */}
<TracerKit siteKey="tk_YOUR_SITE_KEY" />
</head>
<body>{children}</body>
</html>
);
}Push events from client components
"use client";
import { useTracerKit } from "@tracerkit/react";
export function CheckoutButton({ cart }: { cart: Cart }) {
const { pushEvent } = useTracerKit();
return (
<button
onClick={() =>
pushEvent("begin_checkout", {
value: cart.total,
currency: cart.currency,
items: cart.items,
})
}
>
Checkout
</button>
);
}Agents can read this reference as markdown at /docs/sdk.md. The SDK types mirror the data layer spec field-for-field.