Skip to content
Back to skills

Domain Product

ASecurity

Product analytics rules: calendar spine cross-joins, date boundary caps, event type pivoting, first-run NULL behavior.

  • 485 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added September 3, 2026
data

Security analysis

A100/100

Scanned September 3, 2026

npx -y skills add SignalPilot-Labs/SignalPilot --skill domain-product --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Domain Product?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Domain Product
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/signalpilot-labs-domain-product/badge)](https://www.skillsdirectory.com/skills/signalpilot-labs-domain-product)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: domain-product
description: "Product analytics rules: calendar spine cross-joins, date boundary caps, event type pivoting, first-run NULL behavior."
---

# Product Analytics

## Driving Table

When aggregating usage or event metrics, drive FROM the fact/event table (events, sessions, pageviews), not the dimension table (users, features, pages). Users with zero activity MUST NOT appear in activity reports - they have no data to aggregate.

## Calendar Spine Cross-Joins

Daily metrics models that cross-join a calendar spine with entities (users, features, pages) MUST cap the join at `current_date` - generating rows beyond today produces phantom future rows with zero metrics that inflate row counts.

If the YML description says "from creation date to current date," add `AND spine.date_day >= entity.created_at::date AND spine.date_day <= current_date` to the join condition - both bounds are required.

NEVER cross-join without a date cap - unbounded spines grow indefinitely and break row count expectations.

When an entity has a `created_at` or equivalent timestamp, the spine MUST start from that date, not from the earliest date in the spine - starting earlier produces rows before the entity existed.

## Event Type Pivoting

When an events table has a `type` or `event_name` column, pivot distinct values into separate metric columns - each event type becomes a `count_<type>` column in the output.

Do NOT filter the events table to a single type before pivoting - all types must appear in the output as separate columns, using conditional aggregation (`COUNT(CASE WHEN type = 'x' THEN 1 END)`).

Read the YML or a sibling model to confirm the exact set of event types expected - inventing column names from partial data causes schema mismatches.

## First-Run Behavior

On first build with no prior state, rolling window columns (7-day avg, 30-day sum) MUST be NULL for the first N-1 periods - this is correct behavior, not a bug.

Do NOT substitute 0 for NULL in rolling window columns - NULL means "insufficient history," 0 means "activity was zero."

Period-over-period columns follow the same rule: NULL on first build. See dbt-workflow "Incremental Models and Period-Over-Period Columns" for the full rule.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…