Skip to content
Development
Skill

/analytics-events

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

From plugin
metabase
49k23 skills11 agents23 commands
Install
$ npx -y skills add metabase/metabase --skill analytics-events --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/analytics-events

Context preview

The summary Claude sees to decide when to auto-load this skill.

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

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
Ships withmetabase

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

Get the whole plugin