Get Kiwiq running in minutes
Install the SDK, point it at a CSS selector, and start seeing impressions, clicks and scroll events roll in.
Two ways to install
Use npm if you already have a build step, or drop in the CDN script if you don't.
Via npm
RecommendedInstall the package and import it like any other dependency.
npm install kiwiqimport Kiwiq from "kiwiq";
Kiwiq.start({
apiKey: "pk_live_xxxxxxxxx",
action: "scroll",
selector: ".feature-section",
});Via CDN
No build step required — drop this in your HTML and use the global Kiwiq object.
<script src="https://unpkg.com/kiwiq/dist/kiwiq.global.js"></script>
<script>
Kiwiq.start({
apiKey: "pk_live_xxxxxxxxx",
action: "scroll",
selector: ".feature-section",
});
</script>Configuration options
Passed to Kiwiq.start(). Call it once per selector/action pair, or pass an array to register several at once.
| Option | Type | Default | Description |
|---|---|---|---|
| apiKey | string | Required | Your project's public API key. |
| action | "impression" | "click" | "scroll" | "hover" | "submit" | Required | Which interaction to track for matching elements. |
| selector | string | Required | A CSS selector identifying the element(s) to track. |
| endpoint | string | Kiwiq's hosted collector | Override where events are sent. |
| threshold | number | 0.5 | Visibility ratio (0–1) required before impression/scroll fire. |
| hoverDelay | number | 200 | Minimum dwell time in milliseconds before hover fires. |
Tracked actions
Five interaction types, all available through the same action option.
impressionFires once per element the first time it becomes visible in the viewport.
clickFires on click. Delegated under the hood, so it also matches elements added to the page later.
scrollLike impression, but fires again every time the element crosses the visibility threshold — useful for measuring repeated re-engagement.
hoverFires after the pointer rests on the element for at least hoverDelay milliseconds.
submitFires when a matching <form> element is submitted.
About your API key
Your apiKey identifies which project an event belongs to. It's a public identifier, not a secret — similar to a Stripe publishable key — so it's safe to include directly in client-side code that ships to every visitor.
Public keys are prefixed pk_live_ in production.
How data is sent
Events are batched (up to 10, or every 2 seconds) and sent as a single request via navigator.sendBeacon, falling back to fetch with keepalive when sendBeacon isn't available. Network errors, ad blockers and CORS failures are swallowed silently — Kiwiq never throws inside your page.
Works with dynamic content
impression and scroll tracking automatically picks up elements added to the page after Kiwiq.start() runs — useful for single-page apps and anything rendered asynchronously. No need to call start() again when new matching elements appear.
See what tracked data looks like
Explore the dashboard to see how impressions, clicks and scroll events come together.