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_click

Fires when a visitor clicks a link to an external domain.

Properties: url (the destination URL)

file_download

Fires 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_click

Fires 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)
name

Required. The event name. Use snake_case. Keep it short and descriptive.

properties

Optional. 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>
AttributePurpose
data-pulse-scrollGoal name (fires as scroll_{name})
data-pulse-scroll-thresholdVisibility ratio 0.0 to 1.0 (default: 0.5)
data-pulse-scroll-delayMilliseconds 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.