Custom Events
Track specific user interactions beyond basic page views.
Basic Usage
Track any interaction with the klar.track() method:
klar.track('button_click'); Track with properties:
klar.track('button_click', {
button: 'signup',
location: 'header'
});Common Use Cases
Button Clicks
// Track signup button
document.querySelector('.signup-btn').addEventListener('click', () => {
klar.track('button_click', {
button: 'signup',
location: 'hero'
});
}); Form Submissions
document.querySelector('form').addEventListener('submit', (e) => {
klar.track('form_submit', {
form: 'contact',
fields: Array.from(e.target.elements).map(el => el.name)
});
}); Purchases
klar.track('purchase', {
product: 'Pro Plan',
price: 29,
currency: 'USD',
order_id: 'order_123'
}); Video Events
// Track video plays
const video = document.querySelector('video');
video.addEventListener('play', () => {
klar.track('video_play', {
video_id: 'intro_video',
duration: video.duration
});
}); Search
searchInput.addEventListener('change', (e) => {
klar.track('search', {
query: e.target.value,
results: searchResults.length
});
});Event Properties
Add context to your events with properties:
klar.track('event_name', {
// Strings
category: 'engagement',
label: 'signup_button',
// Numbers
value: 29,
quantity: 1,
// Booleans
is_new_user: true,
// Arrays
tags: ['premium', 'trial']
});Goal Conversions and Conversion Rate
A goal turns a pageview path or an event into a conversion. The Goals card on your dashboard shows, for every goal, the conversions and the number the rate is divided by.
- Every completion counts, nothing is deduplicated. Each matching beacon adds one conversion, so a visitor who reaches a goal twice is counted twice. Klar sets no cookie, so it cannot tell a returning visitor from a new one beyond the daily hash.
- Rate = conversions divided by pageviews. The denominator is the number of pageviews in the same period, shown under each rate as "of N pageviews". An event goal can therefore exceed 100% when one page fires it several times.
- Filters apply to both numbers. A page filter narrows the conversions by their path. Any other filter (source, country, device, browser, campaign) keeps the conversions of the sessions that match it, and the same filter narrows the pageviews. Conversions recorded before filters were supported carry no session and drop out of a non-page filter.
React Integration
import { useEffect } from 'react';
function SignupButton() {
const handleClick = () => {
klar.track('button_click', {
button: 'signup',
location: 'header'
});
// ... signup logic
};
return (
<button onClick={handleClick}>
Sign Up
</button>
);
}Vue Integration
<template>
<button @click="trackClick">Sign Up</button>
</template>
<script setup>
function trackClick() {
klar.track('button_click', {
button: 'signup',
location: 'hero'
});
}
</script>Property Limits
- Maximum 50 properties per event
- Property names: maximum 64 characters
- Property values: maximum 256 characters
- An event over a limit is rejected with
400and a JSON body{ error, code, property }, wherecodeistoo_many_properties,property_name_too_longorproperty_value_too_long. Nothing is stored or truncated. - Nested objects are flattened
Funnels
Funnels match steps on the visitor, not on a 30-minute session. A funnel converts when the same visitor completes its steps in order within one visitor-id day, however many visits that takes.
The visitor id is a salted hash that rotates every UTC day, and Klar stores nothing on the device. So funnels cannot link journeys across days: someone who starts on Monday and finishes on Tuesday is counted as a drop-off. Nothing new is stored to make funnels work.