All three use your site key (kst_...), take the same options and send the same events as the script tag, so read that page for events, identifying users and privacy. They send nothing during server rendering.
@knockstat/browser
npm install @knockstat/browserimport { init, track, identify, reset } from "@knockstat/browser";
init({ site: "kst_xxxx" }); // sends to https://app.knockstat.com/v1/e by default
track("signup", { plan: "pro", seats: 3 });init({ site, api, autoPageviews = true, outboundLinks = true, engagement = true, allowLocalhost = false, distinctId }) starts tracking once; later calls return the same client. Pass distinctId when you know the user at load, so the first page view carries it.
| Call | Does |
|---|---|
track(name, props?) | Sends a custom event. Name and property rules are the tag’s. |
pageview() | Sends a $pageview for the current URL. Needed only with autoPageviews: false. |
identify(distinctId) | Sets distinct_id on later events, in memory only. identify(null) clears it. |
reset() | Clears the id (log out). |
Page views follow history.pushState, replaceState and popstate, so routers that use the History API need nothing more.
React and Next.js
npm install @knockstat/reactWrap your app in the provider once. Its props after site are the init options, read on first mount. It is StrictMode-safe and sends one initial page view.
// src/main.tsx (Vite)
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import { BrowserRouter } from "react-router-dom";
import { KnockstatProvider } from "@knockstat/react";
import App from "./App";
createRoot(document.getElementById("root")!).render(
<StrictMode>
<KnockstatProvider site="kst_xxxx">
<BrowserRouter>
<App />
</BrowserRouter>
</KnockstatProvider>
</StrictMode>,
);import { useKnockstat } from "@knockstat/react";
function SignupButton() {
const { track, identify } = useKnockstat();
return (
<button onClick={() => { identify("user-123"); track("signup", { plan: "pro" }); }}>
Sign up
</button>
);
}React Router (BrowserRouter), Next.js, TanStack Router and Remix navigate through the History API, so you add nothing per route. For a router that does not (for example a memory router), set autoPageviews={false} and call usePageview(path) in each page. Requires React 18 or later.
Next.js app router: put the provider in the root layout. The package entry is marked "use client", so a server component can import it; call useKnockstat() only from client components.
// app/layout.tsx
import { KnockstatProvider } from "@knockstat/react";
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
<KnockstatProvider site="kst_xxxx">{children}</KnockstatProvider>
</body>
</html>
);
}Vue and Nuxt
npm install @knockstat/vue// src/main.ts
import { createApp } from "vue";
import { createRouter, createWebHistory } from "vue-router";
import knockstat from "@knockstat/vue";
import App from "./App.vue";
import routes from "./routes";
createApp(App)
.use(createRouter({ history: createWebHistory(), routes }))
.use(knockstat, { site: "kst_xxxx" })
.mount("#app");<script setup lang="ts">
import { useKnockstat } from "@knockstat/vue";
const { track, identify } = useKnockstat();
function signup() {
identify("user-123");
track("signup", { plan: "pro" });
}
</script>
<template>
<button @click="signup">Sign up</button>
<button @click="$knockstat.track('cta_click')">Try it</button>
</template>Vue Router’s createWebHistory() uses the History API, so page views are automatic. createWebHashHistory() changes only the hash, which is not sent as part of the path: use autoPageviews: false and call pageview() in router.afterEach. Requires Vue 3.3 or later.
Nuxt 3: install the plugin in the browser only, in a .client.ts plugin:
// plugins/knockstat.client.ts
import knockstat from "@knockstat/vue";
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.use(knockstat, { site: useRuntimeConfig().public.knockstatSite });
});
// nuxt.config.ts
export default defineNuxtConfig({
runtimeConfig: { public: { knockstatSite: "kst_xxxx" } },
});On the server useKnockstat() is a queue that is never sent, so call track from event handlers or onMounted.
Self-hosted ingest
Every entry point takes an api option for the beacon URL: init({ site, api: "https://stats.example.com/v1/e" }), <KnockstatProvider site="kst_xxxx" api="..."> or app.use(knockstat, { site, api }).
Stuck? Email [email protected].