Event Tracking
Track custom events and user interactions. No extra setup needed for common events.
Auto-Tracked Events
These events are captured automatically by the embed script. No code changes needed.
outbound_clickFires when a visitor clicks a link to an external domain.
Properties: url (the destination URL)
file_downloadFires when a visitor clicks a link to a downloadable file (.pdf, .zip, .csv, .xlsx, .doc, .dmg, .exe, etc.).
Properties: url, fileType (e.g. pdf, zip)
email_clickFires when a visitor clicks a mailto: link. The email address is NOT captured for privacy.
Properties: none
Custom Events
Track any interaction with one line of JavaScript. The pulse.track() function is available globally after the embed script loads.
Basic usage
// Track a simple event
pulse.track("signup_click");
// Track with properties
pulse.track("plan_selected", {
plan: "pro",
interval: "annual"
});Button click example
<button onclick="pulse.track('cta_click', { location: 'hero' })">
Get Started
</button>React / Next.js example
// Declare the global type
declare global {
interface Window {
pulse?: { track: (name: string, props?: Record<string, any>) => void };
}
}
// Use in a component
function SignupButton() {
return (
<button
onClick={() => window.pulse?.track("signup_click")}
>
Sign Up
</button>
);
}Form submission example
document.querySelector("form").addEventListener("submit", () => {
pulse.track("form_submit", {
formId: "contact"
});
});API Reference
pulse.track(name: string, properties?: object)nameRequired. The event name. Use snake_case. Keep it short and descriptive.
propertiesOptional. A flat object of key-value pairs. Values should be strings or numbers. Avoid nested objects.
Viewing Events
Go to your site dashboard and click the Eventstab. You'll see every event name with its total count for the selected date range. You can also ask the AI chat “What events are being tracked?” for a quick summary.
No-Code Goals
Track clicks and scroll visibility without writing any JavaScript. Just add data attributes to your HTML elements.
Click goals
Add data-pulse-goal to any element. Clicks fire an event named goal_{name}.
<button data-pulse-goal="signup_click">Sign Up</button>
<!-- With custom properties -->
<a data-pulse-goal="plan_select"
data-pulse-goal-plan="pro"
data-pulse-goal-interval="annual"
href="/checkout">
Choose Pro
</a>Scroll goals
Add data-pulse-scroll to track when an element becomes visible. Fires once per page load.
<!-- Fire when 50% visible (default) -->
<section data-pulse-scroll="pricing_seen">...</section>
<!-- Fire after 2 seconds of 80% visibility -->
<div data-pulse-scroll="cta_visible"
data-pulse-scroll-threshold="0.8"
data-pulse-scroll-delay="2000">
...
</div>| Attribute | Purpose |
|---|---|
data-pulse-scroll | Goal name (fires as scroll_{name}) |
data-pulse-scroll-threshold | Visibility ratio 0.0 to 1.0 (default: 0.5) |
data-pulse-scroll-delay | Milliseconds to wait before firing (default: 0) |
FAQ
Do events count against pageviews?
No. Events and pageviews are tracked separately. Events don't inflate your pageview count.
Is there a limit on event names?
No hard limit. Use descriptive names and keep the total number of distinct event names manageable (under 50 is ideal).
Are event properties stored securely?
Yes. Properties are stored in your Convex database alongside the event. Don't include sensitive user data like emails or passwords in properties.
Do auto-tracked events work with SPAs?
Yes. The embed script patches pushState/replaceState for SPA support. Outbound clicks and file downloads work regardless of routing.