Browse documentation

Custom events

Configure the client, track meaningful product outcomes, attach useful properties, and verify delivery.

1. Configure the client

Install and initialize Tracwell once in browser-only code. Add delivery callbacks while integrating so failures are visible instead of silent.

analytics.ts
import { createTracwell } from "tracwell";

const analytics = createTracwell({
  collectionMode: "product",
  projectKey: "tw_live_...",
  onDelivery(report) {
    console.log("Tracwell delivery", report.status, report.eventIds);
  },
  onError(error) {
    console.error("Tracwell error", error.code, error.issues);
  },
});

Use private mode for privacy-preserving website analytics. Use product mode when you need persistent anonymous identity, sessions, or identify().

If your framework renders on the server, follow its integration guide and create the client only after the document is available.

2. Name the outcome

Name events after completed outcomes such as signup_completed, checkout_started, or report_exported. Keep the name stable and put changing values in properties.

Event name rules
Start
The first character must be a letter.
Characters
Letters, numbers, periods, underscores, colons, and hyphens.
Length
Between 1 and 100 characters.
Reserved
identify and page_view.
Prefer plan_selected with a plan property over dynamic names such as starter_plan_selected and pro_plan_selected.

3. Track after success

For actions confirmed by your backend, follow the server events guide to record the result with the same visitor/session identity.

Call track() after the product action succeeds. A button click expresses intent; the confirmed result is the useful outcome.

TypeScript
async function handleSignup() {
  const account = await createAccount();

  analytics.track("signup_completed", {
    account_type: account.type,
    plan: account.plan,
  });
}

track() returns the event ID when the event enters the delivery queue. It returns undefined when collection is blocked or validation fails; onError provides the reason for validation failures.

TypeScript
const eventId = analytics.track("signup_completed", {
  plan: "starter",
  source: "pricing",
});

if (!eventId) {
  // Collection is blocked or the event did not pass validation.
}

4. Add useful properties

Properties become filters and breakdowns in reports. Send dimensions you expect to compare later, using JSON-compatible strings, finite numbers, booleans, null, arrays, and nested objects.

TypeScript
analytics.track("report_exported", {
  format: "csv",
  filters: {
    country: "IN",
    range: "last_30_days",
  },
  included_sections: ["overview", "acquisition"],
  row_count: 1842,
});
Property limits
Properties
Up to 100 keys across the event.
Nesting
Up to 4 levels deep.
Arrays
Up to 50 items.
Keys
Up to 128 characters.
Strings
Up to 1,024 characters.
Event size
Up to 16 KiB after serialization.
Never send passwords, authentication tokens, payment-card data, health data, secrets, or unnecessary personal data.

5. Verify the event

Verification checklist
  1. 1

    Open the live stream

    Go to Events in the Tracwell dashboard and open the live stream.

  2. 2

    Perform the action

    Complete the real product outcome in your application.

  3. 3

    Flush while testing

    Call await analytics.flush() when you need to send the current batch immediately.

  4. 4

    Inspect the event

    Confirm the name, project, page, and properties match what you intended.

A delivery status of accepted means the collector returned a matching acceptance receipt. handed_off means the browser handed the batch to sendBeacon while the page was leaving; it is not a server acceptance confirmation.

Using the script build

If you installed the CDN script instead of the npm package, call the same API through window.tracwell.

JavaScript
window.tracwell?.track("signup_completed", {
  plan: "starter",
  source: "pricing",
});

Common mistakes

Before shipping
Tracking intent
Record the successful outcome instead of only the click that started it.
Dynamic names
Keep names stable and move variants such as plan or source into properties.
Duplicates
Track an outcome from one owning success path, not from both a button and an effect.
Manual pages
Let the Browser SDK track standard History API navigation automatically.
Sensitive data
Use opaque internal identifiers and collect only what the report needs.