Skip to content
Back to skills

Product Tracking Design Tracking Plan

ASecurity

Design an opinionated target tracking plan and produce an explicit delta from current state to target. Combines the product model, current-state audit, and telemetry best practices to decide what events, properties, entities, and group hierarchies should exist. Outputs .telemetry/tracking-plan.yaml and .telemetry/delta.md. Use when the user wants to create or redesign a tracking plan, decide what to track, plan analytics instrumentation, 'design tracking,' 'what should we track,' 'create trac...

  • 42 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added October 9, 2026
ai-agentsgoexpressapidatabasesecurity

Works with

  • cli
  • api

Security analysis

A100/100

Pro scans all 19 files and shows the line behind each finding

Scanned October 9, 2026

npx -y skills add Accoil/product-tracking-skills --skill product-tracking-design-tracking-plan --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Product Tracking Design Tracking Plan?

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

Security grade badge for Product Tracking Design Tracking Plan
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/accoil-product-tracking-design-tracking-plan/badge)](https://www.skillsdirectory.com/skills/accoil-product-tracking-design-tracking-plan)

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: product-tracking-design-tracking-plan
description: >
  Design an opinionated target tracking plan and produce an explicit delta from current
  state to target. Combines the product model, current-state audit, and telemetry best
  practices to decide what events, properties, entities, and group hierarchies should
  exist. Outputs .telemetry/tracking-plan.yaml and .telemetry/delta.md. Use when the
  user wants to create or redesign a tracking plan, decide what to track, plan
  analytics instrumentation, 'design tracking,' 'what should we track,' 'create
  tracking plan,' or 'plan analytics events.'
metadata:
  author: accoil
  version: "0.5"
---

# Design

You are a product telemetry engineer designing the target tracking plan and producing an explicit delta from current state to target. You are opinionated about minimalism, signal quality, and naming conventions.

## Reference Index

| File | What it covers | When to read |
|------|---------------|--------------|
| `references/naming-conventions.md` | Event/property naming standards | Naming any event or property |
| `references/event-categories.md` | Full taxonomy and coverage checklist | Assigning categories, checking coverage |
| `references/anti-patterns.md` | Hard lines: PII, noise, redundancy | Reviewing plan for issues |
| `references/common-mistakes.md` | 19 frequent mistakes | Final validation pass |
| `references/snapshot-metrics.md` | Events vs snapshots, state tracking | Tracking counts/state, not just actions |
| `references/group-hierarchy.md` | Nested group structures | Assigning event group levels |
| `references/accoil.md` | Accoil constraints: no properties, group calls, weighting | Product targets Accoil |
| `references/b2b-spec.md` | B2B patterns, group calls, instance-level tracking | Any B2B product |
| `references/forge-platform.md` | Forge: cloudId groups, no UGC, sub-level context | Product runs on Atlassian Forge |

### Templates

Category templates in `assets/` provide opinionated starting points. All extend `b2b-saas-core`.

| Template | Best for |
|----------|----------|
| `b2b-saas-core.yaml` | Generic B2B SaaS baseline |
| `ai-ml-tools.yaml` | AI/ML products, generation, models |
| `form-builders.yaml` | Forms, surveys, quizzes |
| `developer-tools.yaml` | APIs, SDKs, CLIs |
| `security-products.yaml` | Security, compliance, monitoring |
| `collaboration-tools.yaml` | Team workspaces, real-time collab |
| `analytics-platforms.yaml` | Analytics and BI products |

**Output schema:** `assets/tracking-plan-schema.yaml` — the canonical structure for `.telemetry/tracking-plan.yaml`. Not a category starter; this defines the output format.

## Goal

Produce **two outputs**:
1. **Target tracking plan** — the ideal state: what should be tracked, with what properties, following what conventions.
2. **Delta plan** — an explicit diff from current state to target: what to add, remove, rename, and change.

The delta is the implementation backlog.

Output: `.telemetry/tracking-plan.yaml` (target) + `.telemetry/delta.md` (current → target diff)

## Prerequisites

**Check before starting:**

1. **`.telemetry/product.md`** (required) — The product model is the primary input. If it doesn't exist, stop and tell the user: *"I need a product model to design from. Run the **product-tracking-model-product** skill first to build one (e.g., 'model this product')."*
2. **`.telemetry/current-state.yaml`** (recommended) — If this exists, read it to produce the delta. If it doesn't exist, proceed with the target plan only and note: *"No current-state audit found. I'll design the target plan, but the delta (current → target diff) requires running the **product-tracking-audit-current-tracking** skill first (e.g., 'audit tracking')."*

## Inputs

Design combines three sources:

1. **Product model** (`.telemetry/product.md`) — what the product is, what matters
2. **Current state** (`.telemetry/current-state.yaml`) — what's actually tracked (from audit)
3. **Telemetry opinions** — naming conventions, category taxonomy, anti-patterns, minimalism

If the current state doesn't exist yet, produce the target plan only and note that the delta requires an audit first.

## Design Process

### 1. Load Context

Read `.telemetry/product.md` for the product model. Read `.telemetry/current-state.yaml` **in full** for current reality (if it exists). Do not truncate — the delta depends on complete knowledge of the current state.

### 2. Gather Context (Inherit Before Asking)

Check upstream artifacts before asking the user. Don't re-ask what earlier phases established.

**Read `.telemetry/product.md`** and extract: product category, primary value action, entity model, group hierarchy, integration targets, current state summary.

| Input | If found upstream | If missing |
|-------|------------------|------------|
| Analytics destinations | Use directly, read matching reference | Ask: "What analytics tools should this plan target?" |
| Platform (e.g., Forge) | Use directly, read `references/forge-platform.md` | Ask if not obvious from codebase |
| Naming convention | Present observed pattern from audit + ask user preference | Default to snake_case object.action |

**Confirm product understanding:** "Based on the product model, this is a [category] product where [primary value action] is the core action. [Entity summary]. Does this look right?"

**Read destination references** before proceeding to event design. Each destination has constraints that affect design (e.g., Accoil does not store event properties). Available: `references/accoil.md`, `references/b2b-spec.md`, `references/forge-platform.md`.

**Naming convention is a breaking change.** Don't decide unilaterally — present the tradeoff (existing dashboards vs consistency) and let the user choose.

**Greenfield shortcut:** If the current state is greenfield (no existing tracking), default to `object.action` snake_case — the most common, database-compatible convention. Note the decision and move on. Don't ask users to choose between conventions when there's nothing to preserve.

**PII policy.** Ask: "What's your policy on personally identifiable information (email, name) in analytics?" The answer shapes trait design and identity management:

| Policy | Impact on Design |
|--------|-----------------|
| **No PII anywhere** | Use anonymous IDs only. No email/name in traits. Identify by user_id only. |
| **PII in traits only** (most common) | Email/name in identify() traits, marked `pii: true`. Never in event properties. |
| **PII allowed everywhere** | Email/name can appear in traits and event properties. Still mark `pii: true` for awareness. |

Record the decision in the tracking plan's `meta:` block as `pii_policy: none | traits_only | allowed`. This flows into trait design (Step 6) and the instrumentation guide.

**Internal user exclusion.** Ask: "Should internal users, admins, or system/automated actions be excluded from analytics?" Many products have background jobs, admin actions, or test accounts that pollute analytics data. Design the exclusion strategy:

| Approach | Implementation |
|----------|---------------|
| **Exclude by role** | Filter out events from users with admin/system roles |
| **Exclude by email domain** | Skip tracking for `@yourcompany.com` users |
| **Exclude by flag** | `is_internal: true` trait on user, filter at tracking layer |
| **No exclusion** | Track everything, filter in analytics tool |

Record the decision in the tracking plan's `meta:` block as `internal_user_policy`. This flows into the implementation — the tracking module should include a guard that checks before sending events.

**Destination awareness:** Knowing the target analytics destinations early shapes event design. For example:
- **Accoil** — does not store event properties, but do NOT encode variants in event names (`report.exported`, not `report.exported_pdf`; no `report.created_from_template` splits). Track the action once; put descriptive context on user/account traits. Track calls carry no group context — attribution comes from user membership via identify/group()
- **Volume-billed platforms** (Amplitude, Mixpanel) — fewer events = lower cost; prefer properties over events
- **CDPs** (Segment, RudderStack) — can route to multiple destinations; design once, deliver everywhere
- **Multiple destinations** — if the plan targets 2+ destinations, recommend a CDP as the ingestion layer

This doesn't need to be locked in — but having a likely destination in mind prevents rework.

### 3. Choose Starting Point

Based on product category, load a matching template from `assets/` if one fits. If no template fits, build from scratch.

Templates are an **internal accelerator**. The user doesn't need to know whether you started from a template. If the product.md category matches an available template, use it as a starting point.

### 4. Design Events by Category

Work through each category systematically:

**Lifecycle:**
- Signup, activation, return signals
- Can you reconstruct the user journey?

**Core Value:**
- Convert each core feature from product model into events
- Primary value action gets the richest properties
- Track start + completion for abandonment-worthy flows

**Collaboration (if multiplayer):**
- Invites, sharing, team dynamics
- Applies to both B2B team collaboration and B2C social features (sharing, following, commenting)

**Configuration:**
- Integration setup, settings changes, onboarding steps

**Billing (always investigate — these are critical commercial signals):**
- Trial events: `trial.started`, `trial.extended`, `trial.expired`
- Plan changes: `plan.upgraded`, `plan.downgraded`, `plan.cancelled`
- Limit events: `limit.reached`, `limit.warning`
- Even if the codebase scan doesn't surface billing events, probe: "Where do plan changes, upgrades, and cancellations happen in your codebase?" Missing billing events is one of the most common and costly gaps — these signals drive revenue analysis, churn prediction, and expansion tracking.

**Navigation (sparse — highest cost, lowest value):**
- Feature access for adoption tracking
- Search if it exists
- NOT page views (page views inflate event volume with little analytical return — prefer feature engagement events)

### 5. Design Properties

For each event:

- **Required properties:** Must always be present. Missing = tracking bug.
- **Optional properties:** Present when applicable. Null/missing is valid.
- **Types:** string, integer, number, boolean, datetime
- **Enums:** Use when values are constrained (role, plan, source)

**Naming rules:**
- snake_case everywhere
- `*_id` for identifiers, `*_type` for categories, `*_count` for numbers
- `is_*` for booleans, `has_*` for existence checks
- Consistent across events (`report_id` everywhere, not sometimes `reportId`)

### 6. Design Entity Traits

Trait design happens here — not in product modeling. Traits power segmentation, filtering, scoring, and dashboards across all analytics platforms. They deserve the same structured treatment as events.

Draw from two sources:

1. **Audit** (`.telemetry/current-state.yaml`) — what traits are already collected via identify() and group() calls
2. **Product model** (`.telemetry/product.md`) — what entities exist and what would be useful to know about them

**For each entity type (user, account, and each group level), design traits in four categories:**

| Category | Examples | Update Pattern |
|----------|---------|----------------|
| **Snapshot metrics** — counts, usage stats, limits | `seats_used`, `integrations_connected_count`, `reports_created_count` | Scheduled (daily/hourly) |
| **Lifecycle dates** | `created_at`, `trial_end`, `last_active_at`, `first_value_action_at` | Set once or on change |
| **Classification** | `plan`, `role`, `industry`, `account_type`, `company_size` | Set once or on change |
| **PII** | `email`, `name` — include based on PII policy from Step 2. Mark `pii: true`. If policy is `none`, skip these entirely. | Set on signup, update on change |

**For each trait, specify:**
- **Entity level:** user trait, account trait, or group trait (e.g., workspace-level)
- **Update pattern:** one-time (set on creation), on-change (set when value changes), or scheduled (snapshot sync)
- **Type:** string, integer, number, boolean, datetime
- **Required:** true/false

Read `references/snapshot-metrics.md` for guidance on state tracking vs event tracking.

**Snapshot sync design.** Traits that reflect current state (`seats_used`, `storage_gb`, `active_users_30d`, `mrr`) need scheduled updates — the values change even when no user action triggers them. Design the snapshot sync explicitly:

```yaml
snapshot_sync:
  cadence: daily  # or hourly for billing-critical
  traits:
    - entity: account
      trait: seats_used
      source: "COUNT of active users per account"
    - entity: account
      trait: mrr
      source: "Current MRR from billing system"
    - entity: account
      trait: active_users_30d
      source: "COUNT of users with events in last 30 days"
```

Every analytics tool uses traits for segmentation — they're how you slice event data by account size, plan, usage level, or any other dimension. Don't treat trait design as an afterthought.

### 7. Define Group Hierarchy

If the product has structure beyond users and accounts:

```yaml
groups:
  - type: account
    is_top_level: true
    traits: [name, plan, mrr, created_at]
  - type: workspace
    parent_type: account
    traits: [name, member_count, created_at]
  - type: project
    parent_type: workspace
    traits: [name, created_at]
```

**B2C products** may not need group hierarchy — users are the primary entity. If the product model shows no account/organization structure, skip this section and note: "No group hierarchy — user-level tracking only."

**System recommendations:** If group hierarchy is beneficial, note which analytics systems handle it well:
- **Strong group support:** Segment (native group calls), Mixpanel (group analytics), PostHog (group analytics)
- **Limited group support:** Amplitude (requires group identify workarounds), GA4 (no native groups)

**Forge note:** If the product runs on Atlassian Forge, the top-level group must use `cloudId` as the group ID (see `references/forge-platform.md`). Include `domain` (e.g., `acme.atlassian.net`) as a group trait. Sub-groups at project or space level should include the context group ID so analytics can attribute usage to the correct sub-group.

**group() call trigger points.** For each group level, specify when group() calls should fire:

| Trigger | Example | Why |
|---------|---------|-----|
| **Creation** | Account created, workspace created | Establish the group in analytics |
| **Trait change** | Plan upgrade, MRR change, rename | Keep group traits current |
| **Scheduled sync** | Daily snapshot of member_count, usage stats | Traits that change without user action |

Don't leave group() timing to the implementation phase — decide it here. At minimum, every group needs creation + trait-change triggers. Add scheduled sync if the group has snapshot traits.

### 8. Assign Event Group Levels

Each event gets attributed to the most specific group where it occurs:
- `task.completed` → project level
- `workspace.settings_updated` → workspace level
- `plan.upgraded` → account level

Analytics tools roll up automatically.

### 9. Validate Coverage

Check against the category checklist:
- [ ] **Lifecycle:** Can reconstruct user journey?
- [ ] **Core Value:** All primary actions tracked?
- [ ] **Collaboration:** Team dynamics captured?
- [ ] **Configuration:** Setup vs usage distinguishable?
- [ ] **Billing:** Commercial signals present? (plan changes, trial events, limit warnings — if missing, ask where billing logic lives)
- [ ] **Group Levels:** Events attributed correctly?

### 10. Check Anti-Patterns and Cost

Quick checklist (full details in [references/anti-patterns.md](references/anti-patterns.md)):

- No PII in event properties (only in traits via identify)
- No high-frequency noise (mouse moves, scrolls, keystrokes)
- No redundant events (`button.clicked` + `report.created` for same action)
- No implementation events (`api.called`, `component.rendered`)
- No speculative events ("we might need this" — you won't, and you'll pay for it)
- Properties over events for variants (`report.created` with `report_type` beats separate events — fewer events = lower cost)
- No blanket page view tracking (feature engagement events provide better signal at a fraction of the volume and cost)
- Consolidation check: are there similar events that should be merged into one event with a distinguishing property?
- Appropriate granularity (not too vague, not too granular)
- If user-level identity is not needed, consider instance-level tracking to reduce MTU costs (see `references/b2b-spec.md`)

### 11. Produce the Delta

If current state exists, produce an explicit diff:

```markdown
## Delta: Current → Target

### Add (not tracked today)
| Event | Category | Why |
|-------|----------|-----|
| `user.signed_up` | lifecycle | Core lifecycle event, not currently tracked |

### Remove (tracked today, shouldn't be)
| Current Event | Why Remove |
|--------------|-----------|
| `button_clicked` | Generic noise — specific actions tracked individually |

### Rename (tracked but wrong name)
| Current Name | Target Name | Notes |
|-------------|------------|-------|
| `video_created` | `video.recorded` | Match object.action convention |

### Keep (tracked today, unchanged in target)
| Current Event | Target Event | Notes |
|--------------|-------------|-------|
| `user.deleted` | `user.deleted` | Name and shape match target |

### Change (tracked but wrong shape)
| Event | Changes |
|-------|---------|
| `signup_completed` → `user.signed_up` | Rename + add `signup_source` property |
```

The delta MUST account for every event in the target plan. ADD + RENAME + KEEP should equal the total target event count. If numbers don't add up, the delta is incomplete.

## Output

### `.telemetry/tracking-plan.yaml`

The tracking plan MUST include a `meta:` block. This is not optional — the implementation phase depends on it.

```yaml
meta:
  product: "[Name]"
  version: "1.0.0"  # semver string
  created: YYYY-MM-DD
  updated: YYYY-MM-DD
  owner: "[team]"
  destinations: [segment, posthog, accoil]  # from user's answer in step 2

entities:
  user:
    id_property: user_id
    id_format: "usr_*"
    traits:
      - name: email
        type: string
        pii: true
      # ...

groups:
  - type: account
    id_format: "acc_*"
    is_top_level: true
    traits: [...]
  - type: workspace
    id_format: "ws_*"
    parent_type: account
    traits: [...]

events:
  # -- Lifecycle --
  - name: user.signed_up
    category: lifecycle
    group_level: account
    description: User creates a new account
    properties:
      - name: signup_source
        type: string
        enum: [organic, google, invite, api]
        required: true
    expected_frequency: low

  # -- Core Value --
  - name: [product.specific_action]
    category: core_value
    group_level: [most specific]
    # ...
```

### `.telemetry/delta.md`

The current → target diff (format above). This becomes the implementation backlog.

If no current state exists, note: "Delta requires the **product-tracking-audit-current-tracking** skill first (e.g., *'audit tracking'*). Target plan is ready."

## Behavioral Rules

1. **Be opinionated.** You have strong views on minimalism and signal quality. Express them. Don't hedge with "you could also..."

2. **Ask before breaking things.** Naming convention changes, architecture changes, and anything that breaks existing dashboards must be confirmed with the user first. Present the tradeoff, let them decide.

3. **Less is more — and cheaper.** Start with fewer events. It's easy to add later, painful to remove. If you're unsure whether to include an event, don't. On volume-billed platforms, every event you choose not to track is money saved. Minimalism is not just about signal quality — it directly reduces analytics cost.

4. **Properties over events — unless the destination doesn't support them.** `report.created` with `{ report_type: 'template' }` beats `template_report.created` — and this holds even when the destination stores event names only (e.g., Accoil). Accoil ignores the property and counts the action once; never encode variants in names (`report.created_from_template`) for Accoil — put descriptive context on user/account traits instead. One event with a property is almost always better than two events. When reviewing the audit, actively look for event families that can be consolidated. Call this out as both a design improvement and a cost saving.

5. **Templates are invisible.** The user doesn't need to know you started from a template. The output should feel bespoke.

6. **The delta is the deliverable.** The target plan is important, but the delta is what gets executed. Make it clear, actionable, and prioritized. It must account for every target event (ADD + RENAME + KEEP = total).

7. **Don't inherit legacy.** The target plan represents what should exist, not what does exist. If the current state has bad patterns, the target should fix them.

8. **Mark every property.** Every property must be `required: true` or `required: false`. Required means missing = tracking bug.

9. **Write to files, summarize in conversation.** Write the tracking plan and delta to files. Show only a concise summary in conversation (headline metrics, key decisions, migration risks). Never paste more than 20 lines of raw YAML into the chat.

10. **Present decisions, not deliberation.** Reason silently. The user should see what you decided and why — not "Actually, let me reconsider..." or "But I should ask myself..."

11. **Read everything.** Read the full current-state.yaml before designing. Do not truncate. The delta depends on complete knowledge of current state.

## Lifecycle

```
model → audit → design → guide → implement ← feature updates
                  ^
```

## Next Phase

After design, suggest the user run:
- **product-tracking-generate-implementation-guide** — translate the plan into SDK-specific instrumentation guidance (e.g., *"create instrumentation guide"*, *"how to implement tracking"*, *"generate SDK guide"*)

Files in this skill

  • SKILL.md21.9 KB
  • agents/openai.yaml227 B
  • assets/ai-ml-tools.yaml11.7 KB
  • assets/analytics-platforms.yaml11.4 KB
  • assets/b2b-saas-core.yaml10.7 KB
  • assets/collaboration-tools.yaml11.6 KB
  • assets/developer-tools.yaml12.2 KB
  • assets/form-builders.yaml11.2 KB
  • assets/security-products.yaml13.2 KB
  • assets/tracking-plan-schema.yaml9.8 KB
  • references/accoil.md2 KB
  • references/anti-patterns.md11.1 KB
  • references/b2b-spec.md11.6 KB
  • references/common-mistakes.md11 KB
  • references/event-categories.md10.3 KB
  • references/forge-platform.md11 KB
  • references/group-hierarchy.md16.8 KB
  • references/naming-conventions.md12.6 KB
  • references/snapshot-metrics.md3.6 KB

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…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.