Skip to content
Development
Skill

/analytics-events

Add product analytics events to track user interactions in the Metabase frontend

From plugin
metabase
50k30 skills11 agents23 commands

Claude Code

$ npx -y skills add metabase/metabase --skill analytics-events --agent claude-code

SKILL.md

analytics-events.SKILL.md
name: analytics-events
description: Add product analytics events to track user interactions in the Metabase frontend
allowed-tools: Read, Write, Edit, Grep, Glob

Frontend Analytics Events Skill

This skill helps you add product analytics (Snowplow) events to track user interactions in the Metabase frontend codebase.

Quick Reference

Analytics events in Metabase use Snowplow with typed event schemas. Simple events are declared **where they are used** — `trackSimpleEvent` is generic and validates the payload at the call site.

**Key Files:**

  • `frontend/src/metabase/analytics/event.ts` - Core tracking functions, `trackSimpleEvent` / `trackSchemaEvent` (import from `metabase/analytics`)
  • `frontend/src/metabase-types/analytics/event.ts` - The shared `SimpleEventSchema` only. **Do not add event types here** (see below)
  • `frontend/src/metabase-types/analytics/schema.ts` - Schema registry (custom/legacy schemas only)
  • Feature-specific `analytics.ts` files - Where your tracking functions and any local types live

Quick Checklist

When adding a new analytics event:

  • [ ] Pick an event name (snake_case, past tense)
  • [ ] Add a tracking function to the feature's `analytics.ts` file, calling `trackSimpleEvent()`
  • [ ] Keep any field unions (e.g. `"success" | "failure"`) as local types in that same file
  • [ ] Import and call the tracking function at the interaction point
  • [ ] Do **not** add an event type to `metabase-types/analytics/event.ts` or to any union

Event Schema Types

1. Simple Events (Most Common)

Use `SimpleEventSchema` for straightforward tracking. It supports these standard fields:

type SimpleEventSchema = {
  event: string;                    // Required: Event name (snake_case)
  target_id?: number | null;        // Optional: ID of affected entity
  triggered_from?: string | null;   // Optional: UI location/context
  duration_ms?: number | null;      // Optional: Duration in milliseconds
  result?: string | null;           // Optional: Outcome (e.g., "success", "failure")
  event_detail?: string | null;     // Optional: Additional detail/variant
};

**When to use:** 90% of events fit this schema. Use for clicks, opens, closes, creates, deletes, etc.

`trackSimpleEvent` is generic and enforces this schema on the object literal you pass it:

// frontend/src/metabase/analytics/event.ts
export function trackSimpleEvent<
  T extends SimpleEventSchema &
    Record<Exclude<keyof T, keyof SimpleEventSchema>, never>,
>(event: T) {
  trackSchemaEvent("simple_event", event);
}

That means a missing `event` or any field outside `SimpleEventSchema` is a compile error at the call site. There is no separate event type to declare and no `satisfies` clause to add — the old `ValidateEvent<...>` helper is no longer exported and is not part of the workflow.

`trackSchemaEvent` is generic too: it correlates the schema name with the payload type, so you can't send a dashboard event under the `simple_event` schema.

2. Custom Schemas (legacy, no events are being added)

Consider adding new event schema only in very special cases.

**Examples:** `DashboardEventSchema`, `CleanupEventSchema`, `QuestionEventSchema`

Step-by-Step: Adding a Simple Event

Example: Track when a user applies filters in a table picker

Step 1: Create Tracking Functions

In your feature's `analytics.ts` file (e.g., `enterprise/frontend/src/metabase-enterprise/data-studio/analytics.ts`):

import { trackSimpleEvent } from "metabase/analytics";

export const trackDataStudioTablePickerFiltersApplied = () => {
  trackSimpleEvent({
    event: "data_studio_table_picker_filters_applied",
  });
};

export const trackDataStudioTablePickerFiltersCleared = () => {
  trackSimpleEvent({
    event: "data_studio_table_picker_filters_cleared",
  });
};

Step 2: Use in Components

Import and call the tracking function at the interaction point:

import {
  trackDataStudioTablePickerFiltersApplied,
  trackDataStudioTablePickerFiltersCleared,
} from "metabase-enterprise/data-studio/analytics";

function FilterPopover({ filters, onSubmit }) {
  const handleReset = () => {
    trackDataStudioTablePickerFiltersCleared(); // <- Track here
    onSubmit(emptyFilters);
  };

  return (
    <form
      onSubmit={(event) => {
        event.preventDefault();
        trackDataStudioTablePickerFiltersApplied(); // <- Track here
        onSubmit(form);
      }}
    >
      {/* form content */}
    </form>
  );
}

Using SimpleEventSchema Fields

All examples below live in the feature's own `analytics.ts` — nothing is registered centrally.

Example: Event with target_id

export const trackDataStudioLibraryCreated = (id: CollectionId) => {
  trackSimpleEvent({
    event: "data_studio_library_created",
    target_id: Number(id),
  });
};

// Usage
trackDataStudioLibraryCreated(newLibrary.id);

Example: Event with triggered_from

// Local union, exported only if another feature needs to pass the same value
export type NewButtonLocation = "app-bar" | "empty-collection";

export const trackNewButtonClicked = (location: NewButtonLocation) => {
  trackSimpleEvent({
    event: "new_button_clicked",
    triggered_from: location,
  });
};

// Usage
<Button onClick={() => {
  trackNewButtonClicked("app-bar");
  handleCreate();
}}>
  New
</Button>

Example: Event with event_detail

Real example — `frontend/src/metabase/metadata/pages/shared/analytics.ts`:

export type MetadataEditEventDetail =
  | "type_casting"
  | "semantic_type_change"
  | "visibility_change";

export const trackMetadataChange = (detail: MetadataEditEventDetail) => {
  trackSimpleEvent({
    event: "metadata_edited",
    event_detail: detail,
    triggered_from: "admin",
  });
};

// Usage
trackMetadataChange("semantic_type_change");

Example: Event with result and duration

See `frontend/src/metabase/archive/analyti

Read more
@metabase
Ships withmetabase

Metabase is the easy, open-source way for everyone in your company to ask questions and learn from data.

50k30 skills11 agents
Get the whole plugin

Stars on GitHub

Momentum

stars in total
50.3k
Star history of metabase/metabase on GitHub, a chart by star-history.com

Other skills on metabase.

add-malli-schemas

add-malli-schemas

Efficiently add Malli schemas to API endpoints in the Metabase codebase with proper patterns, validation timing, and error…

@metabase@metabaseInstall Skill
add-tracing

add-tracing

Add OpenTelemetry tracing spans to Clojure code following Metabase tracing conventions. Use when instrumenting backend code with…

@metabase@metabaseInstall Skill
api-changelog

api-changelog

Draft or audit the REST API changelog (docs/developers-guide/api-changelog.md) by semantically diffing the checked-in OpenAPI…

@metabase@metabaseInstall Skill
app-db-migrations

app-db-migrations

Add, test, run and roll back application-database (Liquibase) migrations. Use when adding a changeset, changing a table or column…

@metabase@metabaseInstall Skill
clojure-eval

clojure-eval

Evaluate Clojure code via nREPL using clj-nrepl-eval. Use this when you need to test code, check if edited files compile, verify…

@metabase@metabaseInstall Skill

More skills from other plugins.

brainstorming
Auto-invoked

brainstorming

You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…

@obra@obraInstall Skill
ask-matt

ask-matt

Ask which skill or flow fits your situation. A router over the skills in this repo.

skills11d309k
@mattpocock@mattpocockInstall Skill
accessibility
Auto-invoked

accessibility

Design, implement, and audit accessible UI to WCAG 2.2 Level AA across Web, iOS, and Android — semantic ARIA roles and labels,…

ecc12d293k
@affaan-m@affaan-mInstall Skill
compiler-commit

compiler-commit

Use when you want to verify compiler changes and commit with the correct convention. Runs tests, lint, and format, then commits…

react2d252k
@facebook@facebookInstall Skill

Questions about analytics-events.

Which coding agents can use analytics-events?
analytics-events installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.