Custom events

Track your own events with mrkr.track() or the declarative data-mrkr-event attribute, with the exact property limits, and why none of it is billed.

Markdown
Updated Oct 3, 2026
On this page
  1. mrkr.track()
  2. The declarative attribute: data-mrkr-event
  3. Configure and explore an event
  4. Configure through your AI assistant
  5. Property limits
  6. Naming conventions

The tracker records the visit for you: pageviews, outbound clicks, downloads, engaged time. Anything that happens inside your product is yours to name, with mrkr.track() or its declarative counterpart. Neither costs you anything: custom events do not count toward your plan's quota.

mrkr.track()

Call it from your own code, anywhere after the script tag has loaded:

js
window.mrkr?.track("signup_completed", { plan: "pro", placement: "landing_page" });

The first argument is the event name (truncated to 64 characters). The second is an optional flat object of properties. There's no need to declare an event before you send it: the first time an event name arrives, it registers itself and immediately shows up in your Events list.

The declarative attribute: data-mrkr-event

For clicks specifically, you can skip writing JavaScript entirely and annotate the element instead:

html
<button data-mrkr-event="cta_click"
        data-mrkr-prop-variant="hero"
        data-mrkr-prop-plan="pro">
  Get started
</button>

This fires the same as calling mrkr.track("cta_click", { variant: "hero", plan: "pro" }) on click. Each data-mrkr-prop-* attribute becomes one property; multi-word attribute names (data-mrkr-prop-plan-tier) come through as plan_tier, matching what you wrote in the HTML.

Configure and explore an event

  1. Send a meaningful event

    Call window.mrkr.track() after the tracker loads and after the action succeeds. For a signup, track the completed signup rather than every click on the form. Optional chaining avoids an error before the tracker loads but does not queue a missed event.

  2. Open Events

    Your event appears automatically. Search for its captured name, then open its row. Set a readable display label and mark it as a conversion when it represents an outcome.

  3. Configure its value

    For an event such as order_completed, set Revenue property to a numeric property such as total, and include currency in each payload. Leave it unset for nonmonetary events. Use one revenue event per purchase to avoid counting the same payment twice.

  4. Filter traffic

    Choose Filter traffic in the event drawer, or select Event in Filters. Sources, Revenue, Visitors and the overview now show matching sessions. Multiple events use OR; events combine with source, campaign and other dimensions using AND.

A valued custom eventjs
window.mrkr?.track("order_completed", {
  total: 49.00,
  currency: "USD",
  plan: "pro"
});
// In Events, mark order_completed as a conversion.
// Set Revenue property to total (major currency units).
// Send this OR mrkr.revenue() for the purchase, not both.

Configure through your AI assistant

You can also connect an assistant through MCP and grant Configure custom events for this site. Ask it to read the current definition, then set a display label, conversion flag and revenue property. configure_event can declare a definition before its first occurrence; it changes configuration without sending a synthetic event. See the exact tool inputs.

Property limits

Properties are bounded on both the client and the server, so a stray payload can't blow up storage or the bytes your visitors upload:

LimitValue
Event name length64 characters
Properties per event8
Property key length64 characters
Allowed key charactersletters, digits, _, ., :, -
Property value length (strings)256 characters
Total serialized properties size2,048 bytes
  • Booleans and finite numbers are stored as-is; NaN and Infinity are dropped.
  • Strings longer than 256 characters are truncated, not rejected.
  • Objects and arrays are JSON-stringified, then truncated the same way as a string: nested structures survive as a stringified blob, but they can't be broken down by key in the dashboard.
  • null and undefined values are dropped entirely rather than stored as empty.
  • If you send more than 8 properties, the ones that get dropped are chosen deterministically (by sorting keys alphabetically and keeping the first 8), so the same payload always keeps the same subset instead of a random one.

Naming conventions

Event names and property keys become labels in your dashboard's breakdown UI, so treat them like you would a database column: lowercase, snake_case, and consistent across call sites (signup_completed, not signup_completed in one place and SignupComplete in another; those are two different events to mrkr). Avoid putting anything personally identifying in an event name or a property value; properties are for categories to group by (a plan tier, a variant, a step number), not free text.