How Kissmetrics Works
Kissmetrics is a person-based analytics platform that ties every tracked event to an identified user rather than an anonymous session. Where Google Analytics reports aggregate pageviews and sessions, Kissmetrics builds a timeline for each individual: first touch, trial signup, feature usage, payment, and every interaction in between.
The data collection model revolves around three primitives. Identities attach a persistent ID (typically an email address) to a visitor. Events record discrete actions like "Signed Up" or "Upgraded Plan." Properties store attributes on the person, such as plan type, company size, or referral source. The JavaScript SDK queues all calls locally in _kmq and flushes them to Kissmetrics servers asynchronously, so tracking never blocks page rendering.
Kissmetrics processes incoming data through an identity resolution engine that merges anonymous visitor activity with known user profiles. When a visitor who has been browsing anonymously signs up and you call identify, every prior event is retroactively attached to that person. This stitching happens server-side and works across devices, browsers, and sessions.
The platform stores event data indefinitely, which means cohort and funnel reports can span months or years without sampling. Reports are computed on read, so you can define a new funnel today and immediately analyze historical data against it.
Installing the Kissmetrics Script
Add the Kissmetrics JavaScript library before the closing </head> tag. Replace YOUR_API_KEY with the key from your Kissmetrics site settings.
<script type="text/javascript">
var _kmq = _kmq || [];
var _kmk = _kmk || 'YOUR_API_KEY';
function _kms(u) {
setTimeout(function () {
var d = document,
f = d.getElementsByTagName('script')[0],
s = d.createElement('script');
s.type = 'text/javascript';
s.async = true;
s.src = u;
f.parentNode.insertBefore(s, f);
}, 1);
}
_kms('//i.kissmetrics.io/i.js');
_kms('//scripts.kissmetrics.io/' + _kmk + '.2.js');
</script>
To load Kissmetrics through Google Tag Manager, create a Custom HTML tag with the snippet above and set it to fire on All Pages. Make sure the tag fires before any other tags that call _kmq.push().
<!-- GTM Custom HTML Tag -->
<script type="text/javascript">
var _kmq = window._kmq || [];
var _kmk = window._kmk || 'YOUR_API_KEY';
function _kms(u) {
setTimeout(function () {
var d = document,
f = d.getElementsByTagName('script')[0],
s = d.createElement('script');
s.type = 'text/javascript';
s.async = true;
s.src = u;
f.parentNode.insertBefore(s, f);
}, 1);
}
_kms('//i.kissmetrics.io/i.js');
_kms('//scripts.kissmetrics.io/' + _kmk + '.2.js');
</script>
Verify the installation by opening the browser console and typing _kmq. You should see an array. Then check the Kissmetrics Live tab to confirm events are arriving.
Core Tracking: Identify, Track, and Set
Identifying Users
Call identify as soon as you know who the user is, typically at login or signup. Pass a unique, permanent identifier such as an email address.
_kmq.push(['identify', 'jane@example.com']);
Before identification, Kissmetrics assigns an anonymous ID. After you call identify, all prior anonymous activity merges into the named profile. If the same person later visits from a different device and logs in, both device histories unify.
Recording Events
Use record to log discrete actions. The first argument is the event name. The optional second argument is an object of properties attached to that specific event.
_kmq.push(['record', 'Signed Up', { 'Plan': 'Pro', 'Source': 'Blog CTA' }]);
_kmq.push(['record', 'Viewed Pricing Page']);
_kmq.push(['record', 'Started Trial', {
'Trial Length': 14,
'Plan': 'Business'
}]);
Setting Properties
set writes properties onto the person profile without recording an event. Use it for attributes that change over time, like plan tier or company size.
_kmq.push(['set', {
'Plan': 'Enterprise',
'Company Size': '50-200',
'Industry': 'SaaS'
}]);
Properties persist on the person and are available in every report and segment. They overwrite previous values, so calling set with 'Plan': 'Enterprise' replaces whatever plan was stored before.
Revenue and E-Commerce Tracking
Kissmetrics has first-class revenue tracking. Log billing events with a Revenue property (note the exact casing) to populate revenue reports, LTV calculations, and cohort revenue charts.
// Initial purchase
_kmq.push(['record', 'Purchased', {
'Revenue': 49.99,
'Plan': 'Pro Monthly',
'Billing Cycle': 'Monthly'
}]);
// Upgrade
_kmq.push(['record', 'Upgraded', {
'Revenue': 50.01,
'Old Plan': 'Pro Monthly',
'New Plan': 'Business Monthly'
}]);
// Cancellation (negative revenue)
_kmq.push(['record', 'Canceled', {
'Revenue': -99.99,
'Reason': 'Too expensive'
}]);
The Revenue property must be a number. Kissmetrics aggregates it across all events for a person to compute lifetime value. Negative values reduce LTV, which is how you account for refunds and cancellations.
Funnel and Cohort Analysis
Defining Funnels
Funnels in Kissmetrics are defined in the reporting UI but rely on properly tracked events. A typical SaaS funnel:
// Step 1: User visits site
_kmq.push(['record', 'Visited Site']);
// Step 2: User views pricing
_kmq.push(['record', 'Viewed Pricing']);
// Step 3: User starts trial
_kmq.push(['record', 'Started Trial']);
// Step 4: User activates (uses core feature)
_kmq.push(['record', 'Activated', {
'First Feature Used': 'Dashboard Builder'
}]);
// Step 5: User converts to paid
_kmq.push(['record', 'Converted to Paid', {
'Revenue': 49.99,
'Plan': 'Pro'
}]);
In the Kissmetrics UI, create a funnel with these five events in order. The report shows conversion rates between each step, average time between steps, and the ability to drill down into the actual people who dropped off.
Cohort Reports
Cohort reports group users by the week or month they first did something (typically "Signed Up") and track a return event (like "Logged In" or "Purchased") over subsequent periods. No additional code is needed beyond tracking the relevant events. The cohort report builder lets you pick the grouping event, the return event, and the time granularity.
A/B Testing Integration
Kissmetrics can track which experiment variant a user saw by setting a property when the variant is assigned.
// When variant is determined (e.g., by your A/B framework)
var variant = getExperimentVariant('pricing-page-v2'); // 'control' or 'new-layout'
_kmq.push(['set', { 'Pricing Page Experiment': variant }]);
_kmq.push(['record', 'Experiment Viewed', {
'Experiment Name': 'pricing-page-v2',
'Variant': variant
}]);
You can then segment any funnel or report by the Pricing Page Experiment property to compare conversion rates across variants.
Integration with Other Tools
Sending Kissmetrics Data to GA4 via GTM
Use a GTM Custom Event trigger to forward key Kissmetrics events to GA4 for cross-platform reporting.
// After recording a Kissmetrics event, also push to dataLayer
_kmq.push(['record', 'Purchased', { 'Revenue': 49.99, 'Plan': 'Pro' }]);
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
event: 'km_purchase',
km_revenue: 49.99,
km_plan: 'Pro'
});
Server-Side Tracking
Kissmetrics supports server-side event submission via HTTP. Use this for backend events like subscription renewals, webhook-triggered actions, or batch imports.
curl -X GET "https://trk.kissmetrics.io/e" \
-d "_k=YOUR_API_KEY" \
-d "_p=jane@example.com" \
-d "_n=Subscription Renewed" \
-d "Revenue=49.99" \
-d "Plan=Pro"
Data Export
Kissmetrics provides a raw data export in JSON Lines format. Each line contains a timestamp, person identifier, event name, and properties. Use this to feed a data warehouse, build custom dashboards, or join Kissmetrics data with other sources.
Common Errors
| Error | Cause | Fix |
|---|---|---|
| Events appear under anonymous IDs | identify called after record, or never called |
Call _kmq.push(['identify', email]) before recording post-login events |
| Duplicate person profiles | Different identifiers used across devices (email vs. user ID) | Standardize on one identifier format, typically email |
| Revenue reports show $0 | Property name is lowercase revenue instead of Revenue |
Use exact casing: 'Revenue': 49.99 |
| Events missing from funnel | Event names have inconsistent casing or trailing spaces | Audit event names; 'Signed Up' and 'signed up' are different events |
| Script blocked by ad blockers | Kissmetrics domains on common filter lists | Proxy through your own domain or use server-side tracking |
_kmq is not defined error |
Tracking script failed to load or loaded after custom code | Ensure the Kissmetrics snippet is in <head> before any _kmq.push() calls |
| Properties not appearing on person | set called before identify on a new device |
Call identify first, then set; or combine with record |
| Funnel shows 0% conversion | Funnel steps use event names that do not exactly match tracked events | Copy event names from the Live feed into the funnel builder |
| Cohort data looks incomplete | Events tracked only recently but cohort looks back months | Cohorts require historical data; results improve as data accumulates |
Performance Considerations
The Kissmetrics JavaScript library is approximately 20 KB gzipped. It loads asynchronously, so it does not block page rendering or affect Largest Contentful Paint (LCP). The _kmq array acts as a buffer, meaning you can push events immediately even before the library finishes loading.
For single-page applications, Kissmetrics does not automatically track page changes. You need to manually call record on route transitions:
// React Router example
useEffect(() => {
_kmq.push(['record', 'Viewed Page', { 'Page': location.pathname }]);
}, [location.pathname]);
If ad blockers are a significant concern for your audience, implement server-side tracking for critical conversion events. Client-side tracking is fine for behavioral data where 100% accuracy is not required, but revenue and signup events should go through your backend.
Avoid setting high-cardinality properties (like timestamps or unique session IDs) as person properties. These create excessive unique values in the property index and slow down reports. Use event properties instead for high-cardinality data.