---
aliases: ["Metric Semantic Layer"]
tags: [pm-skills, skill]
skill: metric-semantic-layer
description: "Define a metric in a semantic layer so it means one thing everywhere. Use when asked to define a metric, build a semantic layer / metrics layer entry, stop 'revenue means three things' problems, or write a metric definition for dbt MetricFlow / Cube / LookML. Produces a metric definition — exact formula, the base measure & aggregation, dimensions, filters, grain, edge cases, and a tool-ready spec."
---

# Metric Semantic Layer Skill

"Active users" means three different things in three dashboards — that's the problem a semantic layer
solves: define each metric **once**, precisely, and every tool reads the same definition. This skill
writes that definition — the exact formula, base measure, allowed dimensions, default filters, and the
edge cases that usually cause drift — in a tool-ready form (dbt MetricFlow / Cube / LookML).

## Required Inputs

Ask for these only if they aren't already provided:

- **The metric** — its name and the business question it answers.
- **The base data** — the model/table and the column(s) it's computed from.
- **The aggregation** — sum, count, count distinct, average, ratio.
- **Dimensions & filters** — how it can be sliced, and any default filters (exclude test accounts, internal users, refunds).
- **Tool** — dbt MetricFlow, Cube, LookML, or tool-agnostic.

## Output Format

### Metric: `[metric_name]`

**1. Definition (plain English)** — one sentence a non-analyst understands, and the precise version ("count of distinct user_ids with ≥1 qualifying event in the period, excluding internal/test accounts").

**2. Formula** — the exact calculation: base measure · aggregation · numerator/denominator (for ratios).

**3. Grain & time** — the time grain it's reported at, the date column it's anchored to, and how partial periods are handled.

**4. Dimensions** — the dimensions it can be sliced by (and any it must *not* be — non-additive metrics break when summed across the wrong dimension).

**5. Default filters** — what's always excluded (test/internal/refunds) so every consumer gets the same number.

**6. Edge cases** — null handling, late-arriving data, deduplication, currency/timezone, and additivity (can it be summed across days? across segments?). This section is where metric drift is prevented.

**7. Tool-ready spec** — the YAML/LookML for the chosen tool (MetricFlow `metrics:` / Cube `measures:` / LookML `measure:`), ready to commit.

## Quality Checks

- [ ] Has both a plain-English and an exact definition
- [ ] States the base measure, aggregation, and (for ratios) numerator/denominator
- [ ] Default filters are explicit, so every tool returns the same number
- [ ] Additivity is addressed (which dimensions it can/can't be summed across)
- [ ] Edge cases (nulls, dedup, timezone, late data) are handled
- [ ] A tool-ready spec is provided, not just prose

## Anti-Patterns

- [ ] Do not leave the definition fuzzy — "active users" without the exact rule is how three dashboards disagree
- [ ] Do not omit default filters — if one tool counts test accounts and another doesn't, the metric is broken
- [ ] Do not ignore additivity — summing a non-additive metric (like a distinct count) across days gives a wrong number
- [ ] Do not define metrics in BI tools instead of the semantic layer — that's how definitions fork
- [ ] Do not skip timezone/null/dedup edge cases — they cause the subtle, hard-to-find discrepancies

## Based On

Semantic-layer / metrics-layer practice (dbt MetricFlow, Cube, LookML) — single-source metric definitions with explicit grain, filters, and additivity.

---
<!-- Run as an AI-plugin prompt. {{selection}} is the Text Generator / Templater
     variable for the highlighted text — replace it with your plugin's equivalent
     (e.g. {} in Copilot for Obsidian), or paste your input there manually. -->
Apply the skill above to the following input:

{{selection}}
